当挂钩函数被调用 C++ 时,使用 MS Detours 挂钩会崩溃

Hooking with MS Detours crash when hook function is called C++

我写了一个简单的程序来做三件事:

它用文本 "NOT HOOKED"

调用 MessageBoxA (MBA)

然后它加载我创建的一个 dll 文件,该文件挂钩 MBA 函数并使用文本 "HOOKED".

调用 MBA

之后,它再次使用相同的文本调用 MBA ("NOT HOOKED")。 当然,应该挂接第二个 MBA 调用并显示带有 "HOOKED" 文本的消息。

最终它调用 FreeLibrary 并退出。

这是 .cpp 文件:

#include <iostream>
#include <Windows.h>

using namespace std;

int main()
{
    //Place the path of the dll file here, "DLLs\HookDLL.dll" is the default path.
    char dllPath[] = "HookDLL.dll"; 

    //Display a pop-up message with the "NOT HOOKED" message and title. 
    MessageBoxA(NULL, "NOT HOOKED", "NOT HOOKED", MB_OK);

    //Load the dll file
    HMODULE hModule = LoadLibraryA((LPCSTR)dllPath);

    //If hModule is null, then the dll wasn't loaded.
    //An error message will be printed out to the console.
    if (!hModule) {
        cout << "Couldn't load the DLL file!" << endl;

        return 1;
    }

    //This is the tricky part.
    //This should display a pop-up message like before with the "NOT HOOKED" message and title,
    //but the dll that was loaded should hook MessageBoxA function,
    //and call a new one with a "HOOKED" message and title instead.
    MessageBoxA(NULL, "NOT HOOKED", "NOT HOOKED", MB_OK);

    FreeLibrary(hModule);

    return 0;
}

这里是 .dll 文件:

#include "pch.h"
#include "detours.h"
#include <iostream>
#include <Windows.h>

using namespace std;

typedef int(WINAPI* MBA)(HWND, LPCSTR, LPCSTR, UINT);

MBA originalMBA = NULL;

int HookedMessageBoxA(
    HWND   hWnd,
    LPCSTR lpText,
    LPCSTR lpCaption,
    UINT   uType
) {
    return originalMBA(NULL, "HOOKED", "HOOKED", MB_OK);
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  reason,
    LPVOID lpReserved
)
{
    if (reason == DLL_PROCESS_ATTACH) {
        DetourRestoreAfterWith();
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());

        originalMBA = (MBA)DetourFindFunction("user32.dll", "MessageBoxA");//Pointer the the original MBA (MessageBoxA) function.
        DetourAttach(&(PVOID&)originalMBA, (PVOID)HookedMessageBoxA);

        DetourTransactionCommit();
    }

    return TRUE;
}

当我在调试模式下构建和 运行 时,它在第二次 MBA 调用时崩溃(当然是在 .cpp 文件中):
它显示挂钩的 MBA,其中包含 "HOOKED",就像它应该的那样,然后它崩溃,在下面打印错误,程序退出,代码为 3:

Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.
This is usually a result of calling a function declared with one calling convention with a function
pointer declared with a different calling convention.

我已经检查了这个错误和退出代码,并找到了很多有用的帖子和解决方案,但我无法让它们中的任何一个为我工作(也许我做错了什么)。

注1:
如果我处于 Release 模式,我可以调用任意多的 MBA 调用 只要它们先于 FreeLibrary 调用,并且所有这些调用都将被 .dll 文件很好地挂钩,程序将正确退出。 但是,如果我尝试在调用 FreeLibrary 之后调用 MBA 函数 - 程序会因以下错误而崩溃:

Exception thrown at 0x50011000 in ProgrammingTask.exe: 0xC0000005: Access violation executing location 0x50011000.

注2:
我尝试使用DetourDetouch分离dll,但没有解决,可能我做错了。
另外,我尝试阅读有关 CreateRemoteThread 的内容,但对我来说太乱了。

提前致谢。

找到了!

忘记将 __stdcall 添加到 HookedMessageBox 函数。

所以,而不是

 int HookedMessageBoxA 

我改写成这样:

 int __stdcall HookedMessageBoxA 

感谢大家的帮助! <3