12558网页游戏私服论坛

 找回密码
 立即注册
游戏开服表 申请开服
游戏名称 游戏描述 开服状态 游戏福利 运营商 游戏链接
攻城掠地-仿官 全新玩法,觉醒武将,觉醒技能 每周新区 经典复古版本,长久稳定 进入游戏
巅峰新版攻 攻城掠地公益服 攻城掠地SF 新兵种、新武将(兵种) 进入游戏
攻城掠地公 散人玩家的天堂 新开 进入游戏
改版攻城掠 上线即可国战PK 稳定新区 全新改版,功能强大 进入游戏
少年江山 高福利高爆率 刚开一秒 江湖水落潜蛟龙 进入游戏
太古封魔录 开服送10亿钻石 福利多多 不用充钱也可升级 进入游戏
神魔之道 签到送元宝 稳定开新区 送豪华签到奖励 进入游戏
神奇三国 统帅三军,招揽名将 免费玩新区 激情国战,征战四方 进入游戏
龙符 三日豪礼领到爽 天天开新区 助你征战无双 进入游戏
王者之师 免费领豪华奖励 免费玩新区 6元送6888元宝 进入游戏
三国霸业 战车-珍宝-觉醒-攻城掠地SF-全新玩法 免费玩新区 攻城掠地私服 进入游戏
手游私服盒子 各类免费游戏 0.1折送海量资源 各类手游私服 进入游戏
皇家MU2 《奇迹 2:传奇》韩国网禅公司《奇迹》正统续作。 3D锁视角Mmrpg 暗黑3+传奇+流放之路+奇迹 进入游戏
查看: 315|回复: 0

逆向基础笔记七 堆栈图(重点)

[复制链接]

345

主题

345

帖子

700

积分

实习版主

Rank: 7Rank: 7Rank: 7

积分
700
发表于 2021-5-7 23:59:21 | 显示全部楼层 |阅读模式
继续更新个人的学习笔记,
其它笔记传送门
逆向底子笔记一 进制篇
逆向底子笔记二 数据宽度和逻辑运算
逆向底子笔记三 通用寄存器和内存读写
逆向底子笔记四 堆栈篇
逆向底子笔记五 标记寄存器
逆向底子笔记六 汇编跳转和比较指令
逆向底子笔记八 反汇编分析C语言
逆向底子笔记九 C语言内联汇编和调用协定
逆向底子笔记十 汇编寻找C程序入口
逆向底子笔记十一 汇编C语言基本类型
逆向底子笔记十二 汇编 全局和局部 变量
逆向底子笔记十三 汇编C语言类型转换
逆向底子笔记十四 汇编嵌套if else
逆向底子笔记十五 汇编比较三种循环
逆向底子笔记十六 汇编一维数组
逆向底子笔记十七 汇编二维数组 位移 乘法
逆向底子笔记十八 汇编 布局体和内存对齐
逆向底子笔记十九 汇编switch比较if else
逆向底子笔记二十 汇编 指针(一)
逆向底子笔记二十一 汇编 指针(二)
逆向底子笔记二十二 汇编 指针(三)
逆向底子笔记二十三 汇编 指针(四)
逆向底子笔记二十四 汇编 指针(五) 系列完结
这篇笔记是前面笔记的一个阶段性应用,会用到不少前面笔记的知识点,也是逆向学习中极其重要的部门,因此篇幅较长,盼望对大家能有所帮助
堆栈图

首先给定一段反汇编代码,分析该段代码的堆栈的变革情况,并绘制出堆栈图
函数调用

00401168  |.  6A 02         push 0x20040116A  |.  6A 01         push 0x10040116C  |.  E8 99FEFFFF   call HelloWor.0040100A00401171  |.  83C4 08       add esp,0x8CALL内部

00401040  /> \55            push ebp00401041  |.  8BEC          mov ebp,esp00401043  |.  83EC 40       sub esp,0x4000401046  |.  53            push ebx00401047  |.  56            push esi00401048  |.  57            push edi00401049  |.  8D7D C0       lea edi,dword ptr ss:[ebp-0x40]0040104C  |.  B9 10000000   mov ecx,0x1000401051  |.  B8 CCCCCCCC   mov eax,0xCCCCCCCC00401056  |.  F3:AB         rep stos dword ptr es:[edi]00401058  |.  8B45 08       mov eax,dword ptr ss:[ebp+0x8]0040105B  |.  0345 0C       add eax,dword ptr ss:[ebp+0xC]0040105E  |.  5F            pop edi                                  ;  HelloWor.004011710040105F  |.  5E            pop esi                                  ;  HelloWor.0040117100401060  |.  5B            pop ebx                                  ;  HelloWor.0040117100401061  |.  8BE5          mov esp,ebp00401063  |.  5D            pop ebp                                  ;  HelloWor.0040117100401064  \.  C3            retn开始分析

分析流程较为冗长,可能会有些乏味,可以先看最后的流程总结,再来看分析的细节
我们现在开始逐语句分析堆栈的变革情况:
实行前


寄存器状态


堆栈内容


初始堆栈图

我们观察堆栈的情况:
此时ESP:0012FF34        EBP:0012FF80
结合寄存器和堆栈内容绘出简易堆栈图

实行中

压入参数

00401168  |.  6A 02         push 0x2                        

可以看到实行后ESP镌汰了4=0012FF30        并且0012FF30里的内容为2,这就是所谓的入栈操纵
0040116A  |.  6A 01         push 0x1                        

可以看到实行后ESP又镌汰了4=0012FF2C ,并且0012FF2C里的内容为1
上面的两条push语句是将两个立刻数 2和1压入到堆栈中,我们可以画出对应的堆栈图:

CALL指令

0040116C  |.  E8 99FEFFFF   call HelloWor.0040100AF7单步步入



可以看到CALL之后跳转到了0040100A,并且esp又镌汰了4=0012FF28
而且我们可以注意到此时堆栈中0012FF28存放的内容是:00401171正好是我们call指令的下一行指令的地址
0040116C  |.  E8 99FEFFFF   call HelloWor.0040100A00401171  |.  83C4 08       add esp,0x8所以应证了前面所学的call指令会将要返回的地址压入栈中来保存现场
此时的堆栈图为

接着我们就跳转到了call的内部
CALL内部指令

初始化堆栈


00401040  /> \55            push ebpESP变革

堆栈内容

EBP被压入到堆栈中,此时堆栈图为

接着实行
00401041  |.  8BEC          mov ebp,espebp赋值为esp,此时堆栈图为

接着实行
00401043  |.  83EC 40       sub esp,0x40

将esp的值减去0x40=64,我们这里的相差的数据宽度为4即16,64/4=16,因此堆栈图里多了16格(蓝色部门),这种操纵常被叫做提拔堆栈,此时堆栈图为:

我们可以发现提拔完堆栈以后,堆栈的数据有些★意义不明★,这是因为堆栈中存放的是临时的数据,可能是之前使用时没有清理的垃圾数据
接着实行
00401046  |.  53            push ebx00401047  |.  56            push esi00401048  |.  57            push edi将三个通用寄存器压入堆栈,用于保护现场,注意CALL之前和CALL之后,其前后环境要同等,这就是所谓的堆栈均衡

堆栈内容

根据此时的堆栈内容绘制堆栈图

接着实行
00401049  |.  8D7D C0       lea edi,dword ptr ss:[ebp-0x40]
将ebp-40所指向的内存地址赋给edi
前面我们实行了sub esp,0x40 所以这里其实就是将那时esp的地址传给了edi(就是push ebx esi edi)之前的的esp
此时堆栈图并发生没有变革
接着看下一行
0040104C  |.  B9 10000000   mov ecx,0x1000401051  |.  B8 CCCCCCCC   mov eax,0xCCCCCCCC分别给ecx和eax赋值,堆栈图依旧没有发生变革



接着看下一行
00401056  |.  F3:AB         rep stos dword ptr es:[edi]这条语句用到了我们前面所学的逆向底子笔记五 标记寄存器中的内容(如有疑惑可前往查看)
rep的作用是,重复实行 stos dword ptr es:[edi],每次实行都会使ecx-1,直到ecx为0再实行下一条语句
前面赋值ecx为0x10=16,正好对应我们堆栈图中蓝色的格子数,所以将会实行16次
stos dword ptr es:[edi]则是将eax的值赋值给edi所指向的内存地址里的值,并且每实行一次edi都会增加4(D标记位为0所以是增加)
结合前面edi==esp,这里其实是将我们提拔堆栈的那部门内存区域初始化
此时的堆栈内容为

很明显地看到原本的垃圾数据被我们初始化为了CCCCCCCC
堆栈图也酿成了

实际实行内容

接着看下面的代码
00401058  |.  8B45 08       mov eax,dword ptr ss:[ebp+0x8]0040105B  |.  0345 0C       add eax,dword ptr ss:[ebp+0xC]

根据堆栈图我们可以很清晰地看出
[ebp+0x8]正是我们call外部push的参数:1
[ebp+0xc]正是我们call外部push的参数:2
这里是将eax赋值为1,然后再给eax+2,最闭幕果eax=3
还原现场并返回

此时堆栈图依旧没有发生变革,接着看下面的语句
0040105E  |.  5F            pop edi                                  ;  HelloWor.004011710040105F  |.  5E            pop esi                                  ;  HelloWor.0040117100401060  |.  5B            pop ebx                                  ;  HelloWor.00401171出栈,还原现场,堆栈图

下一条
00401061  |.  8BE5          mov esp,ebp
还原esp,前面mov ebp,esp对应也要还原
此时堆栈图为:

继续看下一条指令
00401063  |.  5D            pop ebp                                  ;  HelloWor.00401171
将ebp出栈,恢复现场,此时的堆栈图为

最后一句
00401064  \.  C3            retn此时栈顶为

返回,相称于于pop eip
实行后

实行后的堆栈图为

实行返回后

此时返回到了

也就是之前call的下一句指令
00401171  |.  83C4 08       add esp,0x8
此时的堆栈图

我们可以发现此时的ESP和EBP又变回到了原本实行前的状态,(寄存器也一样),这就是所谓的堆栈均衡
总结

通过上面的分析,我们可以得出这段代码所处理的大致流程
可分为三个部门:压入参数、调用CALL、CALL返回后
压入参数

压入参数部门十分简朴,就是将调用CALL所需的参数压入堆栈,方便CALL内部实行时调用
这里对应的语句为
00401168  |.  6A 02         push 0x20040116A  |.  6A 01         push 0x1即这个CALL得到的参数为2和1
调用CALL

调用CALL又可以分为六个部门:

  • 提拔堆栈
  • 保护现场
  • 初始化提拔的堆栈
  • 实行实际内容
  • 恢复现场
  • 返回
提拔堆栈

对应语句为
00401040  /> \55            push ebp00401041  |.  8BEC          mov ebp,esp00401043  |.  83EC 40       sub esp,0x40将堆栈提拔了0x40
保护现场

对应语句为
00401046  |.  53            push ebx00401047  |.  56            push esi00401048  |.  57            push edi将ebx、esi、edi三个通用寄存器保存到堆栈中,前面的push ebp其实也属于保护现场
初始化提拔的堆栈

00401049  |.  8D7D C0       lea edi,dword ptr ss:[ebp-0x40]0040104C  |.  B9 10000000   mov ecx,0x1000401051  |.  B8 CCCCCCCC   mov eax,0xCCCCCCCC00401056  |.  F3:AB         rep stos dword ptr es:[edi]这里将我们提拔的堆栈中的内容全部初始化为CCCCCCCC
为什么是初始化为CC?防止缓冲溢出
CC的硬编码对应的指令为int 3,即断点
这么做有什么好处呢?当程序实行超过缓冲区时,碰到int 3就会自动停下来
实行实际的内容

对应语句为
00401058  |.  8B45 08       mov eax,dword ptr ss:[ebp+0x8]0040105B  |.  0345 0C       add eax,dword ptr ss:[ebp+0xC]就是将前面压入的参数2和1进行相加得到3
恢复现场

对应语句为
0040105E  |.  5F            pop edi                                  ;  HelloWor.004011710040105F  |.  5E            pop esi                                  ;  HelloWor.0040117100401060  |.  5B            pop ebx                                  ;  HelloWor.0040117100401061  |.  8BE5          mov esp,ebp00401063  |.  5D            pop ebp                                  ;  HelloWor.00401171与前面保护现场相对应
返回

对应语句为
00401064  \.  C3            retnCALL返回后

对应语句为
00401171  |.  83C4 08       add esp,0x8作用为均衡堆栈
逆推C语言代码

根据我们前面的分析,我们不难发现这其实就是个简朴的加法函数
int add(int x,int y){    x=x+y;        //这里的x和y分别对应压入的参数    return x;        //对应RETN 默认采用eax作为返回值的通报载体}过后感言

一个小小的加法函数其对应的汇编代码却不少,而其中的关键代码只有两句
00401058  |.  8B45 08       mov eax,dword ptr ss:[ebp+0x8]0040105B  |.  0345 0C       add eax,dword ptr ss:[ebp+0xC]其它的大部门代码重要都是为保护现场和恢复现场所服务
编译器编译出的Debug和Release版本对应的汇编代码会有所差异,但只要把握了核心思想,万变不离其宗
本笔记可能会有谬误之处,欢迎大家指出,一起探讨,共同提拔

来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
楼主热帖
回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|12558网页游戏私服论坛 |网站地图

GMT+8, 2024-11-24 16:30 , Processed in 0.078125 second(s), 32 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表