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

时间:2019-12-30 14:44:50

标签: c++ dll hook detours

我编写了一个简单的程序,该程序可以执行3件事:

它使用文本“ NOT HOOKED”调用MessageBoxA(MBA)

然后,它会加载我创建的dll文件,该文件会钩住MBA函数并以文本“ HOOKED”调用MBA。

之后,它将再次使用相同的文本(“ NOT HOOKED”)调用MBA。 当然,应该挂断第二个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;
}

当我在Debug模式下构建并运行时,它在第二次MBA调用时崩溃(当然在.cpp文件中):
它像应显示的那样显示带有“ HOOKED”字样的钩住的MBA,然后崩溃,在下面打印错误,程序退出并显示代码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:
如果我处于“释放”模式,则只要在FreeLibrary调用之前,我就可以根据需要调用任意数量的MBA调用,所有这些调用都将被.dll文件挂接,并且程序将正确退出。 但是,如果我尝试在FreeLibrary调用之后 之后调用MBA函数-程序因以下错误而崩溃:

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

注意2:
我尝试使用DetourDetouch分离dll,但无法解决问题,也许是我做错了。
另外,我尝试阅读有关CreateRemoteThread的内容,但对我来说太混乱了。

谢谢。

1 个答案:

答案 0 :(得分:0)

发现了!

忘记将__stdcall添加到HookedMessageBox函数中。

因此,而不是

 int HookedMessageBoxA 

我将其重写为:

 int __stdcall HookedMessageBoxA 

感谢您的帮助! <3