通过 mhook 的 Winapi hook 导致程序崩溃或挂起
Winapi hook via mhook causes program crash or hang
我正在尝试挂钩 StartDocW to intercept printing via mhook。我使用 AppInit_DLLs 加载我的库。
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
- 程序也会挂起。为什么会这样?
此外,如果程序 crashes\hangs 正在打印(如果我添加 return orig(hdc, lpdi)
之外的任何内容)- PC 开始表现得很奇怪,拒绝 运行 程序等。如果我重新启动它 - Windows 只是在启动屏幕上不停地旋转,让它重新启动的唯一方法是通过 liveCD 和 rename\delete 我的挂钩 DLL 启动。
打印程序:Excel2016,记事本。
编译器 - MSVC 2015,x64 版本 DLL 编译,使用 MBCS 而不是 unicode。
你的钩子声明错误。
看看StartDocW()
在Wingdi.h
中的实际声明:
__gdi_entry WINGDIAPI int WINAPI StartDocW(__in HDC hdc, __in CONST DOCINFOW *lpdi);
你可以忽略__gdi_entry
。 WINGDIAPI
简单地解析为 __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;
}
}
我正在尝试挂钩 StartDocW to intercept printing via mhook。我使用 AppInit_DLLs 加载我的库。
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
- 程序也会挂起。为什么会这样?
此外,如果程序 crashes\hangs 正在打印(如果我添加 return orig(hdc, lpdi)
之外的任何内容)- PC 开始表现得很奇怪,拒绝 运行 程序等。如果我重新启动它 - Windows 只是在启动屏幕上不停地旋转,让它重新启动的唯一方法是通过 liveCD 和 rename\delete 我的挂钩 DLL 启动。
打印程序:Excel2016,记事本。
编译器 - MSVC 2015,x64 版本 DLL 编译,使用 MBCS 而不是 unicode。
你的钩子声明错误。
看看StartDocW()
在Wingdi.h
中的实际声明:
__gdi_entry WINGDIAPI int WINAPI StartDocW(__in HDC hdc, __in CONST DOCINFOW *lpdi);
你可以忽略__gdi_entry
。 WINGDIAPI
简单地解析为 __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;
}
}