首页
社区
课程
招聘
[原创]#30天写作挑战#反汇编代码还原之加减乘
发表于: 2020-9-3 23:39 15728

[原创]#30天写作挑战#反汇编代码还原之加减乘

2020-9-3 23:39
15728

系列文章
反汇编技术之熟悉IDA工具
反汇编逆向技术之寻找Main入口点
反汇编代码还原之优化方式

而加法也特别简单.配合上一篇讲解的 优化方式. 可以很好的还原

有如下高级代码

有如下汇编代码

第一段汇编查看

这一段代码我们明显就能看出是有流水线优化的.

正常排序后的汇编代码应该如下

这里是赋值指令所以直接使用mov了.单独拿出这一段是想告诉大家. 第一篇是基础但也是你学习反汇编的前提.如果以后 有除法 乘法等.他们都有单独的优化.在配合流水线优化 往往就让你发觉很难.导致无法入门

看下核心汇编代码.去掉scanf等

我们使用scanf去掉优化后.我们的高级代码

直接变成了 lea指令 lea指令在这里并不是取地址的指令. 而是计算的指令. 计算的是 edx +2 结果再返回给 eax

这是加法的一种优化方式. lea 指令优化

所以在我们还原的时候可以还原为如下

此时我们就反推出了加法原型. 我不知道它人是否是这种反汇编风格.我是从下往上.按照上下文来进行还原. 这种方法 也很类似于 WG 找数据.从下向上找.

看高级代码

这句代码直接被我们优化为了3 符合常量折叠

高级代码中的NumberTwo因为我们并没有对其取地址.而后续也没有进行修改.所以进行常量传播 + 常量折叠 变成了汇编代码中的13

Visual Studio 2019 看下反汇编

高版本代码变多. 函数使用了EBP寻址 vc6.0 使用了esp寻址.所以我们才会看到很多调整指令

核心汇编位置

在VC6.0中使用了 lea指令优化.在VS2019中就使用了add+mov的方式进行优化

本质是没有改变的. 但是两种都要明白.

加法的这个例子特别适合代码还原. 而且不复杂. 认识了流水线优化 常量传播 常量折叠 就会还原的很简单. 如果有常量传播 以及常量折叠.直接按照常量来还原即可.

例如:

直接按照还原11 即可.

减法 对应指令sub 如果是自减 那么对应的指令可能就会有 dec 指令

计算机只会做加法.而不会做减法. 所以对减法的优化 就是变为加法

高级代码

Vc6.0汇编

看下核心汇编

第一种方式跟加法一样. 使用 lea进行计算 第二种方式 使用了add指令.加了一个很大的数0FFFFFFFBh

其实这个地方就是对减法的优化这个很大的数是补码

这里补充下基础知识

其实负数就变成了 补码了 补码的变化就是 负数取反 + 1 那么还原也是

Not(0FFFFFFFBh) + 1 就会得出真实的值.

其余减法优化就会配合第一篇讲的.各种优化方式进行代码优化.

如果代码还原请谨记

如果add 操作数使用了负数的表现形式.那么就可以还原为减法. 因为执行的操作是减法而不是加法.

乘法 对应指令 Imul 以及对应指令 Mul 分别是有符号乘法 以及无符号乘法. 两个数都是变量的时候.且不满足前面所讲的变量去除优化选项 那么是无法进行优化的. 乘法对于 2的幂是可以进行优化的.会使用指令较短的周期来进行优化

高级代码

VC6.0 对应汇编

vs2019 x86对应汇编

Vs2019 X64对应汇编

高级代码 与汇编对应

通过上面我们去掉流水线优化.人肉反汇编可以看出. 在乘法优化中. 大部分使用lea指令进行优化.特别是混合运算

首先我们根据上面汇编先讲解下lea指令对乘法的优化

高级代码

对应汇编

在这里 lea是计算指令而不是取地址 第一行汇编 我们产生了定式 也就是 eax *2 + eax 等价于 3eax

那么第二行汇编又依赖于第一行的输出. 那么产生的 定式也就是

3eax + 3eax * 4 先算乘法得出 3eax + 12eax 继续计算 得出 15eax

那么我们就可以还原高级代码为 eax * 15 , 而eax我们也看到赋值了,也就是 argc变量

所以最终代码就是 argc * 15 我们的原来的代码应该是NumberTwo. 这里也是被编译器给优化掉了.

所以 乘法的优化一定要明白 lea指令,包括我们的加法也会使用.一定要认识lea 以及自己会换算

lea指令我们已经知道了.其实这里着重讲解一下sub指令优化

高级代码与反汇编

lea指令我们说了.在括号内是计算一个值. 通过汇编我们也可以得出 lea得出的结果是 8eax. 而这里又使用 sub 来减去自己本身. 等价于 8eax - eax = 7eax 最后在加 5

eax我们知道是argc 所以得出的反汇编为 7eax + 5 <===> 7 argc + 5 == argc + 7 + 5

这里是首先使用lea换算成2的幂来进行优化的. 然后减去自己本身. 这样也比直接用 IMUL 或者MUL执行效率高.

其他基本上都是使用lea指令进行优化了.熟悉lea看一眼即可.

观看反汇编 除了NumberTwo * 15 有所变化其余的全部同Vc6.0一样. 所以说在编译器优化上.并不是越高级的编译器越好的IDE是最好的. 底层是一样的.优化方式还是同几十年前的VC6.0

其实之前说过.对于2的幂.编译器可能会选择使用移位来进行优化.这里也就出现了. 也是先优化为2的幂减去自己本身

SHL eax,4 = eax *4 = 16eax

然后使用sub 16eax - eax = 15 eax 那么就得出计算的值了.

总结来说原理还是同vc6.0优化一样. 所以要熟悉汇编.

在x64下如果你还是使用x86写代码的形式.那么可能都不用优化了.优化的前提是两个操作数相乘.结果可能溢出.所以有时候会用两个寄存器表示.而在64位下.如果你还是使用两个32位操作数相乘.那么基本上就不给你优化了. 原因是32*32 顶多跟64位的数相等.那么我直接使用指令进行操作了

代码如下

之前高级代码都是32位数.那么我们已_int64的操作数来进行查看.

高级代码

但是发现还是同上.换个大点的数看看

其实可以发现.首先常量是直接配合常量折叠 已经给算出来了. 而其它直接使用Imul进行计算了

无符号大家可以自己建立工程查看.原理同上

我们学习了乘法 加法 减法 那么可以进行总结

1.lea 指令是比较常见与乘法的计算以及加法的计算

2.减法指令是可以转为补码 .优化为加法.

还是那句话 高手复习 新手学习.

 
 
 
 
 
 
 
 

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2020-9-5 19:10 被TkBinary编辑 ,原因:
收藏
免费 15
支持
分享
打赏 + 2.00雪花
打赏次数 1 雪花 + 2.00
 
赞赏  mb_rtlrcnic   +2.00 2020/09/05 支持老大
最新回复 (17)
雪    币: 23080
活跃值: (3432)
能力值: (RANK:648 )
在线值:
发帖
回帖
粉丝
2
Orz
2020-9-4 08:51
0
雪    币: 888
活跃值: (9861)
能力值: ( LV13,RANK:385 )
在线值:
发帖
回帖
粉丝
3
忘了说下,x64代码工程中 CTRL+E 跳转到Start开始位置. 点击Jmp可以到达Main函数调用位置.x64下.寄存器变为了 r8 rcx rdx等寄存器用于传参.所以在调用Main上面有三个Mov 分别对其赋值.很快就能找到入口点.方便自己逆向观看. vc6.0 vs2019 基本都是push. Debug版本下vs2019会在一个call里面.在调用位置找不到三个push. 想看Debug自己找找入口就可以了. 
2020-9-4 09:09
0
雪    币: 26185
活跃值: (63307)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
4
感谢分享!
2020-9-4 09:11
0
雪    币: 1
活跃值: (207)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
感谢老师的细心讲解
2020-9-4 09:23
0
雪    币: 20
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
6
汇编学扎实,做啥都方便,。
2020-9-4 09:27
0
雪    币: 888
活跃值: (9861)
能力值: ( LV13,RANK:385 )
在线值:
发帖
回帖
粉丝
7
lsch 汇编学扎实,做啥都方便,。
反汇编学扎实,任何汇编都是C
2020-9-4 09:53
0
雪    币: 446
活跃值: (595)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
学习了
2020-9-4 10:00
0
雪    币: 202
活跃值: (428)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
感谢分享
2020-9-4 13:42
0
雪    币: 6112
活跃值: (1212)
能力值: (RANK:30 )
在线值:
发帖
回帖
粉丝
10
不错,感谢分享!30天打卡的活动期待有更多的人参与!
2020-9-4 14:31
0
雪    币: 888
活跃值: (9861)
能力值: ( LV13,RANK:385 )
在线值:
发帖
回帖
粉丝
11
CCkicker 不错,感谢分享!30天打卡的活动期待有更多的人参与!
谢谢大佬
2020-9-4 16:24
0
雪    币: 26185
活跃值: (63307)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
12

欢迎更多的小伙伴参与到 #30天写作挑战#中来!活动详情:https://bbs.pediy.com/thread-261705.htm

2020-9-7 16:55
0
雪    币: 1829
活跃值: (1377)
能力值: (RANK:50 )
在线值:
发帖
回帖
粉丝
13
下一章是除法吗?
2020-9-20 17:05
0
雪    币: 888
活跃值: (9861)
能力值: ( LV13,RANK:385 )
在线值:
发帖
回帖
粉丝
14
backer 下一章是除法吗?
老师是的.除法已经写完了
2020-9-20 17:06
0
雪    币: 1759
活跃值: (2334)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
15
所有汇编都是通用的吗?比如学了x86汇编,对arm汇编有帮助吗
2020-9-22 11:25
0
雪    币: 888
活跃值: (9861)
能力值: ( LV13,RANK:385 )
在线值:
发帖
回帖
粉丝
16
又见飞刀z 所有汇编都是通用的吗?比如学了x86汇编,对arm汇编有帮助吗
你可以看下.当时看到一个arm的哥们也遇到这个问题了.优化方式跟我写的除法一样.我给你找找.
2020-9-22 11:45
0
雪    币: 888
活跃值: (9861)
能力值: ( LV13,RANK:385 )
在线值:
发帖
回帖
粉丝
17
又见飞刀z 所有汇编都是通用的吗?比如学了x86汇编,对arm汇编有帮助吗

https://bbs.pediy.com/thread-251284.htm 这篇文章有就说.我下面几篇系列讲解的是x86 x64 gcc 而这篇文章也包括了arm. 其实是一样的.

最后于 2020-9-22 12:03 被TkBinary编辑 ,原因:
2020-9-22 12:03
0
雪    币: 1759
活跃值: (2334)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
18
谢谢,我看了下,的确所运用的数学原理都是一样的,就是汇编指令不一样,不过你这个更详细些,思路更清晰
2020-9-22 13:52
0
游客
登录 | 注册 方可回帖
返回
//