我正在尝试使用Detours挂钩SetRect函数,但我的程序在挂钩后直接崩溃。我之前试过挂钩DrawText之类的其他功能,一切正常,现在我不确定我的代码是否有问题,或者有些东西是关于SetRect(和其他类似功能)我不知道造成的碰撞。
为了测试,我使用提供的Detours运行dll程序:
../admin_module/images/
其中simpleprogram.exe是一个简单的单键C#应用程序。尝试在记事本,计算器,火狐上进行测试,但所有这些都崩溃了。
我的钩子DLL
withdll.exe -d:mydll.exe simpleprogram.exe
我得到的输出:
附
SetRect:138 161 323 161
所以在调用第一个SetRect函数后程序崩溃了,为什么会发生这种情况?
答案 0 :(得分:2)
你的绕道函数的调用约定是错误的。
Visual C ++项目默认为__cdecl
,但所有Windows API都使用WINAPI
(__stdcall
)。
由于调用约定的不同,您正在破坏callstack。这个问题在64位软件中不存在,因为只有一个调用约定,但对于x86,匹配原始函数原型中定义的任何调用约定至关重要。
__declspec(dllexport) BOOL WINAPI M14
(
_Out_ LPRECT lprc,
_In_ int L,
_In_ int T,
_In_ int R,
_In_ int B
){
out << "SetRect: " << L << " " << T << " " << R << " " << B << endl;
return T14(lprc, L, T, R, B);
}
另一方面,可能更严重且更难调试笔记。我会避免在DllMain (...)
中进行C ++流I / O.除非您将DLL静态链接到MSVCRT,否则在您持有加载程序锁定时会导致对其他DLL的依赖。
如果您从DllMain调用任何非静态链接的功能或kernel32.dll
或user32.dll
的一部分,则可以解决死锁问题。好消息是kernel32和user32有很多字符串函数 - 足以让你甚至不需要C ++标准库;)
答案 1 :(得分:1)
我刚尝试挂钩SetRect()
,我让它在Calc上正确挂钩。我将下面使用的代码放在DLL中。
static BOOL (WINAPI *TrueSetRect)(LPRECT, int, int, int, int) = SetRect;
...
...
BOOL WINAPI __stdcall MySetRect(LPRECT lprc, int L, int T, int R, int B)
{
printf("MySetRect: L = %i; T = %i; R = %i; B = %i", L, T, R, B);
return TrueSetRect(lprc, L, T, R, B);
}
__declspec(dllexport)
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
if(fdwReason == DLL_PROCESS_ATTACH)
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach( &reinterpret_cast<PVOID&>(TrueSetRect), MySetRect);
if(DetourTransactionCommit() == NO_ERROR)
{
//Detour successful
}
}
if(fdwReason == DLL_PROCESS_DETACH)
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach( &reinterpret_cast<PVOID&>(TrueSetRect), MySetRect);
if(DetourTransactionCommit() != NO_ERROR)
{
//Detach unsuccessful
} else {
//Detach successful
}
}
}
我怀疑它可能是您实例化SetRect()
和YourSetRect()
的方式,因为这是我的代码和您的代码之间唯一的不同。