逆向知识第十讲,循环在汇编中的表现形式,以及代码还原
逆向知识第十讲,循环在汇编中的表现形式,以及代码还原
一丶do While在汇编中的表现形式
1.1高级代码:
#include "stdafx.h"int main(int argc, char* argv[]) {int nSum = 0;int i = 0;do {nSum = nSum + i;} while (i <=100);return 0; }
高级代码很简单,只是一个简单的求1~100的累加
1.2 Debug版本下的汇编表现形式
代码定式很简单
ADDR
.....do While逻辑代码块
xxxx 条件
JXX Addr
注意,在 do while中, 汇编代码的语义和高级代码语义是一样的.
比如我们以前的if jle的时候(也就是小于等于) 我们的if则会写成 > (jg)也就是反向还原,而循环地址向上增量的条件不用取反
代码还原:
do
int nVar4 = nvar4 + nvar8;
while(nVar8 <= 100) 注意条件,jle就是jle
还需要注意的是,地址是低地址,也就是跳转是往上跳转的
1.3 Release版本下的优化
高级代码:
int main(int argc, char* argv[]) {int nSum = 0;int i = 0;do {nSum = nSum + i;i++;} while (i <= argc);printf("HelloWorld");printf("HelloWorld");printf("HelloWorld");printf("HelloWorld");printf("HelloWorld");printf("HelloWorld");return argc; }
Release版本下的汇编代码:
代码也是最精简的了.和Debug一样,只不过优化为寄存器使用了.效率更快.
二丶while 循环在汇编中的表达形式
2.1高级代码:
#include "stdafx.h"int main(int argc, char* argv[]) {int nSum = 0;int i = 0;while(i <= 100) {printf("%d",nSum);nSum = nSum + i;}return argc; }
2.2 Debug版本下的汇编表达形式
请注意,while循环回合if else的汇编代码类似
但是又有质的不同,在if else中, else语句块,其JMP跳转的地址是往增量地址跳转的,而在while中其跳转的地址是往减量地址跳转的
汇编代码定式:
LowAddr
jxxx HighAddr
....... while语句块代码
JMP LowAddr
HighAddr
可以看出,while循环有两个跳转
上下界的分别
jg highaddr 找到while循环的下界
jmp lowaddr 找到while循环的上界
注意,这里的定式我并没有写条件,因为条件只要会影响标志位即可,有可能不是cmp,反正能影响标志位的即可.
代码还原:
while(nvar8 <= 100) (语义相反,只有do while的语义按正常还原 jg(高于),相反则是小于等于)
{
printf("%d",nvar4);
nvar4 = nvar4 + nvar8;
}
PS: 在第一个跳转之前的所有代码,都作为while循环中的条件
三丶for循环在汇编中的表达形式
3.1高级代码:
int main(int argc, char* argv[]) {int nSum = 0;int i = 0;for(i = 0; i < 100;i++) {printf("%d",nSum);nSum = nSum + i;}return argc; }
3.2Debug下的汇编表现形式
for循环因为有了 步长的概念,所以Debug下的代码可能有点难看懂
说下代码定式把
JMP forCMPaddr 跳转到代码比较
FOR_STEMAddr
for_Step 其代码是步长代码 (i++ j++)
forCMPaddr
for_cmp 代码比较
jxxx forEndAddr 和while循环类似,跳转到结尾,条件不成立则退出,看此跳转则找到for循环的下界
.....循环体
JMP FOR_STEMADDR 执行完循环体之后,执行步长代码.
FOR_ENDADDR
修改为代码定式模样
代码还原:
第一步: JMP FOR_CMP 所以找到for循环的比较代码位置
第二步: 找到jxx For_end 找到for循环的下界.则当前位置是代码的上界
第三步: jmp FOR_STEP 找到for循环的步长部分
for(nVar8 = 0; nVar8 < 100; nVar8++)
{
printf("%d",nVar4);
nVar4 = nVar4 +nVar8;
}
还原for的时候,主要是找到 比较部分,代码步长部分.以及循环体部分.
浅谈Release版本下的循环
上面版本都是Debug版本下的表达形式,但是Release版本下则会优化
主要从几方面来讲解
1.减少跳转的优化方式
2.常量传播的优化方式
3.代码外提的优化方式
4.强度削弱的优化方式
一丶While在汇编中的Release的优化
因为dowhile是最优化的方式了,所以没有更好的优化方式了
1.1 while循环下的减少跳转的优化方式
首先说下为什么减少跳转.
我们知道,do while就一个跳转,而while在Debug版本下是两个跳转,for循环在Debug版本下是3个跳转
那么如果减少了跳转,那么则会大大的增加效率.
1.1.2高级代码:
#include "stdafx.h"int main(int argc, char* argv[]) {int nSum = 0;int i = 0;while(i <= argc) {nSum = nSum + i;i++;} printf("HelloWorld");printf("HelloWorld");printf("HelloWorld");printf("HelloWorld");printf("HelloWorld");printf("HelloWorld");return argc; }
1.1.3 Release版本下的代码
看到这个汇编代码,我们发现jl的时候,是和if相似的.
而 jle的时候,地址是减量跳转,则是do while的条件
那么此时我们可能会还原成 if里面包含do while
但其实,也是这样还原的.这样是为了减少跳转
说下为什么减少跳转
1.首先判断,如果不成立,则不执行循环语句块
2.当第一个条件成立,则循环语句块,此时我知道你的条件是成立的,所以我只需要变为do while去循环即可.
这样就减少跳转了,比如我们的while循环20000次,那么跳转就要 *2,那么此时变成if 包含do while的时候
那么此时跳转就是 200001次,大大的优化了效率
还原代码:
if(argc >= 0)
{
do
ecx = ecx + eax;
eax ++;
while(eax <= argc )
}
识别此类的循环要注意
1.首先if中的条件和 do while中的条件有相关性
2.注意如果是dowhile那么其地址跳转是往减量跳转.
当然如果你喜欢还原为while那么也是可以了
while (eax <= argc)
{
ecx = ecx + eax;
eax ++;
}
第一种还原方式,如果条件有相关性,则还原出的汇编代码是和这个的二进制代码是一摸一样的.2.
1.2 常量传播下的优化方式
在常量传播下,则直接变成了do while了.
看下高级代码:
int nSum = 0;int i = 0;while(i < 100){nSum = nSum + i;i++;}
常量传播后,则i变成了常量.所以直接变成do while即可.
Release汇编
1.3代码外提优化
高级代码:
int nSum = 0;int i = 0;while(i < argc /7){nSum = nSum + i;i++;}
其中 argc/7并没有在循环体中使用所以可以单独提取出来.
int temp = argc / 7;
while(i < temp)...
Release版本下的汇编代码:
上面则是代码外提的情况,此时还原代码也可以还原为 if 包含do while的形式
PS: 代码外提不支持函数
比如
for(i = 0; i < strlen("hello");i++) ... 其中 strlen是函数,所以不会代码外提
二丶减少跳转优化(For循环)
for循环在Debug版本下有三层跳转.那么减少跳转之后,则和上方while一样,也变为if包含 do While了.
PS: 注意,在常量传播下,所有的循环都变成了do while类型去执行循环了
PS: 注意,代码外提的情况下,所有循环都变成 if 加 do while的形式,代码放到外面执行了.
2.1高级代码:
int nSum = 0;int i = 0;for (i = 0; i < argc; i++){nSum = nSum + i;i++;}
Release版本下的汇编
其也变成了if 包含do while循环的形式
还原代码同上
.
循环中的Break和Continue的区别
循环中有continue和break
其中continue是跳过当前循环进行下一次循环.
break是跳出循环体
所以我们知道了,break会跳出循环.而continue不会跳出循环.\
一丶观看For循环的Debug版本.和Releas版本,观察continue和break的区别.
1.1高级代码
int nSum = 0;int i = 0;for ( i = 0; i < argc ;i++){nSum = nSum + i;if(argc == 0){break;}else if(argc == 1){continue;}i++;}
1.2Debug汇编break和Continue的表达形式.
break执行会跳出循环体,而continue则会跳转到补偿代码执行
1.3Release版本下的汇编
也可以看出,break会跳出循环,而continue则不会跳出循环
总结:
1. do while总结
Debug版本下
1.do while有一次跳转,其中跳转的代码是往减量地址跳转(低地址)
2.还原心得,因为其地址往减量跳转,所以汇编语义与高级语言语义一样,正常代码还原
Release版本下
1.常量传播下,直接就是do while了,和Debug版本下一样,一次跳转,还原方式正常跳转
2. While循环总结
Debug版本下
1.有两次跳转,代码特别像 if else,但是又有质的不同,其中第一次跳转其地址是往增量跳转,第二次跳转其地址是往减量地址跳转(if else则都是往增量地址跳转)
2.还原心得,第一次跳转之前的代码都作为while循环中的条件,其条件是反向还原,语义相反.第一次跳转可以找到while的下界,其当前位置则是while的上界.
Release版本下
1.常量传播的优化方式下,其代码会变成do while执行
2.代码外提的情况下,其代码会变成if 包含 do while执行,其中代码的条件外提.注意,函数不可以作为代码外提
3.还原心得: 如果是 if包含do while的形式,则判断两个条件是否有相关性.如果有相关性则可以还原成while或者自己喜好的 if +do while的形式.
4.第一次跳转是相反语义,第二次跳转是正常语义.
3.for循环总结
Debug版本下
1.for循环因为有步长的问题,所以多一次跳转. 其中 第一步跳转到 条件位置处,第二此跳转则判断条件是否成立,不成立则退出,此时找到for的下界,当前位置可以当做if的上界.
条件成立之后代码继续执行,则此时又来了一次跳转,此跳转跳转到步长执行代码
Release版本下
1.常量传播方式下 代码变为do while执行
2.代码外提情况下,代码变成了 if + do while的形式
转载于:https://www.cnblogs.com/iBinary/p/7869304.html
逆向知识第十讲,循环在汇编中的表现形式,以及代码还原相关推荐
- 逆向知识第七讲,三目运算符在汇编中的表现形式,以及编译器优化方式
一丶编译器优化方式 首先说一下编译器优化方式. 1.常量折叠 2.常量传播 3.复写传播 4.公共表达式 5.去掉不可达到分支 6.顺序代替分支 7.数学变化 8.代码外提 9.减少变量. 10 强度 ...
- 计算机基础知识第十讲,计算机文化基础(第十讲)学习笔记
计算机文化基础(第十讲)学习笔记 采样和量化PictureElement Pixel(像素)(链接: 采样的实质就是要用多少点(这个点我们叫像素)来描述一张图像,比如,一幅420x570的图像,就表示 ...
- 逆向知识十三讲,汇编中数组的表现形式,以及还原数组
讲解数组之前,要了解数组的特性 1.数据具有连续性 2.数据类型相同 比如: int Ary[3] = {0,1,2}; 我们可以看出,上面定义的数组,数据是连续的,其中每个数据类型大小都是int类型 ...
- 逆向课程第四讲逆向中的优化方式,除法原理,以及除法优化上
一丶为什么要熟悉除法的优化,以及除法原理 是这样的,在计算机中,除法运算对应的汇编指令分为 DIV(无符号除法指令) 以及 IDIV(有符号除法指令). 但是,除法指令的执行周期较长效率很低.所以编译 ...
- 学习逆向知识之用于游戏外挂的实现.第二讲,快速寻找植物大战僵尸阳光基址.以及动态基址跟静态基址的区别...
通过游戏外挂,学习逆向技术之快速寻找植物大战僵尸阳光基址.以及动态基址跟静态基址的区别 一丶静态基址. 动态基址. 基址的区别 通过上一讲超级马里奥的游戏外挂技术制作.我们学习到了静态基址.以及观看内 ...
- 逆向知识之CS辅助/外挂专题.2.实现CS1.6透视原理
逆向知识之CS辅助/外挂专题.2.实现CS1.6透视原理 一丶透视简介 我们涉及到FPS游戏.免不了说透视.自瞄什么的. 在CS1.6中. 有OpenGl.也有D3D. 透视的方法很多. gl透视(也 ...
- 第十讲:如何去改变 第十一讲:改变——养成良好习惯 第十二讲:改变设定目标
(注:此为课程第十课,更新于2017年5月27日) 早上好!今天要讲的是改变. 上节课结束的时候,我们谈到两种不同的变化.第一种方式是渐进式的,好像滴水穿石,要花时间的.一点一点的.慢慢的:第二种方式 ...
- 树莓派ARM汇编语言编程十讲(第1讲)
内容简介 树莓派单板机(Raspberry Pi Single Computer)是一种极了不起的产品,用户可以以非常低的成本获得一个Linux环境并带GPIO硬件扩展的迷你计算机系统.新一代树莓派4 ...
- 趣谈网络协议笔记-二(第十讲)
趣谈网络协议笔记-二(第十讲) UDP协议:因性善而简单,难免碰到"城会玩" 自勉 如果手上没有剑,我就无法保护你.如果我一直握着剑,我就无法抱紧你.--<Bleach> ...
最新文章
- 怎么自学python编程-零基础如何自学编程?
- SAP中的Currency Converting Factor
- python 利用pyinstaller 编译.exe文件过程中编写完的.exe文件执行过程中闪退
- Mac Eclipse安装lombok
- mysql 日期列表_MySQL 生成日期表
- 1350B. Orac and Models
- dev 中 gridcontrol1 滚动条重绘_浏览器的重绘和回流(Repaint amp; Reflow)
- 整数区间(信息学奥赛一本通-T1324)
- 假如让你来设计SSL/TLS协议,你要怎么设计呢?
- 总有几位老师让你一生感激不尽----我的大学老师
- HDU1418 抱歉【数学】
- AngularJs学习的前景及优势
- 因子分析以及SPSS实现
- 手机基于蓝牙JDY-31蓝牙模块与52单片机串口通信
- 相似度计算方法(一) 皮尔森相关系数
- 百度富文本编辑器php设置图片上传,手把手教你百度富文本编辑器的相关配置包括图片上传(for jsp)...
- 光纤熔接机市场现状及未来发展趋势
- 用html5画瀑布图,漂亮的Excel瀑布图,竟然如此简单~~
- 如何在被伽卡他卡教师端控制时解除控制
- 好好说话之unlink