在c ++中挂钩调用函数?

时间:2014-08-28 22:53:51

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

大家好,
               我是cBox的新手,但我设法创建了自己的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的参数,即使它在控制台窗口中显示奇怪的值,有时也会显示玩家消息的一部分。

P.S。如果有可能解释装配线的情况。

对不起我的英文,提前致谢。

2 个答案:

答案 0 :(得分:1)

我会抛开你为什么要这样做的问题。它可能是其他人的软件,他们可能没有给你许可。你可能在某个地方违反了许可证。

你的描述很纠结。汇编程序行不是函数,它们是具有3个函数调用的代码。我猜你的意思是你要拦截对函数0x00444040的调用以执行你自己的代码。你还没有表明你是如何做到的。

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

  1. 进入时,它必须符合其调用者所期望的调用顺序。在ESI和EDI中似乎有两个参数。
  2. 如果要调用C ++库函数,则必须保存所有可能受到影响的寄存器,然后再进行恢复。
  3. 当你退出时,你应该恢复堆栈并准确地注册它们的入口和分支(JMP而不是CALL)到钩子函数,这样它就可以返回到原来的调用者,而不是你的挂钩代码。 / LI>

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

答案 1 :(得分:0)

除了道德和合法性之外,我只关注你问题的技术方面 - 但我觉得你应该对david.pfx提出的观点给予真诚的思考。

编写了一些与你描述的内容类似的项目,仅出于个人知识,我会推荐一个通用的挂钩库。我使用了源引擎(来自Half-life 2的成名),并使用了一个名为SourceHook的库。 SourceHook是AlliedModder的metamod项目的一部分,该项目在SourceMod中使用。

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

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