【reverse】逆向7 堆栈图

前言

本章就是开始画堆栈图来打基础拉,堆栈熟悉了之后就可以开始C语言的逆向了。

这一章使用的exe文件,我已经上传到了我的个人网盘中,点击下载

1、准备工作

先看这张内容

我们首先打开OD,使用F3打开helloworld.exe程序

然后在任意位置,ctrl+G打开窗口,输入0x401168地址,然后点击OK,自动跳转到这里

然后在这个地址上打一个断点(F2)

然后我们F9运行,让程序运行到这里

然后就是我们画堆栈图的时候了

2、画堆栈图

我们先在OD上看esp栈顶和ebp栈底的内存地址

根据这个内存地址我们可以画出开始时候的堆栈图(这里的黄色表示中间有一定距离,不是每格4字节)

然后我们运行push 0x2 和 push 0x1的汇编指令

运行之后的堆栈图变成了这样

然后下一步的汇编指令是call 0040100A,是我们刚刚学习的call指令,会让我们eip指向0040100A,也就是跳转到这里,并且将这个00401171地址push进堆栈中

我们这里按F7步入

所以堆栈图如下图

然后我们发现我们进入的地址0040100A的语句是jmp 00401040,也就是跳转到00401040,这里没有堆栈操作,我们直接F8步过

接下来我们jmp到了一段比较长的地方,这里我们逐步分析

首先是push ebp,这个操作让堆栈存入ebp的地址,而此时我们的ebp的地址为0019FF30,所以堆栈图如下

这一步执行完了之后,就是mov ebp,esp

这一步的的作用就是将esp的值传给ebp,让ebp = esp,堆栈图如下

然后是sub esp,0x40

这一步是让esp栈顶上升0x40个单位,也就是16个4字节,也就是在堆栈上升16位,堆栈图如下

然后就是push ebp,esi,edi,将ebp、esi、edi这些寄存器存放的东西放入堆栈中,起到保护现场的作用

堆栈图如下

下一步lea edi,dword ptr ss:[ebp-0x40],这句汇编就是让edi存储ebp-0x40之后的内存地址

当然,lea指令是不会影响堆栈的

这里的ebp-0x40是不是非常熟悉?就在刚才,esp也是减去了0x40

所以这个时候的堆栈图如下,edi是存储了0019FE94这个地址的

然后就是

mov ecx.0x10
mov eax,0xcccccccc
rep stos dword ptr es:[edi]

这三句话其实要一起说明

首先ecx是存储循环次数的寄存器,可以看出来这里循环0x10,也就是16次

然后执行mov eax,0xcccccccc,就是让eax这个寄存器存储0xcccccccc这个值

最关键的rep stos dword ptr es:[edi],就是让edi存储eax的值,每次存完的数都会根据DF标志寄存器来决定存储地址+-4,DF=0就是加,DF=1就是减

这上面三句就是重复16次,也就是让堆栈中存储16个缓冲,组成缓冲区

堆栈图如下

然后就是mov eax,dword ptr ss:[ebp+0x8],这句话就是让eax存储ebp+0x8地址中的数据,也就是我们最开始存储的1

add eax,dword ptr ss:[ebp+0xC],这句话就是让eax中原有的数据加上ebp+0xC地址中的数据,也就是我们最开始存储的2,所以eax中是1+2,现在eax=0x3

这一步,堆栈图没有发生改变,但是这两句话却是函数核心,就是两参数相加

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

然后就是pop edi,pip esi,pop ebx

这三句就是为了还原现场。

还记得我们在刚刚开始的时候push了这三个寄存器吗,现在我们把他们pop出来,还原到最开始的状态。

堆栈图如下

然后就是mov esp,ebp

这句话就是把ebp的值赋给esp,这样就是esp = ebp了

堆栈图如下

然后就是pop ebp,这句话就是把现在栈顶指向的返回地址pop给ebp

我们其实也记得,刚刚在call执行完,存完了紫色的返回地址之后,我们push了ebp

这个时候也就是让我们的ebp返回到原来的地址上去

堆栈图如下

然后就是函数的最后 retn

retn就相当于指令 pop eip,就是把返回地址给eip,而eip就是当前指向地址,这就是最后的返回地址

堆栈图如下

当我们执行完retn之后,发现我们的esp并没有回到函数开始前的模样,现在还在绿色的位置

而我们要知道,每个程序都保证了堆栈平衡,也就是,函数运行完了之后,esp和ebp的位置要和运行之前是保持一致的。

我们来看看retn完了之后,OD的页面

eip = 00401171

这里的add esp,0x8就是让esp的地址加8

这样我们的esp就回到了原来的位置,实现了堆栈平衡

这种在函数执行完了之后实现的堆栈平衡,叫做外平栈

即——谁调用函数,谁平衡堆栈

堆栈图如下

3、总结

首先我们认清计算机中函数的概念:

计算机的函数,是一个固定的一个程序段,或称其为一个子程序,它在可以实现固定运算功能的同时还带有一入口和一个出口,所谓的入口,就是函数所带的各个参数,我们可以通过这个入口,把函数的参数值代入子程序,然后根据出口返回

汇编中的函数:

来张好看点的

函数的入口

函数的出口

提醒:

  1. 这里ebp+4是返回地址(在pwn中是要考的!!!)

  2. 函数虽然有入口和出口,但是入口不一定需要传值,出口也不一定要返回(void)

  3. 传参不一定是push,还可能是寄存器传参等等...

  4. 返回值也不一定只通过寄存器返回,也可以通过内存返回

一张windows堆栈的补充图:

【reverse】逆向7 堆栈图的更多相关文章

  1. 【 D3.js 高级系列 — 3.0 】 堆栈图

    堆栈图布局(Stack Layout)能够计算二维数组每一数据层的基线,以方便将各数据层叠加起来.本文讲解堆栈图的制作方法. 先说说什么是堆栈图. 例如,有如下情况: 某公司,销售三种产品:个人电脑. ...

  2. 针对JCC指令练习的堆栈图

    堆栈图,主要目的就是练习一下JCC指令的熟练度,供参考 版权声明:本文为博主原创文章,转载请附上原文出处链接和本声明.2019-09-10,23:41:41.作者By-----溺心与沉浮----博客园 ...

  3. 使用RetionalRose根据现有的java工程逆向生成类图

    1.进入RetionalRose选择J2EE模板 2.在菜单栏选择tools->java/j2EE->reverse engineer 3.编辑路径Edit CLASSPATH选择要生成类 ...

  4. 如何将C++代码逆向生成类图 (VS2013)

    1. 将代码添加到VS2013工程中: 2. 切换到"类视图": 3. 选中项目 右键"视图"->"查看类图". 如果项目文件太多的话 ...

  5. Mac逆向--思维导图

  6. 逆向学习周记-C语言空函数

    实验环境:WIN7虚拟机 软件:VC6 首先在VC6里面写一个空函数Fun(): F7编译运行一下,没有出错,接着在函数处使用F9下断点,使程序运行到Fun函数时停下. 接着F5开始运行这个程序 程序 ...

  7. FusionCharts-堆栈图、xml格式、刷新数据、添加事件link、传参

    *起因* 本来想用Chart.js来搞图表的, 但是来了个新需求,想搞的华丽点,毕竟对Chart.js来说,实现有点难度, *做出的改变* 最终选择了FusionCharts, *难点* 网上关于Fu ...

  8. 在 Visual Studio 中调试时映射调用堆栈上的方法

    本文转自:https://msdn.microsoft.com/zh-cn/library/dn194476.aspx 1.创建代码图,以便在调试时对调用堆栈进行可视化跟踪. 你可以在图中进行标注以跟 ...

  9. 20145230GDB调试汇编堆栈过程分析

    20145230GDB调试汇编堆栈过程分析 分析过程 出现的问题:一开始无法编译,是因为我们的Linux中没有安装一个库. 进入之前先设置断点,之后disassemble可以获取汇编代码,用i r指令 ...

随机推荐

  1. Python小组作业:基于yolov5的口罩佩戴识别

    Python老师给了三个小组项目:1.自身专业问题 2.人工智能 3.游戏或者小工具 提前告知了,写游戏不好拿高分,小工具又不能展示自己的水平.大一刚来也没碰到什么专业问题,于是经过讨论,决定了做人工 ...

  2. CF83A Magical Array 题解

    Content 有一个长度为 \(n\) 的序列 \(a_1,a_2,a_3,...,a_n\).定义一个"神奇数组"为在上面的序列中最大值和最小值相等的子序列.求出这个序列中&q ...

  3. CF1036D Vasya and Arrays 题解

    Content 给定两个长度分别为 \(n\) 和 \(m\) 的数列 \(A,B\).你需要将两个数列都恰好分成 \(k\) 份,使得两个数列中第 \(i(i\in[1,k])\) 份的元素和对应相 ...

  4. CF140D New Year Contest 题解

    Content 小 G 想打一场跨年比赛,比赛从下午 \(18:00\) 开始一直持续到次日清晨 \(6:00\),一共有 \(n\) 道题目.小 G 在比赛开始之前需要花费 10 分钟考虑这些题目的 ...

  5. shiro验证时,当authenticationStrategy为AllSuccessfulStrategy时

    shiro验证时,当authenticationStrategy为AllSuccessfulStrategy时,如果某一个验证出错,那么 PrincipalCollection principalCo ...

  6. Vue页面内公共的多类型附件图片上传区域并适用折叠面板

    在前端项目中,附件上传是很常用的功能,几乎所有的app相关项目中都会使用到,一般在选择使用某个前端UI框架时,可以查找其内封装好的图片上传组件,但某些情况下可能并不适用于自身的项目需求,本文中实现的附 ...

  7. Android NDK开发篇:如何使用JNI中的global reference和local reference

    JNI提供了一些实例和数组类型(jobject.jclass.jstring.jarray等)作为不透明的引用供本地代码使用.本地代码永远不会直接操作引用指向的VM内部的数据内容.要进行这些操作,必须 ...

  8. 【LeetCode】Island Perimeter 解题报告

    [LeetCode]Island Perimeter 解题报告 [LeetCode] https://leetcode.com/problems/island-perimeter/ Total Acc ...

  9. 在Latex 下写毕业论文

    目录 配置 TeXlive 论文模板 TeXstudio 写作 特殊环境 算法 定理.定义 编译 可能出现的问题 参考文献 缺少volume 学位论文 配置 TeXlive 下载了最新的texlive ...

  10. 【Azure 应用服务】探索在Azure上设置禁止任何人访问App Service的默认域名(Default URL)

    问题描述 总所周知,Azure App Service服务会默认提供一个 ***.chinacloudsites.cn为后缀的域名,但是该域名由上海蓝云网络科技有限公司备案,仅用于向其客户提供 Azu ...