1. 程式人生 > >遠端執行緒注入

遠端執行緒注入

在win32程序中,每個程序都有自己獨立的4GB地址空間,各個程序之間相互不影響,win32API中提供能夠了2個函式,writeProcessMemory和readProcessMemory,這兩個函式可以在指定程序的記憶體中進行讀寫操作。

HANDLE CreateRemoteThread(

     HANDLE hProcess,

     LPSECURITY_ATTRIBUTES lpThreadAttributes,

     SIZE_T dwStackSize,

     LPTHREAD_START_ROUTINE lpStartAddress,

     LPVOID lpParameter,

     DWORD dwCreationFlags,

     LPDWORD lpThreadId

);

引數說明:

hProcess:目標程序的控制代碼

lpThreadAttributes:指向執行緒的安全描述結構體的指標,一般設定為NULL,表示使用預設的安全級別

dwStackSize:執行緒堆疊大小,一般設定為0,表示使用預設的大小,一般為1M

lpStartAddress:執行緒函式的地址

lpParameter:執行緒引數

dwCreationFlags:執行緒的建立方式

                  CREATE_SUSPENDED 執行緒以掛起方式建立

lpThreadId:輸出引數,記錄建立的遠端執行緒的ID

 

CreateRemoteThread函式可以在指定程序中建立執行緒,但是執行緒的入口函式必須在目標程序中,那麼我們如何在目標程序中寫入我們的程式碼。通常就是在目標程序中寫入 LoadLiraryA ,讓其來載入我們的 DLL 檔案(我們在目標程序中寫入的程式碼)。DllMain 函式就開始運行了,通常也是在 DllMain 中建立一個執行緒,用 CreateThread ,記住,這個執行緒是在目標程序中建立的了,因為這個 DLL 檔案已經被載入到了目標程序中,這就叫做遠端執行緒注入。首先用 VirtualAllocEx 來在目標程序中分配一個記憶體空間,然後再在這個空間中把 DLL 的路徑名寫到目標程序中,然後建立遠執行緒,把這個空間的地址傳給LoadLibraryA ,因為這樣 DLL 的路徑名就在目標程序裡了,LoadLibraryA 也就可以正確載入 DLL 了,然後 DLL 就可以響應 DLL_PROCESS_ATTACH,然後就可以建立執行緒了,然後那個 EXE 就可以退出了,只要被注入的程序不退出,那麼 DLL 檔案將一直執行。

 

typedef struct tagPROCESSENTRY32

{

    DWORD dwSize; //sizeof(tagPROCESSENTRY32)

    DWORD cntUsage; //程序的引用計數,未使用,設定為0

    DWORD th32ProcessID; //程序ID

    ULONG_PTR th32DefaultHeapID; //程序預設堆ID,未使用,設定為0

    DWORD th32ModuleID; //程序模組ID, 未使用,設定為0

    DWORD cntThreads; //程序開啟的執行緒計數

    DWORD th32ParentProcessID; //父程序ID

    LONG pcPriClassBase;

    DWORD dwFlags;

    TCHAR szExeFile[MAX_PATH]; //程序的可執行檔名稱,非完整路徑

} PROCESSENTRY32, *PPROCESSENTRY32;

 

0.可以通過程序快照資訊,遍歷程序快照,通過程序名稱,找到需要注入的程序ID。

CreateToolhelp32Snapshot(TH32CS_SNAPPPROCESS, 0);

 

1.獲取想要注入程序的控制代碼

Handle handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);

 

2.計算DLL路徑名需要的位元組數.在遠端執行緒中為路徑名分配空間.

cch = 1 + lstrlen(lpszLibName);

pszLibFileRemote = (PSTR)VirtualAllocEx

(hProcess, NULL, cch, MEM_COMMIT, PAGE_READWRITE);

 

3.將DLL的路徑名複製到遠端程序的記憶體空間.

WriteProcessMemory(hProcess, (PVOID)pszLibFileRemote, (PVOID)lpszLibName, cch, NULL)) 

 

4.獲得LoadLibraryA在Kernel32.dll中的真正地址. 

pfnThreadRtn = (PTHREAD_START_ROUTINE)GetProcAddress(

GetModuleHandle(TEXT("Kernel32")),

TEXT("LoadLibraryA"));

 

5.建立遠端執行緒,並通過遠端執行緒呼叫使用者的DLL檔案. 

hThread = CreateRemoteThread(hProcess, NULL, 0, pfnThreadRtn, 

(PVOID)pszLibFileRemote, 0, NULL);

 

6.等待遠端執行緒終止.

WaitForSingleObject(hThread, INFINITE);

 

7.關閉控制代碼. 

if (pszLibFileRemote != NULL) 

VirtualFreeEx(hProcess, (PVOID)pszLibFileRemote, 0, MEM_RELEASE);

if (hThread  != NULL) 

CloseHandle(hThread);

if (hProcess != NULL) 

CloseHandle(hProcess);