逆向课程第三讲逆向中的优化方式,以及加减乘

              逆向课程第三讲逆向中的优化方式,以及加减乘

一丶为什么要熟悉优化方式

熟悉优化方式,可以在看高级代码的时候浮现出汇编代码,以及做逆向对抗的时候,了解汇编代码混淆

优化和混淆是相反的

优化: 指的是汇编代码越少越好,让程序更快的执行

混淆: 一条汇编代码变为多条汇编代码,影响逆向人员的破解能力,但是软件的效率大大降低

二丶加减乘的常见的几种优化方式

优化方式分为:

1.常量折叠

2.常量传播

3.变量去除

这些优化方式成为窥孔优化 (有10几种后面会一一到来)

首先了解什么是常量折叠,常量传播,然后最后讲解什么是窥孔优化

1.常量折叠

介绍常量折叠,首先写一段小程序,举例子说明.

PS: 优化只有在Release版本下才会优化. Debug版本也会优化,在不影响用户调试的前提下进行优化的.

程序:

程序很简单,

常量+常量

变量+常量

变量+变量

首先常量加常量在优化中的汇编代码表现形式

我们定位入口点,查看下反汇编

自己的程序为了快速定位入口点,所以加个int 3断点,触发异常即可.

可以看出,直接变为push 0xF了,然后调用printf

这个就叫做常量折叠

常量折叠: 指的是在编译前遇到的常量,都可以进行计算的,得出一个新的常量值,这样则可以直接变为一个常量去push了

2.常量传播 或者叫做常量扩散

先看下刚才的所有汇编代码把.

首先说下这段汇编代码的意思:

push 0XF           压栈常量
push 00406030  压入格式化符号 %d,下面一样
call  00401030   调用printf
下面一样,依次类推

这个时候可能会有疑问了

我们的变量+常量,  变量加变量,为什么都变成了一个常量去push了

答:

  这个叫做常量传播: 常量传播,指的是变量在写入或者读取的时间内,没有对它做修改,或者传地址,以及重新写入(也可以理解为赋值)的动作,那么在引用这个变量的时候,可以当做常量替换

可能不太懂:

  通俗一点就是说,我用变量+变量,两个变量上面根本就没有修改过,然后也没有传入地址(传入地址代表不确定是否修改,所以不给优化,VS2013 会优化,具体自己看)所以可以用常量代替

这个时候又有一个新问题了

我们变量加常量的时候,随便变为了常量传播了,但是用常量替换了

应该是 把n换成了常量 + 常量的

就比如:

n + 6

n没有修改过,现在是0,因为常量传播的原因,变为了0

变成了

0 + 6 才对,那为什么还是push一个常量了,这个就要说下,这个是窥孔优化了.

请先转到JMP 3窥孔优化查看.

JMP 回来之后,那么此时看减法和加法一样的. 只不过需要注意的是

比如我们的高级代码为:

n - 3

那么汇编代码可能变为add -3  ,或者直接sub

当然不影响结果.

乘法:

乘法的优化分为带幂优化和不带幂优化

带幂优化: 带幂优化则是我在算乘法的时候,我可以左移几位,最终取得我们要的结果

不带幂优化: 直接指令相乘.

看下高级代码对应汇编代码:

高级代码:

对应的汇编代码:

PS看的是Debug版本,Release版本直接都常量折叠了,push的都是常量

可以看出都是有符号的相乘,不带幂的相乘

3.窥孔优化

窥孔优化,上面我们说了,变量+常量,那么变量没有修改的前提下,可以用常量代替的,

变为了常量+常量

但是优化方式是这样的

首先先看看你的变量+常量是否可以常量传播,现在能常量传播,变为了常量+常量了

其次,检查源代码有没有改变(或者标志,反正会检查)改变了,继续第二此优化,此时看到了常量+常量,接着常量折叠了.

优化就是这样的.

而且看你的变量也没有使用过,也去掉吧.

比如我们不让它常量传播怎么办,好办,直接写个空函数,然后传入地址即可.因为条件是不能传入地址,因为不确定是否会改变(2013会优化)

查看汇编代码

我们上面只要让n和m变成了不常量传播,那么此时n和m则不能常量传播,不能常量传播了,就要老老实实的该怎么做怎么做.

JMP 回去

时间: 2024-10-14 00:48:14

逆向课程第三讲逆向中的优化方式,以及加减乘的相关文章

逆向知识十三讲,汇编中数组的表现形式,以及还原数组

逆向知识十三讲,汇编中数组的表现形式,以及还原数组 讲解数组之前,要了解数组的特性 1.数据具有连续性 2.数据类型相同 比如: int Ary[3] = {0,1,2}; 我们可以看出,上面定义的数组,数据是连续的,其中每个数据类型大小都是int类型(类型也是一样的) 汇编中识别数组: 1.地址连续 2.带有比例因子寻址   (lea  reg32,[xxx  + 4 *xxxx]) 一丶一维数组在汇编中的表现形式 首先说下数组寻址公式,便于下面讲解 公式: 数组首地址 + sizeof(ty

逆向课程第五讲逆向中的优化方式,除法原理,以及除法优化下

一丶除法的优化 1.有符号被除数 / 无符号除数的情况下 高级代码为: 汇编中优化的体现形式 相比于昨天,我们发现了的 无符号 / 常量多出了点东西 无符号/常量 如果无符号/常量,那么我们还原的时候 套用公式即可 am >> n a是被除数  m是设  2n/c   等价于  m == 2n/c 无符号的情况的,n的值是2^33次方  ,n = 33 根据上面得知,  m = 0AAAAAAABh 此时求出C来即可,  C = 除数 公式: 2n / m = c 套进去得到 2^33次方 /

逆向课程第四讲逆向中的优化方式,除法原理,以及除法优化上

一丶为什么要熟悉除法的优化,以及除法原理 是这样的,在计算机中,除法运算对应的汇编指令分为 DIV(无符号除法指令) 以及 IDIV(有符号除法指令). 但是,除法指令的执行周期较长效率很低.所以编译器想进办法的用其它指令去代替除法指令. 比如: DIV 指令是100个周期 计算 2 / 2 那么可能在汇编中的表现形式是这样的 CDQ  符号扩展 DIV EDX,2 好,现在100个周期没有了 减法和加法指令,指令周期是4个那么上面的公式可以演化为 mov eax,2 sub eax,2 就算m

SQL Server 中的时间的加减和时间的比较

最近在写一个项目时,用到了时间的比较和时间的加减,在这里简单说一下,我也是刚接触数据库不久,如有说的不当之处望大家包涵,指正 一.时间的比较 开始的时候我比较时间用的是 Time>GETDATE() 简单粗暴 其实SQL Server有自带的时间比较函数,所以可以用它自带的,还安全也很方便 DATEDIFF(); 我参照的W3School 中对于DATEDIFF函数的解析,具体如下: 语法 DATEDIFF(datepart,startdate,enddate) 其中datepart是只你要比较

逆向知识第六讲,取摸优化的几种方式

逆向知识第六讲,取摸优化的几种方式 除法讲完之后,直接开始讲 % 运算符在汇编中表现形式 首先C的高级代码贴上来. 高级代码: // Tedy.cpp : Defines the entry point for the console application. // #include "stdafx.h" int main(int argc, char* argv[]) { unsigned Number; scanf("%d",&Number); //防止

逆向知识第九讲,switch case语句在汇编中表达的方式

一丶Switch Case语句在汇编中的第一种表达方式 (引导性跳转表) 第一种表达方式生成条件: case 个数偏少,那么汇编中将会生成引导性的跳转表,会做出 if else的情况(类似,但还是能分辨出来的) 1.高级代码: #include "stdafx.h" int main(int argc, char* argv[]) { switch(argc) { case 0: printf("case 0\n"); break; case 1: printf(&

逆向知识第八讲,if语句在汇编中表达的方式

一丶if else的最简单情况还原(无分支情况) 高级代码: #include "stdafx.h" int main(int argc, char* argv[]) { unsigned int nNumber = 0; scanf("%ud",&nNumber); if(argc == 0) { nNumber = 0; //第一种情况下无分支 } else { nNumber = -1; } return nNumber; } 总共两种情况,我们看下R

mysql中的优化, 简单的说了一下垂直分表, 水平分表(有几种模运算),读写分离.

一.mysql中的优化 where语句的优化 1.尽量避免在 where 子句中对字段进行表达式操作select id from uinfo_jifen where jifen/60 > 10000;优化后:Select id from uinfo_jifen where jifen>600000; 2.应尽量避免在where子句中对字段进行函数操作,这将导致mysql放弃使用索引 select uid from imid where datediff(create_time,'2011-11

Oracle数据库中的优化方案

来自: http://woainichenxueming.iteye.com/blog/726541 一. 优化oracle中的sql语句,提高运行效率 1. 选择最有效率的表名顺序(只在基于规则的优化器中有效) ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名, FROM子句中写在最后的表(基础表 driving table)将被最先处理, 在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表. 如: 表T_USER有16384条记录, 表T_DEPARTME