注:不知道說“偷調函數”說法合不合適,在此也就這樣一說了~
主要有兩點:
一、再說C++反匯編函數調用,重點是怎樣通過堆棧實現由被調用函數轉到調用者
二、在 1 的基礎上,在WinDbg下通過修改EIP實現如下一個功能:
有兩個函數foo()和hack(),在main函數中調用foo,但是在foo執行過程中,通過修改EIP來調用hack函數,最后再回到main中foo函數的下一條語句
一、再說C++反匯編函數調用,重點是怎樣通過堆棧實現由被調用函數轉到調用者
程序如下(很簡單):
1 #include "stdafx.h"
2
3 int MyAdd(int a,int b)
4 {
5 return a+b;
6 }
7
8 void main()
9 {
10 MyAdd(1,2);
11 }
反匯編后如下:
void main()
11: {
00401080 push ebp
00401081 mov ebp,esp
00401083 sub esp,40h
00401086 push ebx
00401087 push esi
00401088 push edi
00401089 lea edi,[ebp-40h]
0040108C mov ecx,10h
00401091 mov eax,0CCCCCCCCh
00401096 rep stos dword ptr [edi]
12: MyAdd(1,2);
00401098 push 2
0040109A push 1
;程序執行到這,堆棧內容如下(至于為什么是這,請參看《c++反匯編代碼分析--函數調用》)

0040109C call @ILT+15(hook) (00401014);
--------------------------------開始轉入MyAdd函數去執行--------------------------
;在執行0040109C call @ILT+15(hook) (00401014)到這句時,F11單步調試,會依次執行下邊的反匯編代碼:
00401014 jmp MyAdd (00401030)
;執行到此句時,ESP和EBP還是原來的值嗎?
;我們可能會覺得,現在也沒有push操作,ESP和EBP應該還是應該如上圖一樣沒有變化吧
;非也,其實執行到這一句時,已經有一個自動的入棧操作,入棧的是0040109C call @ILT+15(hook) (00401014)
;這條指令的下一條指令的地址,具體如下圖所示:
;執行到0040109C call @ILT+15(hook) (00401014)這條語句時,如圖:

;執行到0040109C call @ILT+15(hook) (00401014)這條語句,按F11后,如下圖:

;此時的堆棧情況如下圖

;之后,轉入下邊的程序執行
5: int MyAdd(int a,int b)
6: {
00401030 push ebp
……
}
……
;執行過ret后,會自動將堆棧中retAddr的值彈給EIP,從而完成從被調用函數MyAdd轉到main函數中去執行。
;這一點十分重要,也就是 二 的理論基礎了吧。
00401053 pop ebp
00401054 ret
--------------------------MyAdd子函數執行完畢,在此進入main函數執行------------------------------------
004010A1 add esp,8
13: }
004010A4 pop edi
......
二、在 一 的基礎上,在WinDbg下通過修改EIP實現如下一個功能:......
程序如下:
#include <iostream>
using namespace std;
void foo()
{
printf("--foo--\n");
}
void hook()
{
printf("--hook--\n");
}
void main()
{
foo();
hook();
}
理論如圖:

輸出為:
--foo--
--hack--
--hack--