• 函数调用栈


    博客网址: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
    
  • 相关阅读:
    类和对象10:对象访问方法
    maven运行spring boot项目
    Floxif蠕虫病毒分析与处置
    复习 --- QT服务器客户端
    0201安装报错-hbase-大数据学习
    将写的项目部署到Linux服务器上
    Java多线程并发编程
    Git - 异常处理 : Git | SSL certificate problem: certificate has expired
    harmony 鸿蒙系统学习 安装ohpm报错 ohpm install failed
    【重温基础算法】内部排序之希尔排序法
  • 原文地址:https://www.cnblogs.com/shilinkun/p/16272423.html