挂钩 Windows API 函数使应用程序崩溃
Hooking Windows API function crashes application
我正在制作一个 DLL,将特定的 Windows API 函数与 Microsoft Detours 挂钩,以便执行一些分析。 DLL 被添加到第三方游戏的导入 table,以便 DllMain 函数 运行 和应用挂钩。
我 运行 在尝试挂接 GetFileSize 函数时遇到了问题。当我走弯路时,即使是一个简单的弯路,游戏几乎立即崩溃并出现访问冲突异常。在我看来,绕行以某种方式破坏了应用程序。这是导致我的问题的最简单代码:
static DWORD(WINAPI * TrueGetFileSize) (
HANDLE hFile,
LPDWORD lpFileSizeHigh
) = GetFileSize;
DWORD GetFileSizeDetour(HANDLE hFile, LPDWORD lpFileSizeHigh) {
return TrueGetFileSize(hFile, lpFileSizeHigh);
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
{
if (DetourIsHelperProcess()) {
return TRUE;
}
if (dwReason == DLL_PROCESS_ATTACH) {
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)TrueGetFileSize, GetFileSizeDetour);
DetourTransactionCommit();
}
else if (dwReason == DLL_PROCESS_DETACH) {
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)TrueGetFileSize, GetFileSizeDetour);
DetourTransactionCommit();
}
return TRUE;
}
我在调试游戏的时候,加了DLL,绕路其实打了一次,但是继续执行的时候就失败了。这是进程崩溃时 Visual Studio 中调用堆栈 window 的屏幕截图:
问题似乎出现在 dsound.dll 初始化 CRT 的过程中,我猜这是 Windows 游戏处理声音的方式。
进程因访问冲突异常而崩溃,表示无法执行调用堆栈屏幕截图中的位置。
这让人觉得迂回似乎以某种方式破坏了应用程序,使一些依赖于函数的代码失败。但是,我更有可能误解了某些事情,或者试图以错误的方式做某事。 :)
任何帮助或指导将不胜感激!
问题
你的绕行功能calling convention
DWORD GetFileSizeDetour(HANDLE hFile, LPDWORD lpFileSizeHigh)
不符合原GetFileSize()
函数的调用约定:
DWORD WINAPI GetFileSize( HANDLE hFile, LPDWORD lpFileSizeHigh );
我通过右键单击 > "go to declaration" 从 "fileapi.h" 中删除了后者,并删除了不相关的内容。
WINAPI
默认是 __stdcall
. Your detour function has no explicit calling convention modifier, so MSVC uses __cdecl
的定义。
为什么这是个问题? __cdecl
要求调用者清理堆栈,而 __stdcall
要求被调用函数清理堆栈。显然,如果使用不正确的调用约定,堆栈可能会损坏。
红利阅读:Calling Conventions Demystified
解决方案
通过添加 WINAPI
:
修复调用约定
DWORD WINAPI GetFileSizeDetour(HANDLE hFile, LPDWORD lpFileSizeHigh)
我正在制作一个 DLL,将特定的 Windows API 函数与 Microsoft Detours 挂钩,以便执行一些分析。 DLL 被添加到第三方游戏的导入 table,以便 DllMain 函数 运行 和应用挂钩。
我 运行 在尝试挂接 GetFileSize 函数时遇到了问题。当我走弯路时,即使是一个简单的弯路,游戏几乎立即崩溃并出现访问冲突异常。在我看来,绕行以某种方式破坏了应用程序。这是导致我的问题的最简单代码:
static DWORD(WINAPI * TrueGetFileSize) (
HANDLE hFile,
LPDWORD lpFileSizeHigh
) = GetFileSize;
DWORD GetFileSizeDetour(HANDLE hFile, LPDWORD lpFileSizeHigh) {
return TrueGetFileSize(hFile, lpFileSizeHigh);
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
{
if (DetourIsHelperProcess()) {
return TRUE;
}
if (dwReason == DLL_PROCESS_ATTACH) {
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)TrueGetFileSize, GetFileSizeDetour);
DetourTransactionCommit();
}
else if (dwReason == DLL_PROCESS_DETACH) {
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)TrueGetFileSize, GetFileSizeDetour);
DetourTransactionCommit();
}
return TRUE;
}
我在调试游戏的时候,加了DLL,绕路其实打了一次,但是继续执行的时候就失败了。这是进程崩溃时 Visual Studio 中调用堆栈 window 的屏幕截图:
问题似乎出现在 dsound.dll 初始化 CRT 的过程中,我猜这是 Windows 游戏处理声音的方式。
进程因访问冲突异常而崩溃,表示无法执行调用堆栈屏幕截图中的位置。
这让人觉得迂回似乎以某种方式破坏了应用程序,使一些依赖于函数的代码失败。但是,我更有可能误解了某些事情,或者试图以错误的方式做某事。 :)
任何帮助或指导将不胜感激!
问题
你的绕行功能calling convention
DWORD GetFileSizeDetour(HANDLE hFile, LPDWORD lpFileSizeHigh)
不符合原GetFileSize()
函数的调用约定:
DWORD WINAPI GetFileSize( HANDLE hFile, LPDWORD lpFileSizeHigh );
我通过右键单击 > "go to declaration" 从 "fileapi.h" 中删除了后者,并删除了不相关的内容。
WINAPI
默认是 __stdcall
. Your detour function has no explicit calling convention modifier, so MSVC uses __cdecl
的定义。
为什么这是个问题? __cdecl
要求调用者清理堆栈,而 __stdcall
要求被调用函数清理堆栈。显然,如果使用不正确的调用约定,堆栈可能会损坏。
红利阅读:Calling Conventions Demystified
解决方案
通过添加 WINAPI
:
DWORD WINAPI GetFileSizeDetour(HANDLE hFile, LPDWORD lpFileSizeHigh)