反汇编技术之熟悉IDA工具
反汇编逆向技术之寻找Main入口点
反汇编代码还原之优化方式
反汇编代码还原之加减乘
反汇编代码还原之除法为2的幂
除法在非2的幂优化上,采用的是除法转变为乘法 的形式. 在学习这方面知识的时候我们先了解下简单的数学知识
也有助于我们能看懂公式
分数加法
相同分母加法 分子想加 分母不变 例如下
不同分母想加 如果是不同分母想加你就要进行寻找最小公分母
公分母指的是. 当两个或者以上的分数有相同的分母 那么他们便是公分母 注意这里是公分母.而不是最小公分母 最小公分母指的是两个分数以上,最小的公分母
最小公分母的寻找
最小公分母我们可以列出 分母的倍数 如果有两个分数那么都列出分母的倍数.找出相同的倍数.然后让其等价即可.
例如:
列出3的倍数: 3 6 9 12 15 .....
列出6的倍数: 6 12 18 24 ....
我们发现最小公倍数都是6. 所以我们的分子分母都*2转为为相同分母然后进行想加即可
分数乘法
如下:
口诀: 乘分数 没难度 上乘上 下乘下 再约分
整数相乘
如果一个整数 * 一个分数.那么这个分数就可以看做是分子,而分母就是1
例子:
至于约分.可以寻找最小公因数.跟公倍数相反.公倍数是找出相乘 公因数就是找出可以分子/分母的数. 都去除同一个数
汇编对应代码
乍一看上面汇编代码.除法怎么变为了这样.为什么又有乘法又有除法.还有调整等. 那么这里就着重讲解一下.
如果想要直接还原.那么我们把代码定式提取出来 直接进行还原
代码定式
根据汇编我们只需要看三个点即可. 并且得出三个点的公式得原理
其中M是编译器计算出来了. ecx是被除数. 这里sar n值.直接操作的是edx. 这里其实是除法转变为了乘法 而如果除法转变为乘法 那么在32位年代下.两个数相乘 32的值是不会放下的. 所以我们这里其实使用的是 edx,eax 来代表乘法的结果 然后我们直接操作了乘积的高位 这里右移1 等价于是 除以
那么我们还原的时候直接记住死公式就可以.
直接统计n的取值. 然后用 2的32次方 + n即可. 因为乘积的低位时代表2^32次方.这里直接是对乘积高位做操作.所以我们需要加上低位的32次方的值
例子还原
我们套用公式
2.99直接向上取整 = 3. 所以这里我们就寻得被除数为3
首先先看我们的汇编
这里我们汇编分为两部分.上边是可以直接套用公式还原. 而下方其实是获取符号位.调整一下符号位.
shr 逻辑右移. 最高位以0填充. 右移31(1F)位 取得符号位 然后这里有一个加法.其实这个加法也是套路.跟我们之前讲解的无分支优化差不多. 如果结果是正数. 那么 add edx,eax 就是加0 等于什么都不干. 如果是结果是负数 那么我们就需要除法的商做调整.做加1调整.
除法转化为乘法的原理
如果想要了解为什么非2的幂代码会变成上面的代码.那么我们就要理解下原理
设 a = 被除数 b = 除数(是一个常量值)
那么就会有以下公式
这个就是我们上面所了解的分数相关知识.
看最后的公式
其中 2n/b这个是可以在编译期中计算出来的. VC++6.0 或者VS2019 在编译 期间n的取值是大于32的.所以是可以算出来的.
所以我们的公式可以变为如下 在这里我们把编译器可以计算出来的值记做C. 那么可以得出以下公式
最终简化为就是(a * c) >> n 而反过头来看我们的汇编代码
列出公式
ecx = 被除数
eax = M 等价于 2n/b的值.
ecx eax / 2^33 这条公式就正好对应着我们除法转变为乘法的原理 和我们上面的公式一样. (a c) >> n
所以我们解方程即可. 2^n / b = M值. 那么 2^n / M = b b就是我们的要求的除数. 所以得出我们的除数
除法还原公式为:
除法的还原公式
这里的C其实就是2^n/b 在汇编中我们也设为M.所以也可以写为如下
除法转变为乘法的公式
转变为如下
继续转变
最终转变
对于上面我们记住代码定式也可以进行还原.当然熟悉除法转变为乘法的原理更好.
高级代码看其特征我们发现其实是一样的. 都可以使用 除法转乘法的公式来进行还原
除法还原公式其实就是解方程了.解开就可以得到被除数
高级代码
汇编代码
看如上代码.根据除法转为乘法公式 (a * b) >> n .我们可以求出
2^n / b = M 2^n/M = b(除数常量)
这里只不过是换成了无符号而已.
还原公式还是同上
如:
取N 值 = 1 取M值 = 2863311531(注意这里IDA我按了下H转为10进制来查看.这样方便我们用科学计算器来进行运算)
操作的是edx.所以
高级代码如下
核心代码反汇编 代码段
代码定式
根据上面反汇编代码.我们看到三个地方 有我们的 疑似 (a * c) >> n的代码
也就是除法转变为乘法的公式
我们随便取出一处代入公式进行还原
设 M = 40000001h =10进制的 1073741825
设 n = 1E = 10进制的 30
那么代入我们的还原公式为:
以计算器的科学计算计算出的数值是4294967292(10进制)
那么我们将这个数复制到以程序员计算的计算器中.(复制到Dec 10进制输入) 可以看到是一个负数
注意输入的时候以QWORD输入.然后再点击一下变成DWORD则可以看到表达为-4
此时直接对其NOT取反则可以得到原始的被除数. 但是这个被除数常量是负数
你也可以让此值做+1调整 变为4294967293 那么就得出了数直接就是-3 可以很明确的知道我们的被除数是-3
看到上面有一段代码.我们特别不理解 为什么/-6汇编变了
这些后面有专题转么讲解特殊的怎么还原
现在可以看一下我算的
2^64 / 4,294,967,302 = 0x100000006 最高位为符号位 代表这是个负数也就是-6
如果根据定式还原得出的结果为 0xFFFFFFF9 然后对其取反得到6
但是也有代码定式
观看代码定式可以得出
乘减移加移
这种先使用定式还原
这里取出两个n值. 1+31 = 32所以n值为32
代入公式得
2^64 / 4,294,967,303 = 0XFFFFFFF9
关于特殊汇编在下一篇应该会详细讲解.
还是那句话为什么学习除法优化. 好就以我们上面的例子为例.那么使用IDA F5查看
请问看到这种代码你怕了吗. 直接反汇编可以得出这一段代码我是干啥.用IDA反汇编就会得出 右移等等.在我们看来就是硬汇编
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2020-9-12 09:19
被TkBinary编辑
,原因: 修复公式截图错误