【问题标题】:Hooking call function in c++?在 C++ 中挂钩调用函数?
【发布时间】:2014-10-22 22:22:48
【问题描述】:

大家好,
我是 C++ 的新手,但我设法创建了自己的 dll 并将其注入到我的 gameserver.exe 中

好吧,我已经尝试了几天来挂钩用户调用函数,但我总是失败,因为它属于程序集:(
我希望你们向我展示我如何编写适当的行来挂钩此功能:

0048C1AF  |. 8B9B 4C010000  MOV EBX,DWORD PTR DS:[EBX+14C]
0048C1B5  |. 8B13           MOV EDX,DWORD PTR DS:[EBX]
0048C1B7  |. 8B82 EC000000  MOV EAX,DWORD PTR DS:[EDX+EC]
0048C1BD  |. 8BCB           MOV ECX,EBX
0048C1BF  |. FFD0           CALL EAX
0048C1C1  |. 8BF8           MOV EDI,EAX
0048C1C3  |. E8 789EF8FF    CALL SR_GameS.00444040
0048C1C8  |. 8B7C24 1C      MOV EDI,DWORD PTR SS:[ESP+1C]
0048C1CC  |. 8BF0           MOV ESI,EAX
0048C1CE  |. E8 6D9EF8FF    CALL SR_GameS.00444040

到目前为止,我在 c++ 上写的内容是:

void __cdecl Global()
{

    __asm
    {

           mov msg, edi; //msg

           push ebx;
           mov ebx, dword ptr[esp+1C]; //playername
           mov playername, ebx;
           pop ebx;
    }

    printf("Global [%s] -> %s\n", playername, msg);

    //then calling func entry
    CALL((DWORD)0x00444040);
}

当 0048C1CE 被调用时,我将它放入我的 c++ 并将它的参数移动到 Global() 直到这里一切正常,但在 Global() 内部,我无法成功将参数回调到 x00444040,即使它在控制台窗口中显示一个奇怪的值,有时还会显示一部分播放器消息。

附:如果可能的话,可以解释装配线的情况。

对不起我的英语,提前谢谢。

【问题讨论】:

    标签: c++ visual-c++ assembly reverse-engineering


    【解决方案1】:

    关于您为什么要这样做的问题,我将暂且不提。这可能是别人的软件,他们可能没有给你许可。您可能在某处违反了许可。

    你的描述很纠结。汇编器的行不是一个函数,它们是带有 3 个函数调用的代码。我猜你的意思是你想拦截对函数 0x00444040 的调用以执行你自己的代码。你还没有展示你是如何做到的。

    C++ 代码大约需要做三件事。

    1. 在进入时,它必须符合其调用者所期望的调用顺序。在 ESI 和 EDI 中似乎有两个论点。
    2. 如果要调用 C++ 库函数,则必须保存所有可能会受到调用影响的寄存器,然后再恢复它们。
    3. 当您退出时,您应该恢复堆栈和寄存器在入口时的状态,并分支(JMP 不是 CALL)到被钩子函数,以便它可以返回到原始调用者,而不是您的钩子代码。

    在调试器级别,只需确保每个寄存器(包括堆栈指针)都与进入时相同,就在您分支到挂钩函数之前。

    【讨论】:

    • 您好,感谢您的回答,关于您的问题,这是多年前泄露的游戏服务器文件,现在在论坛上公开,关于我的 c++ 项目,我无法分享完整代码,因为我没有共享它的权限,但我确定它与您的第 1 点和第 3 点工作正常。我在第 2 点失败了,您能否举例说明如何在不影响它们的情况下保存所有寄存器并恢复它们之后?
    • 只需将一些寄存器压入堆栈,然后以相反的顺序将它们弹出。使用调试器检查哪些寄存器发生了变化,以及哪些需要保存。
    【解决方案2】:

    抛开道德和合法性不谈,我将只关注您问题的技术方面 - 但我认为您应该真诚地思考 david.pfx 提出的观点。

    已经编写了一些与您描述的类似的项目,仅出于个人知识,我会推荐一个通用挂钩库。我使用源引擎(来自《半条命 2》),并使用了一个名为 SourceHook 的库。 SourceHook 是 AlliedModder 的 metamod 项目的一部分,在 SourceMod 内部使用。

    当我尝试在源引擎项目之外编写通用挂钩时,我发现 SourceHook 仍然有用,但也探索了其他选项。我很高兴使用mHook,另一个通用挂钩库。

    了解您要挂钩的方法的调用约定很重要,因为正确恢复寄存器对于安全执行挂钩至关重要

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-28
      • 2020-03-24
      • 2010-11-30
      • 2013-05-21
      • 2020-08-01
      相关资源
      最近更新 更多