挂钩 SetRect 时 Detours 3.0 应用程序崩溃
Detours 3.0 application crashing when hooking SetRect
我之前尝试挂钩 SetRect function using Detours but my program is crashing directly after hooking. I tried hooking other functions such as DrawText,一切正常,现在我不确定我的代码是否有问题,或者我不知道 SetRect(和其他类似函数)是否有问题意识到导致崩溃。
为了测试,我使用提供的 Detours 运行 和 dll 程序:
withdll.exe -d:mydll.exe simpleprogram.exe
其中 simpleprogram.exe 是一个简单的一键式 C# 应用程序。也尝试在记事本、calc、firefox 上进行测试,但它们都崩溃了。
我的挂钩DLL
#include <Windows.h>
#include <detours.h>
#include<string>
#include<fstream>
#include<iostream>
using namespace std;
wofstream out;
BOOL(__stdcall * T14)
(
_Out_ LPRECT lprc,
_In_ int xLeft,
_In_ int yTop,
_In_ int xRight,
_In_ int yBottom
) = SetRect;
__declspec(dllexport) BOOL 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);
}
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
out.open("out.txt");
out << "Attached" << endl;
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)T14, M14);
DetourTransactionCommit();
}
else if (dwReason == DLL_PROCESS_DETACH)
{
out << "detached" << endl;
out.close();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)T14, M14);
DetourTransactionCommit();
}
return TRUE;
}
我得到的输出:
Attached
SetRect: 138 161 323 161
所以在调用第一个 SetRect 函数后程序崩溃了,知道为什么会这样吗?
我刚刚尝试挂钩 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()
的方式,因为这是我的代码与您的代码之间唯一不同的地方。
你绕行函数的调用约定是错误的。
Visual C++ 项目默认为 __cdecl
,但所有 Windows API 使用 WINAPI
(__stdcall
).
由于调用约定的差异,您正在破坏调用堆栈。这个问题在 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++ 标准库 ;)
我之前尝试挂钩 SetRect function using Detours but my program is crashing directly after hooking. I tried hooking other functions such as DrawText,一切正常,现在我不确定我的代码是否有问题,或者我不知道 SetRect(和其他类似函数)是否有问题意识到导致崩溃。
为了测试,我使用提供的 Detours 运行 和 dll 程序:
withdll.exe -d:mydll.exe simpleprogram.exe
其中 simpleprogram.exe 是一个简单的一键式 C# 应用程序。也尝试在记事本、calc、firefox 上进行测试,但它们都崩溃了。
我的挂钩DLL
#include <Windows.h>
#include <detours.h>
#include<string>
#include<fstream>
#include<iostream>
using namespace std;
wofstream out;
BOOL(__stdcall * T14)
(
_Out_ LPRECT lprc,
_In_ int xLeft,
_In_ int yTop,
_In_ int xRight,
_In_ int yBottom
) = SetRect;
__declspec(dllexport) BOOL 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);
}
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
out.open("out.txt");
out << "Attached" << endl;
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)T14, M14);
DetourTransactionCommit();
}
else if (dwReason == DLL_PROCESS_DETACH)
{
out << "detached" << endl;
out.close();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)T14, M14);
DetourTransactionCommit();
}
return TRUE;
}
我得到的输出:
Attached
SetRect: 138 161 323 161
所以在调用第一个 SetRect 函数后程序崩溃了,知道为什么会这样吗?
我刚刚尝试挂钩 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()
的方式,因为这是我的代码与您的代码之间唯一不同的地方。
你绕行函数的调用约定是错误的。
Visual C++ 项目默认为 __cdecl
,但所有 Windows API 使用 WINAPI
(__stdcall
).
由于调用约定的差异,您正在破坏调用堆栈。这个问题在 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++ 标准库 ;)