绕过3.0应用程序在钩子SetRect时崩溃
Detours 3.0 application crashing when hooking SetRect
我试图使用弯路挂钩SetRect函数,但我的程序在挂钩后直接崩溃。我尝试挂钩其他功能,如DrawText之前,一切工作正常,现在我不确定是否有问题与我的代码或有一些关于SetRect(和其他类似的功能),我不知道导致崩溃。
对于测试,我使用提供的Detours运行与dll程序:
withdll.exe -d:mydll.exe simpleprogram.exe
simpleprogram.exe是一个简单的一键c#应用程序。我也试过在记事本,calc,火狐上测试,但是它们都崩溃了。
我的钩子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;
}
我得到的输出:
附SetRect: 138 161 323 161
程序在第一个SetRect函数被调用后崩溃了,知道为什么会发生这种情况吗?
你的绕道函数调用约定是错误的。
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()
,我让它正确地钩住了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()
的方式,因为这是我的代码和你的代码之间唯一的不同之处。
- 当回溯以零开始时,如何调试崩溃
- 内联映射初始化的动态atexit析构函数崩溃
- 执行函数时导致崩溃的变量
- 程序崩溃并显示"std::out_of_range"错误
- CoInitialize()在单独的线程上崩溃而不返回
- 使用调试/崩溃报告将应用程序部署到客户端
- 为什么所有C++编译器都会崩溃或挂起此代码
- 为什么lambda在clang上崩溃而不是在gcc上崩溃
- 为什么我的多线程作业队列崩溃
- ExtractIconEx:可以工作,但偶尔会崩溃
- 为什么引用传递会导致此崩溃(C++)
- 试图创建流或fopen时程序崩溃
- 类对象数组的问题会导致崩溃
- 排序时无法执行交换操作.我做的时候它会崩溃.为什么
- 为什么要增加导致崩溃的指针
- 在虚幻引擎中删除NXOpen对象时崩溃
- 为什么它只打印双链接列表的第一个值,而我的程序却崩溃了
- 应用程序崩溃并显示"symbol _ZdlPvm, version Qt_5 not defined in file libQt5Core.so.5 with link time reference"
- Visual Studio在尝试读取resource.txt文件时崩溃
- 绕过3.0应用程序在钩子SetRect时崩溃