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

Windows API钩子实现异常:Hook后未触发目标消息框求助

Windows API钩子异常问题排查与修复

问题核心分析

你的代码存在两个致命错误,直接导致钩子安装后程序崩溃:

  1. 相对偏移量计算错误:rOffset = (DWORD *)(dst-src); 这行把偏移量数值强制转成指针,后续复制的是指针地址而非偏移量本身,生成的跳转指令地址完全非法,触发内存访问违规。
  2. 未修改内存页保护属性:DLL代码段默认是只读+执行权限,直接调用WriteProcessMemory写入会触发系统内存保护机制,导致程序直接终止。

修复后的完整钩子代码

#include <windows.h>

// 全局变量:保存原始指令字节与被Hook函数地址
BYTE originalBytes[5] = {0};
LPVOID hookedAddress = nullptr;

// 定义被Hook函数的类型
typedef void (*CatFunc)(const char*);
CatFunc catFunc = nullptr;

// Hook触发后的自定义函数
void myFunc(const char* msg) {
    MessageBoxA(NULL, "Hook触发!", "提示", MB_OK);
    
    // 恢复原始指令,调用原函数
    WriteProcessMemory(GetCurrentProcess(), hookedAddress, originalBytes, 5, NULL);
    catFunc(msg);
    
    // 重新安装Hook,保证后续调用仍能触发
    setMySuperHook();
}

void setMySuperHook() {
    HINSTANCE hLib;
    VOID* myFuncAddress;
    DWORD rOffset;
    DWORD src;
    DWORD dst;
    BYTE patch[5] = {0};

    // 第一次调用时初始化函数地址与原始指令
    if (!hookedAddress) {
        hLib = LoadLibraryA("pet.dll");
        hookedAddress = GetProcAddress(hLib, "Cat");
        catFunc = (CatFunc)hookedAddress;
        ReadProcessMemory(GetCurrentProcess(), hookedAddress, originalBytes, 5, NULL);
    }

    myFuncAddress = &myFunc;

    // 计算E9跳转的相对偏移:目标地址 - (源地址 + 5)
    src = (DWORD)hookedAddress + 5;
    dst = (DWORD)myFuncAddress;
    rOffset = dst - src;

    // 构造跳转指令:0xE9是相对跳转操作码,后面跟4字节偏移
    patch[0] = 0xE9;
    memcpy(patch + 1, &rOffset, 4);

    // 修改内存页权限为可写,避免写入失败
    DWORD oldProtect;
    VirtualProtect(hookedAddress, 5, PAGE_EXECUTE_READWRITE, &oldProtect);

    // 写入跳转指令
    WriteProcessMemory(GetCurrentProcess(), hookedAddress, patch, 5, NULL);

    // 恢复内存页原权限
    VirtualProtect(hookedAddress, 5, oldProtect, &oldProtect);
}

int main() {
    // 加载DLL并获取原始函数地址
    HINSTANCE hLib = LoadLibraryA("pet.dll");
    catFunc = (CatFunc)GetProcAddress(hLib, "Cat");

    // 调用原始Cat函数
    catFunc("meow-meow");

    // 安装Hook
    setMySuperHook();

    // 调用Hook后的Cat函数
    catFunc("meow-meow");

    FreeLibrary(hLib);
    return 0;
}

关键修复点说明

  • 偏移量计算修正:直接用rOffset = dst - src;计算合法的相对偏移,将数值本身复制到跳转指令中,而非指针地址。
  • 内存权限处理:通过VirtualProtect临时修改目标内存页为可写,写入完成后恢复原权限,绕过系统内存保护。
  • Hook生命周期维护:在自定义函数中先恢复原始指令调用原函数,再重新安装Hook,确保后续调用仍能触发钩子逻辑。

x64dbg调试查错步骤

  1. 附加进程:打开x64dbg,点击File->Attach选择你的程序进程。
  2. 设置断点:在命令框输入bp pet.dll!Cat,回车设置Cat函数的断点。
  3. 运行追踪:点击Run按钮,程序会在调用Cat函数时暂停,查看函数开头的5字节内容,确认是否写入了0xE9开头的跳转指令。
  4. 崩溃定位:若程序崩溃,x64dbg会自动暂停,查看Call Stack窗口可定位崩溃位置,检查内存地址是否合法、指令是否被正确写入。

常见疑问解答

  • 为什么用5字节?:x86架构下E9相对跳转指令是1字节操作码+4字节偏移,刚好覆盖多数函数开头的单字节指令(如push ebp),基础场景下足够使用。
  • 为何之前正常现在异常?:可能是编译环境切换(Debug/Release)、DLL文件更新导致函数开头指令变化,或是系统内存保护机制触发条件改变。

内容的提问来源于stack exchange,提问作者movies netflix

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 20:52:37