本随笔记录通过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 ", (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 "); 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 "); 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 "); 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的第一个参数相同。
实现效果: