詳細解讀:遠程線程注入DLL到PC版微信


一、遠程線程注入的原理

  1、其基礎是在 Windows 系統中,每個 .exe 文件在雙擊打開時都會加載 kernel32.dll 這個系統模塊,該模塊中有一個 LoadLibrary() 函數,可以將DLL文件加載到自身進程中。

  2、這樣,就可以用 CreateRemoteThread() 函數創建一個遠程線程,讓目標進程調用LoadLibrary() 來加載我們自己寫的DLL 。CreateRemoteThread() 有這幾個參數比較關鍵:A:想要注入的進程的句柄,這里可以通過OpenProcess()得到; B:想要運行的函數,本例中當然是 LoadLibrary() 啦; C: 所運行函數的參數,本例中是自己寫的DLL的存放路徑。

  3、那么,怎么讓 LoadLibrary() 找到自己寫的DLL的存放路徑呢?這就需要在內存中開辟一塊空間,把路徑寫入進去。這要先用 VirtualAllocEx()開辟一塊空間,然后用WriteProcessMemory() 函數把DLL路徑寫進去。

  4、小結:總的來說,就是:先在目標進程的內存空間里開辟一塊新地方,往新地方里面寫入DLL的路徑,再創建遠程線程找到LoadLibrary() 函數,並在剛才開辟的新地方中讀取DLL路徑,進而加載我們自己寫的DLL。

二、代碼實現(含詳細注釋)

 1 #include <iostream>
 2 #include "stdlib.h"
 3 #include <tchar.h>
 4 #include <Windows.h>
 5 
 6 bool Inject(DWORD dwId, WCHAR* szPath)//參數1:目標進程PID 參數2:DLL路徑
 7 {  8     //一、在目標進程中申請一個空間
 9 
 10 
 11     /*
 12  【1.1 獲取目標進程句柄】  13  參數1:想要擁有的進程權限(本例為所有能獲得的權限)  14  參數2:表示所得到的進程句柄是否可以被繼承  15  參數3:被打開進程的PID  16  返回值:指定進程的句柄  17     */
 18     HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwId);  19 
 20 
 21     /*
 22  【1.2 在目標進程的內存里開辟空間】  23  參數1:目標進程句柄  24  參數2:保留頁面的內存地址,一般用NULL自動分配  25  參數3:欲分配的內存大小,字節單位  26  參數4:MEM_COMMIT:為特定的頁面區域分配內存中或磁盤的頁面文件中的物理存儲  27  參數5:PAGE_READWRITE 區域可被應用程序讀寫  28  返回值:執行成功就返回分配內存的首地址,不成功就是NULL  29     */
 30     LPVOID pRemoteAddress = VirtualAllocEx(  31  hProcess,  32  NULL,  33         1,  34  MEM_COMMIT,  35  PAGE_READWRITE  36  );  37 
 38     //二、 把dll的路徑寫入到目標進程的內存空間中
 39 
 40     DWORD dwWriteSize = 0;  41     /*
 42  【寫一段數據到剛才給指定進程所開辟的內存空間里】  43  參數1:OpenProcess返回的進程句柄  44  參數2:准備寫入的內存首地址  45  參數3:指向要寫的數據的指針(准備寫入的東西)  46  參數4:要寫入的字節數(東西的長度+0/)  47  參數5: 返回值。返回實際寫入的字節  48     */
 49     WriteProcessMemory(hProcess,pRemoteAddress, szPath, wcslen(szPath) * 2 + 2, &dwWriteSize);  50 
 51 
 52     //三、 創建一個遠程線程,讓目標進程調用LoadLibrary
 53 
 54     /*
 55  參數1:該遠程線程所屬進程的進程句柄  56  參數2:一個指向 SECURITY_ATTRIBUTES 結構的指針, 該結構指定了線程的安全屬性  57  參數3:線程棧初始大小,以字節為單位,如果該值設為0,那么使用系統默認大小  58  參數4:在遠程進程的地址空間中,該線程的線程函數的起始地址(也就是這個線程具體要干的活兒)  59  參數5:傳給線程函數的參數(剛才在內存里開辟的空間里面寫入的東西)  60  參數6:控制線程創建的標志。0(NULL)表示該線程在創建后立即運行  61  參數7:指向接收線程標識符的變量的指針。如果此參數為NULL,則不返回線程標識符  62  返回值:如果函數成功,則返回值是新線程的句柄。如果函數失敗,則返回值為NULL  63     */
 64     HANDLE hThread = CreateRemoteThread(  65  hProcess,  66  NULL,  67         0,  68  (LPTHREAD_START_ROUTINE)LoadLibrary,  69  pRemoteAddress,  70  NULL,  71  NULL  72  );  73     WaitForSingleObject(hThread, -1); //當句柄所指的線程有信號的時候,才會返回
 74     
 75     /*
 76  四、 【釋放申請的虛擬內存空間】  77  參數1:目標進程的句柄。該句柄必須擁有 PROCESS_VM_OPERATION 權限  78  參數2:指向要釋放的虛擬內存空間首地址的指針  79  參數3:虛擬內存空間的字節數  80  參數4:MEM_DECOMMIT僅標示內存空間不可用,內存頁還將存在。  81  MEM_RELEASE這種方式很徹底,完全回收。  82     */
 83     VirtualFreeEx(hProcess, pRemoteAddress, 1, MEM_DECOMMIT);  84     return 0;  85 }  86 
 87 
 88 int _tmain(int argc, _TCHAR * argv[])  89 {  90     wchar_t wStr[] = L"E:\\inject.dll";  91     DWORD dwId = 0;  92 
 93     //參數1:(NULL  94     //參數2:目標窗口的標題  95     //返回值:目標窗口的句柄
 96     HWND hCalc = FindWindow(NULL, L"微信");  97     printf("目標窗口的句柄為:%d\n", hCalc);  98 
 99     DWORD dwPid = 0; 100 
101     //參數1:目標進程的窗口句柄 102     //參數2:把目標進程的PID存放進去
103     DWORD dwRub = GetWindowThreadProcessId(hCalc, &dwPid); 104     printf("目標窗口的進程PID為:%d\n", dwPid); 105 
106     //參數1:目標進程的PID 107     //參數2:想要注入DLL的路徑
108  Inject(dwPid, wStr); 109 
110     return 0; 111 }

 

執行之后,DLL就注入到了PC版的微信進程。且該DLL中含有一個彈窗代碼,也出現在了PC版微信的界面之上。

 

 

附:測試用的DLL代碼

 1 #include <windows.h>
 2 
 3 
 4 DWORD WINAPI runBot(LPVOID lpParam) {  5     // 此處可以寫具體的bot代碼
 6     return 1;  7 }  8 
 9 
10 BOOL APIENTRY DllMain( HMODULE hModule, 11  DWORD ul_reason_for_call, 12  LPVOID lpReserved 13  ) 14 { 15     switch (ul_reason_for_call) 16  { 17     case DLL_PROCESS_ATTACH: 18         MessageBoxA(NULL, "DLL Attached!\n", "Game Hacking", MB_OK | MB_TOPMOST); 19         CreateThread(NULL, 0, &runBot, NULL, 0, NULL); 20         break; 21  } 22     return TRUE; 23 }

(以上例程均在 Windows 10 系統,VisualStudio 2019 環境中編譯通過)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM