使用MS Detours挂钩MessageBoxA时程序崩溃问题求助
解决你的Detours挂钩MessageBoxA的两个问题
先看你的两个问题,都是典型的挂钩实现细节没处理好导致的,咱们一个个来解决:
问题1:Debug模式下ESP栈平衡错误
这个错误提示已经说得很明确了——调用约定不匹配。你看代码里:
- 你定义的
MBA函数指针用了WINAPI(也就是stdcall,这是Windows API的标准调用约定) - 但你的
HookedMessageBoxA函数却没加WINAPI修饰,默认是cdecl调用约定
两种调用约定对栈的处理方式完全不同:stdcall是被调用者清理栈,cdecl是调用者清理栈,Debug模式下VC++会严格检查ESP的值,所以触发了Run-Time Check Failure #0。
修复方法:给HookedMessageBoxA加上WINAPI修饰,让它的调用约定和原函数一致:
int WINAPI HookedMessageBoxA( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType ) { return originalMBA(NULL, "HOOKED", "HOOKED", MB_OK); }
问题2:Release模式卸载DLL后访问违规
这个问题是因为你卸载DLL的时候,没有解除对MessageBoxA的挂钩。当DLL被FreeLibrary卸载后,原来通过DetourAttach设置的跳转指令还指向DLL内存里的HookedMessageBoxA函数,但这块内存已经被系统回收了,所以再次调用MessageBoxA就会触发访问违规。
修复方法:在DllMain的DLL_PROCESS_DETACH分支里,添加解除挂钩的逻辑,和挂钩的步骤对称:
BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID lpReserved ) { if (reason == DLL_PROCESS_ATTACH) { DetourRestoreAfterWith(); DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); originalMBA = (MBA)DetourFindFunction("user32.dll", "MessageBoxA"); DetourAttach(&(PVOID&)originalMBA, (PVOID)HookedMessageBoxA); DetourTransactionCommit(); } else if (reason == DLL_PROCESS_DETACH) { // 解除挂钩的步骤 if (originalMBA != NULL) { DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourDetach(&(PVOID&)originalMBA, (PVOID)HookedMessageBoxA); DetourTransactionCommit(); originalMBA = NULL; } } return TRUE; }
额外注意事项
- 确保你链接了Detours的对应库文件(Debug模式用
detoured.lib+detours.lib,Release模式用Release版本的库),否则可能出现隐式链接错误。 DllMain里尽量避免复杂操作,但Detours的事务操作是安全的,它本身就是为DLL注入场景设计的。- 如果你在卸载DLL之后还要调用MessageBoxA,一定要确保挂钩已经完全解除,上面的代码在DETACH时执行解除操作,就能彻底避免访问违规。
现在把这两个修复点加上,再重新编译测试,应该就能解决你的问题了。
内容的提问来源于stack exchange,提问作者Elyasaf755
相关产品推荐
相关产品推荐

