Winapi钩子通过mhook导致程序崩溃或挂起

Winapi hook via mhook causes program crash or hang

本文关键字:程序 崩溃 挂起 mhook Winapi      更新时间:2023-10-16

我试图通过mhook钩StartDocW拦截打印。我使用appinit_dll来加载我的库。

DLL代码很简单:

#include <windows.h>
#include "mhook/mhook-lib/mhook.h"
using StartDocPtr = int(*)(HDC, const DOCINFO*);
StartDocPtr orig;
int HookedStartDocW(HDC hdc, const DOCINFO* lpdi) {
    return orig(hdc, lpdi);
}
BOOL WINAPI DllMain(__in HINSTANCE, __in DWORD Reason, __in LPVOID) {
    orig = (StartDocPtr)GetProcAddress(GetModuleHandle("gdi32"), "StartDocW");
    switch (Reason)
    {
    case DLL_PROCESS_ATTACH:
        Mhook_SetHook((PVOID*)&orig, &HookedStartDocW);
        break;
    case DLL_PROCESS_DETACH:
        Mhook_Unhook((PVOID*)&orig);
        break;
    }
}

钩子正在工作,打印已经完成。但如果我改变HookStartDocW如下:

int HookedStartDocW(HDC hdc, const DOCINFO* lpdi) {
    char buf[40];
    GetModuleFileName(NULL, buf, 40);
    return orig(hdc, lpdi);
}

正在打印的程序将立即崩溃。即使我只是离开char buf[40]和评论GetModuleHandle -程序将挂起。为什么会发生这种情况?

此外,如果程序崩溃挂在打印上(如果我添加return orig(hdc, lpdi)以外的任何东西)- PC开始表现得非常奇怪,拒绝运行程序等。如果我重新启动它——Windows只是在引导屏幕上无休止地旋转,使它恢复活动的唯一方法是通过liveCD引导并重命名/删除我的钩子DLL。

打印程序:Excel 2016,记事本。

编译器- MSVC 2015, x64版本DLL编译,使用MBCS代替unicode。

你的钩子声明错误。

查看Wingdi.hStartDocW()的实际声明:

__gdi_entry WINGDIAPI int WINAPI StartDocW(__in HDC hdc, __in CONST DOCINFOW *lpdi);

可以忽略__gdi_entryWINGDIAPI简单地解析为__declspec(dllimport)。在此声明中重要的是WINAPI .

几乎所有的 Win32 API函数一样,StartDocW()使用__stdcall调用约定。WINAPI宏解析为__stdcall

你的代码根本没有指定任何调用约定,所以它使用编译器的默认值,通常是__cdecl。因此,您对调用堆栈管理不当。这就是你的代码崩溃的原因。

当你应该使用DOCINFOW时,你也在使用DOCINFO。在您的代码中很明显,您正在为MBCS而不是UNICODE编译,因此DOCINFO映射到DOCINFOA。你不能将DOCINFOA传递给StartDocW(),它期望的是DOCINFOW

你需要修改你的声明,例如:

#include <windows.h>
#include "mhook/mhook-lib/mhook.h"
using StartDocPtr = int (WINAPI *)(HDC, const DOCINFOW*);
StartDocPtr orig = nullptr;
int WINAPI HookedStartDocW(HDC hdc, const DOCINFOW* lpdi) {
    //...
    return orig(hdc, lpdi);
}
BOOL WINAPI DllMain(__in HINSTANCE, __in DWORD Reason, __in LPVOID) {
    orig = (StartDocPtr) GetProcAddress(GetModuleHandle(TEXT("gdi32")), "StartDocW");
    switch (Reason)
    {
    case DLL_PROCESS_ATTACH:
        Mhook_SetHook((PVOID*)&orig, &HookedStartDocW);
        break;
    case DLL_PROCESS_DETACH:
        Mhook_Unhook((PVOID*)&orig);
        break;
    }
}