【问题标题】:Call a function twice with Assembly and C++使用 Assembly 和 C++ 调用函数两次
【发布时间】:2010-07-13 02:05:01
【问题描述】:

我有一个代码可以将要调用的函数更改为我的新函数,但我不想只调用我的新函数,我也想调用旧函数。 这是一个例子,所以你可以理解我在说什么:

如果我反汇编我的.exe,我会看看这部分:

L00123456:
      mov   eax, [L00654321] //doesn't matter
      mov   ecx, [eax+1Ch]   //doesn't matter
      push  esi              //the only parameter
0x123 call  SUB_L00999999    //this is the function I wanna overwrite
      //...

(0x123 是该行的地址) 所以,我使用了这段代码:

DWORD old;
DWORD from = 0x123;
DWORD to   = MyNewFunction;
VirtualProtect(from, 5, PAGE_EXECUTE_READWRITE, &old);

DWORD disp = to - (from + 5);
*(BYTE *)(from) = 0xE8;
*(DWORD *)(from + 1) = (DWORD)disp;

现在,它不再调用 SUB_L00999999,而是调用 MyNewFunction...

那么...关于如何调用旧函数的任何想法?

我尝试过这样的事情(在很多方面),但它使我的应用程序崩溃:

int MyNewFunction(int parameter)
{
    DWORD oldfunction = 0x00999999;
    _asm push parameter
    _asm call oldfunction
}

注意:我使用 Visual Studio C++ 2010,这些代码位于 .exe 中加载的 .dll 中。

谢谢。

【问题讨论】:

    标签: c++ memory assembly hook inline-assembly


    【解决方案1】:

    前段时间我遇到过这样的问题。无论如何,_asm call dword ptr [oldfunction] 为我工作。

    【讨论】:

    • 谢谢你,这很好用,我不记得我以前用过这个......
    【解决方案2】:

    ret 期望栈顶参数是要返回的地址。您可以通过在新函数中的 ret 指令之前将旧函数地址推入堆栈来利用这一点。随着调用返回(或者更确切地说,分支到旧函数),堆栈指针将移动以将原始返回地址(此处为 0x128)留在顶部,因此堆栈将看起来完好无损。 (如果你没有绕道,应该是一样的)。

    【讨论】:

    • 试用_asm { push oldfunction; ret 4 } 并使用调试器检查您的输出。我不确定 C 编译器是否可能添加/删除任何其他可能扰乱堆栈的内容。堆栈在进入 oldfunction 时应该看起来与进入 newfunction 时相同。 (哦,有些寄存器可能需要相同,可能需要在retn之前设置)。
    • 您的答案也应该有效,但更复杂的是,我们不是只使用我的参数调用函数,而是返回旧堆栈然后调用函数。我在某个项目文件中看到了这一点,并尝试以这种方式进行,但比@myeviltacos 的方式更难。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-03
    • 1970-01-01
    相关资源
    最近更新 更多