2010-07-13 25 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