#include <iostream><?xml:namespace prefix = o />
using namespace std;
void f1(int a,int b)
{
}
int main()
f1(3,4);
system("pause");
将上述代碼反彙編如下(vs05debug):
004113D0 push ebp ;/儲存棧基址
004113D1 mov ebp,esp ;将棧頂指針賦給ebp,此時都指向函數調用的棧頂
004113D3 sub esp,0C0h ;棧頂指針下移0xc0h,為main函數内局部變量配置設定空間
004113D9 push ebx ;在棧中儲存ebx
004113DA push esi
004113DB push edi
004113DC lea edi,[ebp-0C0h] ;将ebp-0c0h值賦給edi
004113E2 mov ecx,30h
004113E7 mov eax,0CCCCCCCCh
004113EC rep stos dword ptr es:[edi];從lea指令到這條指令作用就是把為局部變量配置設定的記憶體空間填充CC資料。Stos将eax中資料放入es:[edi]中,同時edi增加4個位元組。Rep使指令重複執行ecx次數。
f1(3,4);
004113EE push 4
004113F0 push 3 ;參數入棧
004113F2 call f1 (4111D6h) ;call指令實際動作是push eip;mov eip,4111D6h連續兩條指令。
004113F7 add esp,8 ;c的調用約定,調整棧
system("pause");
004113FA mov esi,esp
004113FC push offset string "pause" (415810h)
00411401 call dword ptr [__imp__system (4182B4h)]
00411407 add esp,4
0041140A cmp esi,esp
0041140C call @ILT+315(__RTC_CheckEsp) (411140h)
void f1(int a,int b) //f1函數反彙編代碼。
004113A0 push ebp
004113A1 mov ebp,esp
004113A3 sub esp,0C0h
004113A9 push ebx
004113AA push esi
004113AB push edi
004113AC lea edi,[ebp-0C0h]
004113B2 mov ecx,30h
004113B7 mov eax,0CCCCCCCCh
004113BC rep stos dword ptr es:[edi] ;上述彙編指令每個函數都有主要用來初始化棧和儲存一些寄存器的值。
004113BE pop edi
004113BF pop esi
004113C0 pop ebx ;函數調用完畢,回複edi等寄存器的值
004113C1 mov esp,ebp
004113C3 pop ebp ;回收為f1函數配置設定的棧幀。
004113C4 ret ;此指令實際動作是pop eip;call f1時push eip,那時eip的值是call函數下條指令的值,程式跳轉main函數執行。
是以通過上述分析,我們得到一下的棧内資料的布局:
由于eip要存入棧中,是以就有可能被修改,導緻程式異常的運作,很多病毒就是利用了這一點。
參考:
[2] 天書夜讀