c++ - 挂接 Windows API 函数使应用程序崩溃

标签 c++ windows winapi hook detours

我正在制作一个 DLL,它将特定的 Windows API 函数与 Microsoft Detours Hook ,以便执行一些分析。 DLL 被添加到第三方游戏的导入表中,以便运行 DllMain 函数并应用 Hook 。

我在尝试挂​​钩 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 中调用堆栈窗口的屏幕截图:

Crash call stack

问题似乎是在 dsound.dll 初始化 CRT 时出现的,我猜这是 Windows 游戏处理声音的方式。

进程因访问冲突异常而崩溃,表示无法执行调用堆栈屏幕截图中的位置。

这让人觉得迂回似乎以某种方式破坏了应用程序,使某些依赖于该函数的代码失败。但是,我更有可能误解了某些事情,或者试图以错误的方式做某事。 :)

任何帮助或指导将不胜感激!

最佳答案

问题

calling convention你的绕行功能

DWORD GetFileSizeDetour(HANDLE hFile, LPDWORD lpFileSizeHigh)

不符合原GetFileSize()函数的调用约定:

DWORD WINAPI GetFileSize( HANDLE hFile, LPDWORD lpFileSizeHigh );

我通过右键单击 >“转到声明”从“fileapi.h”中获取了后者,并删除了不相关的内容。

WINAPI__stdcall 的定义.您的绕行函数没有显式调用约定修饰符,因此 MSVC 使用 __cdecl默认情况下。

为什么这是个问题? __cdecl 要求调用者清理堆栈,而 __stdcall 要求被调用函数清理堆栈。显然,如果使用不正确的调用约定,堆栈可能会损坏。

红利阅读:Calling Conventions Demystified

解决方案

通过添加 WINAPI 修复调用约定:

 DWORD WINAPI GetFileSizeDetour(HANDLE hFile, LPDWORD lpFileSizeHigh)

关于c++ - 挂接 Windows API 函数使应用程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54852191/

相关文章:

c++ - 存储指向 map 中包含的对象的指针

c++ - 如何在 C++ 中去掉 -0

c++ - SetFont() - 函数不适用于 wxFrame

windows - ggplot-s 是否依赖于上一个桌面 session 属性?

android - 在 Windows 中通过代理在 Android 中启用 Internet 连接

c++ - 使用 boost 线程时出现链接器错误

c - 如何使用 C 转储 PE 导出函数名称?

c++ - SDL2 + Win32 API 菜单栏单击事件不起作用

c++ - 在 Win32 应用程序上工作,希望输出到 Win32 窗口和控制台窗口

c++ - 当窗口关闭时,我的析构函数会被调用吗?