远程注入的源码:
http://files.cnblogs.com/shadow-lei/Injector1.1.zip
//DLL注入到进程中,是当前游戏外挂常使用的一种作弊方式,因此在这里先和大家交流一下DLL的注入方法,在以后的文章中还会和大家讨论一下如何拦截: DLL的注入方法总结: 1.使用远程线程 2.hook的方式 一、 远程线程注入 1. 想要把自己的DLL注入到目标进程中,需要获取目标进程的句柄,因此,我们就需要提高我们自己注入工具的权限,否则获取不到目标进程的句柄,下面是提高权限的方法:
1 bool enableDebugPriv()
2 {
3 HANDLE hToken;
4 LUID sedebugnameValue;
5 TOKEN_PRIVILEGES tkp;
6
7 if (!OpenProcessToken(GetCurrentProcess(),
8 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
9 {
10 return false;
11 }
12 if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue))
13 {
14 CloseHandle(hToken);
15 return false;
16 }
17 tkp.PrivilegeCount = 1;
18 tkp.Privileges[0].Luid = sedebugnameValue;
19 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
20 if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL))
21 {
22 CloseHandle(hToken);
23 return false;
24 }
25 return true;
26 }
2. 获取目标进程句柄 OpenProcess(权限类型,是否可被持续,过程ID):功能:返回目标过程句柄 OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessID);
3. 在目标进程中分配内存,来存储我们要注入的DLL路径: VirtualAllocEx(hProcess, NULL, strlen(Path), PAGE_READWRITE);
//VirtualAllocEx()函数功能:为制订的过程分派虚拟地址 //参1:要分派的过程句柄 //参2:要分派的虚拟地址的地位,0默示,主动分派地位 //参3:分派的大小 //参4:MEM_COMMIT默示,分派物理内存或者页面内存,并且初始化内存为0 //参5:存储选项:PAGE_READWRITE默示可以在页面内存中 “读写” //返回值:若是分派内存成功,则返回分派内存的地址,若是分派失败则返回NULL,调用GetLastError()查看错误原因
4. 在目标进程中上面分配的内存中,写入DLL的路径: 4.1 WriteProcessMemory(hProcess, pszLibFileRemote, (PVOID)pszLibFile, strlen(Path), NULL)
//WriteProcessMemory()函数功能:在制订过程中写入内存 //参1:写入过程的句柄 //参2:写入内存的,必须是已经创建的地址,比如上方用VirtualAllocEx()在过程中创建的内存地址 //参3:写入内存中的数据内容的缓存 //参4:写入数据大小 //参5:一个选项,0默示忽视 //返回值: 非0值默示成功, 返回0则默示写入错误。调用GetLastError()查看错误原因
有时会读写失败,有可能是因为内存块的保护权限,因此需要修改内存块的保护权限,在写入成功之后,要还原刚才修改的权限 VirtualProtectEx(hProcess, pszLibFileRemote, strlen(Path), PAGE_EXECUTE_READWRITE, &dwOld); WriteProcessMemory(hProcess, pszLibFileRemote, Path, strlen(Path), NULL); VirtualProtectEx(hProcess, pszLibFileRemote, strlen(Path), dwOld, &dwOld); VirtualFreeEx(hProcess, pszLibFileRemote, strlen(Path), MEM_RELEASE);
5. 获取LoadLibrary()函数地址,因为要用他来动态加载DLL,该函数在kernel32.dll文件中 PROC AdrMyDllDir=(PROC)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryW"); //W代表UNICODE版本,说实话,A代表多字节字符集
6. 创建远程线程 CreateRemoteThread(hProcess,NULL, NULL, (LPTHREAD_START_ROUTINE)AdrMyDllDir(LPVOID)LoadString, NULL, NULL); 这里的AdrMyDllDir存放LoadLibraryW ,也就是说把LoadLibraryW当做线程处理惩罚函数,传入的参数bufRemote存放的是目标DLL文件的地址。
二、下面讲解一下如何用hook既钩子注入DLL文件。 所谓hook,既钩子。hook会在应用程序接到消息之前,阻碍应用程序的信息,比如鼠标键盘钩子会阻碍一个应用程序的鼠标键盘信息。要做盗号木马?用WH_KEYBOARD类型的hook 1.我们要跨过程应用钩子,要把hook函数写在DLL文件中。 2.在DLL文件中 设置钩子. 这里须要调用线程ID,threadId,我们会在面调用DLL的调用端中写入 hhookGetMsg=::SetWindowsHookEx(WH_GETMESSAGE,GetMessageHookProc,::GetModuleHandle(TEXT("dll.dll")),threadId); //参数1:钩子类型 //参数2:钩子处理函数 //参数3:钩子地点的模块 //参数4:钩子要阻碍的线程ID,若是要设置全局钩子,这里给0。 把这个SetWindowsHookEx()函数写在一个导出函数中: _declspec(dllexport) void SetHook(DWORD threadId) { hhookGetMsg=::SetWindowsHookEx(WH_GETMESSAGE,GetMessageHookProc,::GetModuleHandle(TEXT("dll.dll")),threadId); } SetHook()就是本dll的导出函数 3.在钩子处理函数中写入功能,当钩子截取到WM_NULL消息的,注入DLL文件。因为WM_NULL消息,是个没用的消息,应用程序一般不会收到这个消息,除非我们本身发送一个这个消息,所以我们在注入DLL的时,只要给要注入的应用程序发一个WM_NULL消息,当钩子截取到WM_NULL的时就注入钩子,就可以了。 LRESULT CALLBACK GetMessageHookProc(int nCode,WPARAM wParam,LPARAM lParam) { MSG* pMsg=(MSG*)lParam; if(WM_NULL==pMsg->message) ::LoadLibraryW(TEXT("D://MyDLL.dll")); } 编译DLL项目,产生DLL文件。
4.编写调用端,调用钩子 首先获取窗口句柄 HWND FindWindow( LPCTSTR lpClassName,LPCTSTR lpWindowName); 返回窗体句柄。hWnd. hWnd=FindWindow(0,要注入dll的窗体的名称(例如:记事本)) 通过hWnd,查找窗体线程ID threadId=GetWindowThreadProcessId(hWnd,0); 有了线程ID了,可以调用钩子了。 SetHook(threadId); 这时钩子已经加载到目标线程中了。 向目标窗体发送WM_NULL消息 SendMessage(hWnd,WM_NULL,0,0); 钩子会在目标窗体受到消息前受到WM_NULL消息。因为钩子处理函数中做了判断,当受到WM_NULL消息时,加载DLL文件。所以DLL文件就注入到目标线程中了。
|