本隨筆記錄通過win32api學習進程間通信和dll注入外掛原理的學習過程
基本思路:
- 通過dll注入的方式將代碼加載進目標進程
- 通過共享內存的方式進行數據通信(共享物理頁)
- 通過循環讀取命令隊列,並通過內聯匯編的方式調用各種函數
准備/具體實現:
1.獲取進程PID:
說明通過函數去實現,這樣就不需要每次都修改再編譯。【之前沒有詳細寫過這塊,所以這邊會詳細的寫一下】
重要頭文件:#include <tlhelp32.h>
原理:通過CreateToolhelp32Snapshot()函數捕捉即時的操作系統進程快照,再遍歷找出需要使用的進程。
重要結構體:PROCESSENTRY32結構體
具體代碼實現如下(函數參數為可執行文件名而不是窗口名):
1 DWORD GetPid(char* szName){ 2 HANDLE hprocessSnap = NULL; 3 PROCESSENTRY32 pe32 = {0}; 4 hprocessSnap = CreateToolhelp32Snapshot( 5 TH32CS_SNAPPROCESS, 6 0);//捕捉所有進程的快照 7 if (hprocessSnap == INVALID_HANDLE_VALUE){ 8 //快照失敗 9 return 0; 10 } 11 //初始化pe32結構體 12 pe32.dwSize = sizeof(PROCESSENTRY32); 13 if (Process32First(hprocessSnap, &pe32)){ 14 do{ 15 if (!strcmp(szName, pe32.szExeFile)){ 16 printf("Process Found, PID: %d \n", (int)pe32.th32ProcessID); 17 return (int)pe32.th32ProcessID; 18 } 19 //遍歷查找進程名 20 }while (Process32Next(hprocessSnap, &pe32)); 21 }else{ 22 CloseHandle(hprocessSnap); 23 } 24 return 0; 25 }
2.共享內存的實現(共享物理頁):
這里主要就是那幾個api函數以及原理,直接貼關鍵代碼了。
執行注入程序的代碼:
1 //創建一塊共享內存物理頁 2 HANDLE hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,0x1000,"外掛"); 3 DWORD dwtype = 0; 4 if (hMapFile == NULL){ 5 printf("CreateFileMapping Error \n"); 6 } 7 //映射內存 8 LPTSTR lpBuff = (LPTSTR)MapViewOfFile(hMapFile, 9 FILE_MAP_ALL_ACCESS, 10 0,0,BUFSIZ); 11 if (lpBuff == NULL){ 12 printf("MapViewOfFile error \n"); 13 exit(0); 14 }
被注入的dll的代碼:
1 //共享內存映射 2 HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "外掛"); 3 DWORD dwtype = 0; 4 if (hMapFile == NULL){ 5 printf("OpenFileMapping Error \n"); 6 } 7 //映射內存 8 LPTSTR lpBuff = (LPTSTR)MapViewOfFile(hMapFile, 9 FILE_MAP_ALL_ACCESS, 10 0,0,BUFSIZ);
關鍵的api函數:CreateFileMapping/OpenFileMapping/MapViewOfFile
之后通過CopyMemory的方式進行共享內存的讀寫。
3.dll注入:
dll注入的內容在上一篇隨筆中已經有了詳細的記錄,此處不再贅述。
鏈接:https://www.cnblogs.com/Mz1-rc/p/13671844.html
4.內聯匯編調用各種函數:
先通過調試器找到所有函數的地址,再通過dll去調用。
例:
1 #define ATTACK 0x00401014 2 __asm{ 3 mov eax,ATTACK 4 call eax 5 }
5.將dll釋放
由執行注入的線程對目標線程中的dll創建的線程傳遞信號,dll通過執行FreeLibraryAndExitThread()函數釋放自身。
FreeLibraryAndExitThread((HMODULE)g_hModule, 0); //g_hModule與傳入DllMain的第一個參數相同。
實現效果:

