棧桢
首先來看一段代碼
#include<stdio.h>
int add(int x, int y)
{
int z = x + y;
return z;
}
int main()
{
int a = ;
int b = ;
int ret = add(a, b);
printf("ret = %d\n",ret);
return ;
}
此處是為了給a,b分别開辟空間,這時棧桢如圖所示
兩條push指令将a,b變量入棧儲存
接下來通過call指令,将call指令的下一條指令的位址入棧,目的是為了恢複,其次call指令通過jmp指令修改eip寄存器的值,進而達到跳轉的目的
通過push指令将此時的ebp壓棧保護(此時的ebp是main函數的ebp),再通過move将esp和ebp的指向變得相同(都指向esp指向的位置),再将esp減44,至此形成新的棧桢結構
接下來,通過以下幾條指令計算出a + b,并将其儲存,同時通過pop指令出棧,再用move指令将esp和ebp指向相同位置再通過ret将目前棧頂的資料彈回到eip(ret将目前棧頂資料彈回到eip 中)
對應彙編代碼如下
此時對應的棧桢結構如圖所示
此時已經回到初始狀态,通過add和move指令達到将ebp傳回到main函數的ebp,再将a+b的内容放到ebp-12的那塊空間,如圖所示.
至此完成所棧桢結構,以及臨時變量的釋放 再來看一段棧桢應用的代碼:
#include<stdio.h>
#include<windows.h>
void bug();
int my_add(int x, int y);
void* ret = NULL;
void bug()
{
int x = ;
int* q = &x;
q += ;
*q = ret;
printf("bug: hehe i am a bug!\n");
Sleep();
}
int my_add(int x, int y)
{
//printf("my_add:");
int* p = &x;
p--;
ret = *p;
*p = bug;
}
int main()
{
int a = ;
int b = ;
int c = my_add(a, b);
__asm
{
sub esp,
}
printf("main: you should run here\n");
return ;
}