函数调用栈
博客网址:www.shicoder.top
微信:18223081347
欢迎加群聊天 :452380935
这个分栏我们开始学习PWN,当然PWN也是自己的兴趣爱好,所以可能博客更新较慢,不好意思啦
前置知识
每个函数都有自己的栈帧,栈底用ebp
,栈顶用esp
,还有一个eip
,表示即将执行的指令的地址,下面是栈的图示,是从高地址向低地址增长
函数的栈帧包括
- 函数的返回地址和参数
- 本地变量
- 调用前后上下文
因此比如一个main
函数执行时候,ebp
指向其栈帧底部,然后在函数运行时候随时push
和pop
,导致其esp
不断变化,当要调用子函数func
时候,会先push
子函数所需要的参数,然后进入func
之后,首先push ebp
,因为此时的ebp
是main
函数的,为了在func
函数结束后,找到main
函数的ebp
,所以先保留,然后mov ebp,esp
,这时候ebp
就会被赋予新的值,这个值就是func
函数栈帧的底部,然后就是一些func
函数自己的操作,当要使用传进来的参数时候,就去当时在main
调用func
前push
的参数去取,当执行func
函数之后,需要返回到main
,此时分两种情况
func
中没有使用过局部变量,则进入func
之后,ebp
和esp
始终是一样的,所以直接pop ebp
,此时ebp
中就存放了call
调用前,main
的ebp
func
中使用过局部变量,则进入func
之后,首先会sub esp,一些空间
来给func
使用,然后结束时候,使用leave => mov esp,ebp、pop ebp
,先将esp
值变为ebp
的值,此时两个一样,然后pop ebp
之后,ebp
中就存放了call
调用前,main
的ebp
简单的就是如下代码
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