Cheat Engine汇编转C++ DLL实现游戏自动化运行崩溃问题求助
问题根因与修复方案
核心崩溃原因
1. 注入逻辑存在致命错误
你当前的注入流程完全错误:你在自己的Main.exe进程内加载DLL拿到的ClickID地址,是仅属于你本地进程地址空间的函数地址,直接把这个地址传给游戏进程的远程线程执行,游戏进程的地址空间内不存在对应代码,必然触发内存访问违规崩溃。
2. DLL内汇编代码栈不平衡
你在汇编代码开头主动push了esi、eax寄存器,但执行完逻辑后没有弹出恢复,函数返回时栈帧不匹配,也会导致游戏崩溃。
3. 额外注意
必须保证你的DLL、注入程序的编译位数和游戏完全一致,游戏是32位就编译x86版本,是64位就编译x64版本,位数不匹配也会直接崩溃。
修复方案
步骤1:修正注入逻辑,使用标准远程DLL注入流程
正确的注入逻辑是让游戏进程先调用系统LoadLibraryA加载你的DLL,系统会自动把DLL映射到游戏的地址空间:
auto h_process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); if (!h_process) return; const char dll_path[] = "D:\\project\\DivHook\\divhook\\Debug\\divlib.dll"; size_t path_len = strlen(dll_path) + 1; // 在游戏进程分配内存存储DLL路径 LPVOID remote_mem = VirtualAllocEx(h_process, NULL, path_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (!remote_mem) { CloseHandle(h_process); return; } // 写入DLL路径到游戏内存 WriteProcessMemory(h_process, remote_mem, dll_path, path_len, NULL); // 系统kernel32.dll的地址在所有进程中一致,直接取本地的LoadLibraryA地址即可 LPVOID load_lib_addr = (LPVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA"); // 创建远程线程加载DLL HANDLE remote_thread = CreateRemoteThread(h_process, NULL, 0, (LPTHREAD_START_ROUTINE)load_lib_addr, remote_mem, 0, NULL); if (remote_thread) { WaitForSingleObject(remote_thread, INFINITE); // 等待DLL加载完成 CloseHandle(remote_thread); } // 清理资源 VirtualFreeEx(h_process, remote_mem, 0, MEM_RELEASE); CloseHandle(h_process);
步骤2:修正DLL内的汇编代码
修复栈不平衡问题,也可以直接对齐CE的汇编写法减少出错:
// 修复后的汇编写法,恢复被保存的寄存器 void ClickID() { _asm { push esi; push eax; mov esi, 0x014656DC; mov eax, 0x00633940; push esi; call eax; add esp, 0x04; pop eax; // 按push逆序恢复寄存器 pop esi; } } // 更稳妥的写法,完全和CE的汇编对齐,不需要额外保存无关寄存器 /* void ClickID() { _asm { push 0x014656DC; call 0x00633940; add esp, 0x04; } } */
步骤3:添加DLL自动执行逻辑
在DLL的DllMain中添加代码,DLL加载后自动开线程执行逻辑(不要直接在DLL_PROCESS_ATTACH里调用函数,避免加载死锁):
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ClickID, NULL, 0, NULL); break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }
内容的提问来源于stack exchange,提问作者Divide
相关产品推荐
相关产品推荐

