2010-07-13 37 views
4

我有一个代码可以改变将被调用的函数到我的新函数,但我不想只调用我的新函数,我也想调用旧函数。 这是一个例子,这样你就可以明白我在说什么:使用Assembly和C++调用函数两次

如果我拆开我的.exe文件,我会看这个部分:

L0: 
     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。

谢谢。

回答

2

我曾经有过这样的问题。无论如何,_asm call dword ptr [oldfunction]为我工作。

+0

谢谢你,这工作得很好,我不记得我前一段时间使用过... – 2010-07-13 06:02:04

2

ret预计顶层堆栈参数是要返回的地址。您可以在新功能的ret指令之前立即将旧功能地址推入堆栈,从而充分利用此功能。当调用返回(或者更确切地说,分支到旧函数)时,堆栈指针将会移到原来的返回地址(此处为0x128),所以堆栈将不会损坏。 (如果你没有走弯路,应该是一样的)。

+0

你能给我一个使用“ret”的例子代码吗?谢谢。 – 2010-07-13 02:40:44

+1

尝试'_asm {push oldfunction; ret 4}'并用调试器检查你的输出。我不确定C编译器是否可以添加/删除任何可能会使堆栈崩溃的东西。当它进入旧功能时,它应该看起来一样,就像它进入新功能时一样。 (哦,一些寄存器可能需要相同,你可能需要在retn之前设置它们)。 – 2010-07-13 02:51:12

+0

你的答案也应该可以工作,但事实并非如此,而是用我的参数调用函数,而是回到旧的堆栈,然后调用函数。我在一些项目文件中看到了这一点,并试图这样做,但是@myeviltacos的方式更难。感谢您的帮助。 – 2010-07-13 06:15:08