Win32,如何用C挂钩编译程序中的函数?
以此为例(在Ollydbg调试器中查看)
第一个PUSH EBP指令是void * f(int32_t n)的开始(idk它返回的内容,只是猜测void *),我知道输入参数n在堆栈中,而EBP 8是指向它的指针变量,我想它会是这样的 我想制作一个钩子,它将检查n是否高于7或低于0,如果是,则将其更改为1.使用ollydbg,直接编写汇编代码,我可以这样做: ,然后在0068BCCD,我可以编写汇编代码来检查EBP 8指向的int,并在必要时修改它: PUSHAD CMP DWORD PTR SS:[EBP+8],7 JA SHORT Error CMP DWORD PTR SS:[EBP+8],0 JL SHORT Error JMP SHORT Finished Error: PUSHAD PUSH OFFSET TheString CALL Onlink-x86.App::Output ADD ESP,4 POPAD MOV DWORD PTR SS:[EBP+8],1 Finished: POPAD JMP LONG 00447493 TheString: "Warning: label assertion failed,but (pretending its 1 and) trying to ignore.."+0x00 哪个(如果我没有搞砸)基本上相当于 void FilterIntAtEBP_8(){ int i=*(int*)(uint32_t(EBP)+8); if(i>7 || i<0){ Output("Warning: label assertion failed,but (pretending its 1 and) trying to ignore.."); *(int*)(uint32_t(EBP)+8)=1; } return; } 最后,问题是:如何使用Ollydbg,而不是使用C? (我看到了一个源代码回来,一个MMORPG作弊程序,挂钩客户端,执行此操作,但代码丢失给我)
首先,您需要在目标进程中注入一个dll.为此,您可以使用以下代码:
Injector.h #ifndef INJECTOR_H_INCLUDED #define INJECTOR_H_INCLUDED #include <Windows.h> #include <string> class Injector { public: /** * Loads a DLL into the remote process * @Return true on sucess,false on failure */ bool InjectDll(DWORD processId,std::string dllPath); private: }; #endif // INJECTOR_H_INCLUDED Injector.cpp #include "Injector.h" bool Injector::InjectDll(DWORD processId,std::string dllPath) { HANDLE hThread,hProcess; void* pLibRemote = 0; // the address (in the remote process) where szLibPath will be copied to; HMODULE hKernel32 = GetModuleHandle("Kernel32"); HINSTANCE hInst = GetModuleHandle(NULL); char DllFullPathName[_MAX_PATH]; GetFullPathName(dllPath.c_str(),_MAX_PATH,DllFullPathName,NULL); // Get process handle hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,processId); // copy file path in szLibPath char szLibPath[_MAX_PATH]; strcpy_s(szLibPath,DllFullPathName); // 1. Allocate memory in the remote process for szLibPath pLibRemote = VirtualAllocEx( hProcess,NULL,sizeof(szLibPath),MEM_COMMIT,PAGE_READWRITE ); if (pLibRemote == NULL) { // probably because you don't have administrator's right return false; } // 2. Write szLibPath to the allocated memory WriteProcessMemory(hProcess,pLibRemote,(void*)szLibPath,NULL); // 3. Force remote process to load dll hThread = CreateRemoteThread(hProcess,(LPTHREAD_START_ROUTINE) GetProcAddress(hKernel32,"LoadLibraryA"),NULL); if (hThread == NULL) { return false; } return true; } main.cpp中 #include "Injector.h" int main() { Injector injector; DWORD processId = 1653; // change the process id here. if (injector.InjectDll(processId,"injected.dll")) { printf("Good job,you injected the dlln"); } else { printf("Something wrong happenedn"); } while (true); } 然后你必须做你的DLL.这是它变得更复杂的地方.首先一些包括: injected.dll #include <Windows.h> #include <stdio.h> 然后我们需要创建一个绕过正确位置的函数: void DetourAddress(void* funcPtr,void* hook,BYTE* mem) { BYTE cmd[5] = { 0xE9,0x00,0x00 }; // jump place holder void* RVAaddr = (void*)((DWORD)funcPtr + (DWORD)GetModuleHandle(NULL)); // base + relative address // make memory readable/writable DWORD dwProtect; VirtualProtect(RVAaddr,5,PAGE_EXECUTE_READWRITE,&dwProtect); // read memory ReadProcessMemory(GetCurrentProcess(),(LPVOID)RVAaddr,&mem[2],NULL); // write jmp in cmd DWORD offset = ((DWORD)hook - (DWORD)RVAaddr - 5); // (dest address) - (source address) - (jmp size) memcpy(&cmd[1],&offset,4); // write address into jmp WriteProcessMemory(GetCurrentProcess(),cmd,0); // write jmp // write mem VirtualProtect(mem,13,&dwProtect); void* returnAdress = (void*)((DWORD)RVAaddr + 5); memcpy(&mem[8],&returnAdress,4); // write return address into mem // reprotect VirtualProtect(RVAaddr,dwProtect,NULL); } 如果您需要在某个时候删除您的DLL,则需要恢复代码: void PatchAddress(void* funcPtr,BYTE* mem) { void* RVAaddr = (void*)((DWORD)funcPtr + (DWORD)GetModuleHandle(NULL)); // base + relative address // make memory readable/writable DWORD dwProtect; VirtualProtect(funcPtr,&dwProtect); WriteProcessMemory(GetCurrentProcess(),NULL); // write jmp VirtualProtect(RVAaddr,NULL); } 接下来,我们需要从绕行的字节中创建一个函数,以便程序执行它们,这样它就不会受到绕行的影响.在全球空间中添加: // memory (0x5E = pop esi,0x68 = push DWORD,0xC3 = RETN) BYTE detourMem[13] = { 0x5E,0x5E,0x0,0x68,0xC3 }; // Convert bytes array to function typedef void ( * pFunc)(); pFunc funcMem = (pFunc) &detourMem; // I also added a variable as an example of what you can do with it. DWORD var = 0; 之后,您需要绕行功能: _declspec(naked) void DetourFunction() { // we need to push all flag and registers on the stack so we don't modify them by accident __asm { PUSHFD PUSHAD // You can do "whatever" you want here in assembly code // ex,put eax value into var: mov var,eax } printf("this code is executed everytime the detoured function is calledn"); // Do whatever you want in c++ here if (var < 7) { // eax was smaller than 7 } // We pop every flags and registers we first pushed so that the program continue as it was supposed to __asm { // we set everything back to normal POPAD POPFD push esi // we call our funcMem mov edx,funcMem; call edx } } 最后,这是你的DLLMain的样子: BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved ) { DWORD detouredAddress = 0x689B; // add the RELATIVE ADDRESS of the location you want to detour FILE *stream; switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: // Only add this if you want a console to appears when you inject your dll (don't forget FreeConsole when you remove the dll) AllocConsole(); freopen_s(&stream,"CONOUT$","w",stdout); // If you need to know the base address of the process your injected: printf("base address: 0x%Xn",(DWORD)GetModuleHandle(NULL)); // Our detour function DetourAddress((void*)detouredAddress,(void*)&DetourFunction,detourMem); break; case DLL_PROCESS_DETACH: // We restore the process to have what it was before it was injected PatchAddress((void*)detouredAddress,detourMem); FreeConsole(); break; } return true; } 我明白这一切都很多,所以如果你有任何问题请不要犹豫! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- Server 2012 hyper-v3实时迁移
- 最新Microsoft Edge!使用chromium内核
- 在Windows系统上移动文件的最快方式
- 外语Windows安装和语言包之间有区别吗?
- windows – 指定NVCC用于编译主机代码的编译器
- windows – 如何让for循环使用逗号分隔的字符串?
- 重新安装前最好的免费工具来映像Windows XP驱动器?
- win10家庭版升级到win10专业版和工作站版本的最新方法和密钥
- windows-runtime – WinRt. UnhandledException处理程序. S
- winapi – 如何使用嵌入作为资源的清单? (Windows XP / Vi
- windows – Window的命令行(cmd.exe)命令的最大长
- windows-server-2008-r2 – 为什么我的Server 20
- windows-runtime – Windows Phone 8.1中的Image
- Windows Server 2012域控制器具有不同网络配置文
- <Windows> git的使用
- 我正在寻找适用于Windows的Python 2.7的gevent
- windows – NSIS自动和静默更新
- 组策略 – 是否可以通过GPO禁用MS Office受保护的
- windows – Docker-compose无效的bind mount spe
- 我可以使用带有Windows域身份验证的html5 Websoc