You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 08:06:03