MinHook Hook Windows API 需严格匹配位数、调用约定与运行时,正确编译库、声明函数指针、注入DLL并按序卸载,否则易崩溃或失效。

MinHook 能直接 Hook 任意 Windows API,但必须确保位数匹配、内存可写、调用约定一致——否则进程大概率崩溃或 Hook 失效。
编译 MinHook 库时选对平台和运行时
MinHook 不提供预编译的通用二进制,必须自己按目标进程架构编译。x86 进程只能用 lib/MinHook.x86.lib,x64 进程必须用 lib/MinHook.x64.lib,混用会触发 STATUS_ACCESS_VIOLATION 或静默失败。
- VS 中新建 DLL 项目后,在「属性 → 配置属性 → 常规 → 平台工具集」选与目标进程一致的版本(如 v143),避免 MSVC 版本错配导致
MH_Initialize返回MH_ERROR_MEMORY_ALLOC - 「C/C++ → 代码生成 → 运行时库」必须设为
/MT(多线程静态链接),不能用/MD;否则注入后目标进程可能因 CRT 冲突崩溃 - 头文件路径要加到「附加包含目录」:
include/;库路径加到「附加库目录」:lib/
Hook 前必须正确声明原函数指针类型
函数签名不匹配是 Hook 后立即崩溃的最常见原因,尤其在 x64 下:Windows API 默认用 WINAPI(即 __stdcall),但 x64 实际统一使用 __fastcall 调用约定,编译器会忽略 WINAPI 标记——所以你声明的指针类型必须和真实 ABI 一致,否则栈被破坏。
- 查 MSDN 确认目标函数真实签名,例如
CreateFileW返回HANDLE,参数共 7 个,最后一个为LPCWSTR,不能漏掉const修饰 - 原函数指针必须用
typedef显式声明,且与 DLL 导出符号完全对齐:typedef HANDLE (WINAPI* pfnCreateFileW)(LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE); - 不要用
auto或函数指针模板推导,MinHook 的MH_CreateHook第三个参数要求void**,类型擦除后无法校验调用约定
启用 Hook 必须在目标进程上下文中执行
MinHook 本身不负责注入,MH_EnableHook 只修改当前进程地址空间里的指令。想 Hook 其他进程,必须先把你的 DLL 注入进去,再在它的 DLL_PROCESS_ATTACH 里调用初始化和启用逻辑——否则所有操作都只在你自己的进程里生效,对目标毫无影响。
立即学习“C++免费学习笔记(深入)”;
- 远程注入推荐用
CreateRemoteThread + LoadLibrary,别用 APC 注入(x64 下QueueUserAPC在非调试进程里常被忽略) - 注入后等待几毫秒再调用
MH_Initialize,防止目标进程 DLL 还没加载完(比如 Hookws2_32.dll的send,得等网络模块初始化完成) - 若目标启用了 CFG(Control Flow Guard),需提前用
SetProcessValidCallTarget注册跳板地址,否则MH_EnableHook可能成功但首次调用就触发异常
卸载 Hook 时顺序和时机很关键
卸载不是简单调用 MH_DisableHook 就完事。如果目标线程正卡在被 Hook 的函数内部(比如 recv 阻塞中),此时禁用会导致跳转指令残留,后续调用直接飞到野地址。
- 先用
MH_DisableHook禁用,再用MH_RemoveHook移除钩子定义,最后MH_Uninitialize清理全局状态——三步缺一不可 - 卸载必须在
DLL_PROCESS_DETACH中做,且确保没有线程仍在执行你的MySend回调函数(可用InterlockedDecrement计数保护) - 若目标进程是 GUI 程序,
DLL_PROCESS_DETACH可能被延迟触发,建议在 Hook 函数里加超时检测,避免长期持有锁或资源
真正难的从来不是写几行 MH_CreateHook,而是确认目标进程的位数、调用栈深度、内存页属性、CFG 状态、以及它是否正在执行被 Hook 的函数——这些信息不会报错,但会让 Hook 表面成功、实际失效。


















