函數調用棧

博客網址:www.shicoder.top
微信:18223081347
歡迎加群聊天 :452380935

這個分欄我們開始學習PWN,當然PWN也是自己的興趣愛好,所以可能博客更新較慢,不好意思啦

前置知識

每個函數都有自己的棧幀,棧底用ebp,棧頂用esp,還有一個eip,表示即將執行的指令的地址,下面是棧的圖示,是從高地址向低地址增長

image-20220502093832451

函數的棧幀包括

  • 函數的返回地址和參數
  • 本地變量
  • 調用前後上下文

因此比如一個main函數執行時候,ebp指向其棧幀底部,然後在函數運行時候隨時pushpop,導致其esp不斷變化,當要調用子函數func時候,會先push子函數所需要的參數,然後進入func之後,首先push ebp,因為此時的ebpmain函數的,為了在func函數結束後,找到main函數的ebp,所以先保留,然後mov ebp,esp,這時候ebp就會被賦予新的值,這個值就是func函數棧幀的底部,然後就是一些func函數自己的操作,當要使用傳進來的參數時候,就去當時在main調用funcpush的參數去取,當執行func函數之後,需要返回到main,此時分兩種情況

  • func中沒有使用過局部變量,則進入func之後,ebpesp始終是一樣的,所以直接pop ebp,此時ebp中就存放了call調用前,mainebp
  • func中使用過局部變量,則進入func之後,首先會sub esp,一些空間來給func使用,然後結束時候,使用leave => mov esp,ebp、pop ebp,先將esp值變為ebp的值,此時兩個一樣,然後pop ebp之後,ebp中就存放了call調用前,mainebp

簡單的就是如下代碼

main:
	...
    push arg2
    push arg1
    call func
    ...

; func函數內沒有局部變量
func:
	push ebp
	mov ebp,esp
	將main的棧中的參數放到寄存器中
	一頓操作
	pop ebp
	retn

; func函數內有局部變量
func:
	push ebp
	mov ebp,esp
	sub esp,0x10(就是一段長度,存放局部變量)
	將main的棧中的參數放到寄存器中
	一頓操作
	leave
	retn

注意:

  • call => 等價 push 返回地址,然後eip跳轉到sum開頭的地方
  • leave => 等價 mov esp, ebp 然後 pop ebp
  • retn => 等價 pop eip

小試牛刀

以下面的c語言代碼進行講解

#include<stdio.h>

int sum(int a,int b)
{
	return a + b;
}

int main(){
	sum(3,4);
	return 0;
}

push    ebp
mov     ebp, esp
push    4
push    3
call    sum
add     esp, 8
mov     eax, 0
leave
retn

push    ebp
mov     ebp, esp
mov     edx, [ebp+8]
mov     eax, [ebp+0Ch]
add     eax, edx
pop     ebp
retn

下面一段視頻就是其過程,可以看下

後面還有兩段有局部變量的,大家也可以自己推導下。

#include<stdio.h>

int sum(int a,int b)
{
	int c;
	c = a + b;
	return c;
}

int main(){
	int ret;
	ret = sum(3,4);
	return 0;
}
push    ebp
mov     ebp, esp
sub     esp, 10h
push    4
push    3
call    sum 
add     esp, 8
mov     [ebp-4], eax
mov     eax, 0
leave  
retn  

push    ebp
mov     ebp, esp
sub     esp, 10h
mov     edx, [ebp+8]
mov     eax, [ebp+0Ch]
add     eax, edx
mov     [ebp-4], eax
mov     eax, [ebp-4]
leave
retn
#include<stdio.h>

int sum(int a,int b)
{
	return a + b;
}

int main(){
	int ret;
	ret = sum(3,4);
	return 0;
}
push    ebp
mov     ebp, esp
sub     esp, 10h
push    4
push    3
call    sum
add     esp, 8
mov     [ebp-4], eax
mov     eax, 0
leave
retn

push    ebp
mov     ebp, esp
mov     edx, [ebp+8]
mov     eax, [ebp+0Ch]
add     eax, edx
pop     ebp
retn
Tags: