当前位置: 首页 > news >正文

滴水逆向 Day05:函数嵌套调用的内存布局(图文版)

0基础小白学逆向记录贴,一起来学逆向。https://mp.weixin.qq.com/s/EPDY6i2-R-WQI101KTJvtg

一、核心目标:搞懂一个函数调用另一个函数时,栈空间是怎么变化的、参数怎么传递、返回值怎么回来、ebp/esp 到底在干什么。


二、示例代码(C 语言)

我们用一个最简单的两层嵌套调用来分析:

#include<stdio.h>int plus(int x, int y){return x+y;}int plus1(int x, int y , int z){int m;m=plus(x,y);return m+z;}int main(){int r ;r=plus1(1,2,3);printf("%d",r);return 0;}

调用关系:main → plus2 → plus1这是最典型的函数嵌套调用


三、关键知识点(必须理解)

  1. 函数调用统一遵循栈规则

    • 参数从右向左入栈

    • 先压入返回地址

    • 保存旧 ebp,ebp = esp建立栈帧

    • 局部变量在 ebp 上方

  2. 嵌套调用本质:就是在一个函数的栈帧内部,再开启一个新的子函数栈帧。调用完子函数,栈会恢复到调用前的状态,继续执行父函数。

  3. 整个过程:

    • main

      调用plus2(1,2,3)

    • plus2

      内部又调用plus1(x,y)

    • plus1

      计算完成,返回结果给plus2

    • plus2

      再加上 z,返回给main

    • 最终r = 1+2+3 = 6


四、内存布局(栈空间)说明

1. 整体栈走向

esp始终指向栈顶

  • ebp

    用于定位当前函数的栈底,方便访问参数和局部变量

2. 调用 plus2 时的栈布局

  • 从右往左入栈参数:321

  • 压入main中调用plus2返回地址

保存旧 ebp(main 的 ebp)

  • 新 ebp = esp,建立 plus2 栈帧

  • 分配局部变量空间(如 int m)

3. 嵌套调用 plus1 时

在 plus2 函数内部,再次执行完整调用流程:

  • 从右往左入栈:yx

  • 压入 plus2 内部的返回地址

  • 保存当前 ebp(plus2 的 ebp)

  • 新 ebp = esp,建立 plus1 栈帧

  • 执行计算,通过 eax 带回返回值

4. 返回过程

  • plus1

    执行完毕,销毁自己的栈帧,回到 plus2

  • plus2

    拿到返回值,继续计算,再销毁自己栈帧,回到 main

  • 最终结果存入 main 中的变量 r

一句话总结:嵌套调用,就是栈帧的层层嵌套;返回时,栈帧层层弹出恢复。


五、总结

函数嵌套调用的完整流程

  1. 参数入栈顺序:从右向左

  2. 栈帧结构:旧 ebp → 返回地址 → 参数 → 局部变量

  3. 嵌套本质:栈帧里再套栈帧,调用完逐层恢复

理解这套内存布局,是后续看懂反汇编、栈溢出、HOOK、函数调用约定的基础。

关注"0基础学逆向",一起学逆向

http://www.jsqmd.com/news/669093/

相关文章:

  • Elasticsearch 多标签高亮配置:多关键词不同颜色高亮完整实战
  • 告别截图!用mutool draw命令把PDF批量转成高清PNG图片(附Python脚本)
  • Verilog实战:用SystemVerilog验证你的跨时钟域(CDC)设计是否可靠
  • 智慧金融——解读DeepSeek金融审计应用场景1000问【附全文阅读】
  • 别再买错USB转串口模块了!手把手教你读懂CH340G芯片引脚与典型电路
  • intv_ai_mk11实战教程:用intv_ai_mk11构建内部知识库问答前端原型
  • 告别二维码!用NXP NTA5332 NFC标签,5分钟打造你的智能家居自动化触发器
  • 备案后别忘了这件事!手把手教你为已备案域名配置HTTPS(阿里云SSL证书+Tomcat)
  • 今天爬山去了 , 所以就刷了一道力扣
  • 用于 VoIP 隐写分析的校准感知跨视图注意力网络
  • Windows 安装云崽
  • org.openpnp.vision.pipeline.stages.Normalize
  • 锁相环调频系统避坑指南:VCO中心频率不稳、环路失锁怎么办?
  • Elasticsearch 磁盘水位阈值设置:最合理配置 + 生产实战
  • XFS大硬盘+NFS共享踩坑记:一个fsid=0参数如何避免‘Stale file handle’
  • 别再到处找资源了!一份网盘搞定Keil MDK ARM+C51双环境搭建(含STM32F1/F4芯片包)
  • 如何实现超低延迟音频采集:OBS-ASIO插件完整配置指南
  • 拒绝 API 延迟!侠客工坊如何基于端侧 SLM 重构移动端“数字员工”的视觉操作架构
  • 2026年梧州市代运营引流获客:定义、流程与团队选择标准百科解读
  • TCC分布式事务代码
  • C语言:数组名的理解(size of 和strlen示例)
  • vector模拟实现
  • 保姆级教程:用华为ENSP模拟器搞定企业级有线无线网络(含S5700/AC6605配置)
  • Python学习-数据结构与算法02
  • API的基础讲解
  • CTF SHOW WEB 4(无法查看源代码)
  • 【仅限首批200名AI架构师】:获取AGI融合系统故障诊断矩阵(含17类典型冲突模式+动态权重调优公式)
  • 抓包方案分享
  • 手把手教你:在UVM验证环境中安全使用disable fork管理并发线程
  • 当代码几乎免费时,程序员还剩下什么?