Fig 1. 函數調用發生和結束時調用棧的變化shell
Fig 2. 將被調用函數的參數壓入棧內函數
Fig 3. 將被調用函數的返回地址壓入棧內佈局
Fig 4. 將調用函數的基地址(ebp)壓入棧內,並將當前棧頂地址傳到 ebp 寄存器內spa
首先咱們來看看如下程序調用棧的過程:code
int sum(int a,int b) { int temp = 0; temp = a+b; return temp; } int main() { int a = 10; int b = 20; int ret = 0; ret = sum(a,b); cout<<ret<<endl; return 0; }
以下調用過程:blog
每一個函數在調用前都會作一件事情。 教程
(1)把調用方的ebp入到本身的棧裏去內存
(2)用esp指向新的棧頂位置,把esp的值賦給ebp,產生新的ebp get
(3)開闢空間,初始0XCCCCCCCC。 ebp入棧,實參入棧,形參入棧,調用call指令。call有兩步,把下一行指令的地址入棧,跳轉到調用的函數執行。形參內存主調方開闢,主調方釋放。class
main函數棧幀
開闢sum函數棧幀
sum函數內存佈局
棧溢出的shellcode中常常會出現:
payload : padding1 + address of shellcode + padding2 + shellcode
payload: padding1 + address of system() + padding2 + address of 「/bin/sh」
這幾種payload,不少教程對於padding2這個沒有解釋的很清楚,ctf wiki上是這樣說的 :「若是是正常調用 system 函數,咱們調用的時候會有一個對應的返回地址」