首页
社区
课程
招聘
[原创]#30天写作挑战#反汇编代码还原之特殊除法还原
发表于: 2020-9-20 13:40 17875

[原创]#30天写作挑战#反汇编代码还原之特殊除法还原

2020-9-20 13:40
17875

反汇编技术之熟悉IDA工具
反汇编逆向技术之寻找Main入口点
反汇编代码还原之优化方式
反汇编代码还原之加减乘
反汇编代码还原之除法为2的幂
反汇编代码还原之除法为非2的幂

在下面会有大量的数学知识来进行讲解. 当然如果你奔着如何还原.直接按照定式还原就行.不用纠结如何计算出来的

但是你了解数学知识.从数学角度来看待优化.那么会可以了解其真正原理 本人数学也不好.但还是查阅很多资料.把基础数学

罗列出来.一来是便与复习.二来是能看到基本的数学公式即可.

方程: 有一个未知数.我们来解这个未知数那么叫做解方程

例如:

解方程我们可以代入一个数进行去解.也可以直接做平衡解.

意思就是 如果 等式的左边+ 那么我们就利用减法.两边都减去这个值. 如果是x 那么做相反运算也就是/ 反之亦然

解:

简化表达式分为 移除括号 交换结合定律 合并同类项

移除括号. 看公式:

关于去括号的另一个特性

两种方式都是可以得出结果的.一般第一种就是加这个数的和.第二种就是拆分为乘数来.计算之后在相机啊.

第二种用途用于不好算的数来用的

例如:

交叉相乘用于分数.可以帮助我们进行简化

解决的是把一个分数变为表达式

图片描述

原理就是分子与分母相乘

image-20200913121722346

可以看到分子变了.而分母都变成了(12×3) 所以都是除同一个数

所以可以去掉了.变成 8 × 3 = 12 × 2

公式记为

image-20200913121929153

如果看官方简介会看到一大堆名词解释.那么这里说一下自我的理解吧.

同类项 就是这一类属于一项.优先把他们组合起来.

例如:

image-20200913122440475

在这里 有xy就是同类项.所以可以优先组合起来.

组合的时候我们可以再根据加法减法符号来组合同符合类别的

分数加法

​ 分数的加法是有一条简单的规矩的.就是去分母.

如何去分母之前也有说.就是让分母一致.然后直接计算分子

我们可以看一下上面的倒数相乘去分母.就是一个很好的例子

image-20200913123228171

公式为如上,也就是交叉相乘的结果

image-20200913123919340

​ 分数减法同加法一样.之不管变成相减了

image-20200913124427380

分数乘法

分数乘法简化还是按照上乘上下乘下原则

image-20200913131234213

分数除法要转变为分数乘法.具体原则就是 *分数的倒数来进行相乘

image-20200913131529190

其余按照分数乘法来做

高级代码:

一个是无符号/-6 一个是/正数7

看下汇编

我们去掉流水线优化后的核心反汇编如下

观看代码定式.我们发现了一个特点. 核心汇编代码都是 乘 减 移 加 移的指令

如果你想要还原.记住代码定式

利用除法转变为乘法的特性.我们首先统计 n值 然后使用2的幂加上n值. 一般是2^(32 + n)

注意这里是幂值想加

如下

image-20200920114923708

然后统计M值

这里的代码还原的公式为

image-20200920115009162

比如我们要还原/7 我们可以代入公式

设M = 24924925h 10进制 = 613566757

设n值 = 3 进行幂想加后得出 2^35

代入公式之后计算的结果向上取整

image-20200920115057747

得出结果为7 这个就是我们求的被除数. 所以这一整段代码我们可以还原为

如果是负数一样代入公式.比如这里是/-6

M = 7

n = 1F + 1 = 32

代入公式得

image-20200920115137458

很明显这是一个很大的数.这个数放到计算器中可以看到是一个负数

image-20200913190909446

我们看16进制就可以看出这个是个负数,我们对其取反.然后转变为DWORD即可.

image-20200913191002422

还记得我们上一讲的除法转变为乘法的例子吧

简单例子如下

image-20200920133319703

那么这里其实本质还是用这个除法转变为乘法的公式.只不过有些许不同

不同点在于C计算位置. 也就是计算M数的时候. 如果n的取值大于32. 那么其结果会超过 4个字节整数的表达范围 所以要进行调整.

调整为我减去2^32次方 然后最后的时候再加上

比如下

image-20200920115224609

那么我们的除法就会随之改变.剩下的就是求出M怎么得出的

在这里我们看下汇编表达形式.并且列出与之对应表达式 但是我们先看一下乘法的特性

x86乘法特性

在x86下.乘法的乘积放在edx.eax中.但是这不是绝对.看如下

举例

image-20200914220651443

与之同理

image-20200914220727121

4字节计算被乘数是4个字节

image-20200914220755666

x64下的乘法特性

64 位模式下,MUL 指令可以使用 64 位操作数。一个 64 位寄存器或内存操作数与 RAX 相乘,产生的 128 位乘积存放到 RDX:RAX 寄存器中。下例中,RAX 乘以 2,就是将 RAX 中的每一位都左移一位。RAX 的最高位溢出到 RDX 寄存器,使得 RDX 的值为 0000 0000 0000 0001h:

了解了乘法原理我们来看等式.根据我们的汇编产生的等式

最终我们以图示的方式来列出公式

image-20200914221846948

然后我们化简

首先是第一段化简 也可以称作是简化 如果不明白看下上面的数学知识补充

image-20200914234200853

最后得出的公式 我们直接求解即可.

2^35 / (2^32 + M) 就得出了最终结果

比如我们的 /7 我们代入公式

汇编对应代码

提取出核心汇编

观看上面代码.发现跟我们除法转化为乘法的代码定式很像 唯一不同的就是在使用 imul 指令之后.后面不是移位而是紧接着是一个add指令

其实这里的代码跟我们的特殊汇编第一种很相似. 这里的M数也很大. 原因是除法转换为乘法的时候做了调整.加了2^32次方

这个定式等价于除法转化为乘法的定式

直接使用这个定式进行还原即可.

除法转化为乘法的代码定式为

image-20200917222940802

解方程得

image-20200920133417037

编译器再计算M数的时候(2^n/b)是以无符号数来进行计算的.而代入除法转变为乘法的代码中.是以有符号进行处理的.有符号的最高位是代表符号位

而无符号的最高位是数据位.所以如果你以无符号来进行计算.那么结果就会出错. 所以我们计算机中.如果(2^n/b)计算出的M数大于0x80000000

最高位为1也就是负数的表现形式.那么实际参与除法转变为乘法的过程是以补码来计算的. 结果是以

image-20200920115304234

来进行计算的. 所以我们的除法转变为乘法的公式又变了.

变成了

image-20200917224404085

这里的括号是求补码的意思 计算机中 2^n / b - 2^32次方是可以计算出来的

所以根据我们的代码定式列出方程式

在加法这里.直接使用edx想加. 而EXE是M与被除数计算出来的.是乘积的高位.所以这里的edx等价于是

image-20200917224706087

我们直接列出公式

image-20200917224826319

直接进行代码公式优化即可.

image-20200917225043782

这个公式等价于除法转变为乘法的公式 所以直接使用公式还原即可.

当除数为负数且无调整的时候会出现这样的问题新的除法调整

核心汇编

遇到上述指令.直接使用代码定式还原

image-20200920115353786

这里我们已知M 跟n值 直接代入公式即可.

image-20200920115448108

结果向上取整.但是我们结果要判别为负.

首先我们先看一下除法转变为乘法的公式

image-20200918210420599

image-20200920133549944

如果我们b为正数的时候.那么公式就是使用上面的公式. 如果为负数那么除法公式就变化了.变成了负数的方式求结果了

如下:

image-20200918210618016

求 -C

image-20200918210921447

那么最终如果我们要求b(除数) 就是 2^n /(2^32 - M) 即可.

减调整对于我们特殊的定式汇编我们算的是加调整. M值是小于0x80000000 而且有add调整.说明是一个正数

如果小于还是进行减调整.那么 我们要还原的除数还是为负数

看下高级代码

核心反汇编

如果想要计算出上方的定式.那么我们还是使用

image-20200920115514482

进行还原即可.

代入公式得

结果向上取整.得出7 但是是负数所以得出是-7

跟我们除数为 +7的代码公式相似.(2.2小结,M大于0x8000000) 只不过除数变成负数了.所以要对M数进行取负计算.

公式如下:

image-20200918212615432

上面的公式是有符号为正数的公式.此时我们对我们的M取负数即可.

设C为如下公式

image-20200918213206022

最终求解即可.

使用

image-20200920115521098

进行还原即可.

M小于0x80000000

如果M大于0x8... 且有加调整 那么除数为正数 使用 b = 2^n / b 还原即可

如果M大于0x8 且没有调整 那么除数为负数 使用 b = 2^n /(2^32 - M) 还原即可.

M大于0x80000000

如果有减调整.那么除数为负数. 使用 b = 2^n/(2^32-M) 即可.

如果加调整,且满足 乘 减 移 加 移 使用 b = 2^n/(2^32+M) 即可.

除法的优化与还原资料. 参考自恩师 钱林松 出版的 <<C++反汇编与逆向分析技术揭秘>> 在此前提上加了自己的一些理解.以及定式还原的方式.

最后感谢一下 编程技术版主KevinsBobo 本书的公式资料在我写的时候有些许不理解.最后请教编程技术版主.然后熬夜做公式做还原得出的.

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

 
 
 
x + 3 = 6
4x + 5 = 17
x + 3 = 6
4x + 5 = 17
 
 
x + 3 = 6
x +3-3= 6 - 3
x = 3
 
4x + 5 = 17
4x + 5 - 5 = 17 - 5
4x = 12
4x / 4 = 12 / 4
x = 3
x + 3 = 6
x +3-3= 6 - 3
x = 3
 
4x + 5 = 17
4x + 5 - 5 = 17 - 5
4x = 12
4x / 4 = 12 / 4
x = 3
 
3(5 + 2) 展开的时候计算括号的值变成 3*5 + 3*2 = 15 + 6
a(b + c) = ab + ac
3(x + 6) = 3x + 3*6
负数乘法去括号遵循 负正得负 负负得正的规律
-3(a + -6) =  -3a + -3*-6 = -3a + 18
-3(a + 6) = -3a + -3*6 = -3a + -18
3(5 + 2) 展开的时候计算括号的值变成 3*5 + 3*2 = 15 + 6
a(b + c) = ab + ac
3(x + 6) = 3x + 3*6
负数乘法去括号遵循 负正得负 负负得正的规律
-3(a + -6) =  -3a + -3*-6 = -3a + 18
-3(a + 6) = -3a + -3*6 = -3a + -18
3 * (2 + 4) = 3 * 6
3 *(2 + 4) = 3*2 + 3*4
3 * (2 + 4) = 3 * 6
3 *(2 + 4) = 3*2 + 3*4
 
 
2 * 204  直接算算不出可以简化为
2* 200 + 2*4 = 408
2 * 204  直接算算不出可以简化为
2* 200 + 2*4 = 408
 
 
 
 
 
 
 
 
 
 
 
 
 
(-xy + 5xy) + (-2xy - 4xy)+(3 - 7) == -2xy - 4
也可以变成
(-xy + 5xy) + (-2xy - 4xy)+(3 - 7) == -2xy - 4
也可以变成
 
 
 
 
 
 
#### 1.2.6 简化表达式之分数的减法简化
#### 1.2.6 简化表达式之分数的减法简化
 
 
 
 
 
int main(int argc, char* argv[])
{
    /*
    除法
    */
     unsigned int NumberOne = 0;
     unsigned int NumberTwo = 0;
     scanf("%u",&NumberOne);
     scanf("%u",&NumberTwo);
     unsigned int Count1 = NumberOne / -6;
     unsigned int Count2 = NumberTwo / 7;
    printf("%d%d",Count2,Count1);
    system("pause");
    return 0;
}
int main(int argc, char* argv[])
{
    /*
    除法
    */
     unsigned int NumberOne = 0;
     unsigned int NumberTwo = 0;
     scanf("%u",&NumberOne);
     scanf("%u",&NumberTwo);
     unsigned int Count1 = NumberOne / -6;
     unsigned int Count2 = NumberTwo / 7;
    printf("%d%d",Count2,Count1);
    system("pause");
    return 0;
}
 
.text:00401000
.text:00401000
.text:00401000 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00401000 _main           proc near               ; CODE XREF: start+AF↓p
.text:00401000
.text:00401000 var_8           = dword ptr -8
.text:00401000 var_4           = dword ptr -4
.text:00401000 argc            = dword ptr  4
.text:00401000 argv            = dword ptr  8
.text:00401000 envp            = dword ptr  0Ch
.text:00401000
.text:00401000                 sub     esp, 8
.text:00401003                 xor     eax, eax
.text:00401005                 mov     [esp+8+var_8], eax
.text:00401009                 mov     [esp+8+var_4], eax
.text:0040100D                 lea     eax, [esp+8+var_8]
.text:00401011                 push    eax
.text:00401012                 push    offset aU       ; "%u"
.text:00401017                 call    _scanf
.text:0040101C                 lea     ecx, [esp+10h+var_4]
.text:00401020                 push    ecx
.text:00401021                 push    offset aU       ; "%u"
.text:00401026                 call    _scanf
.text:0040102B                 mov     ecx, [esp+18h+var_8]
.text:0040102F                 mov     eax, 7
.text:00401034                 mul     ecx
.text:00401036                 sub     ecx, edx
.text:00401038                 mov     eax, 24924925h
.text:0040103D                 shr     ecx, 1
.text:0040103F                 add     ecx, edx
.text:00401041                 shr     ecx, 1Fh
.text:00401044                 push    ecx
.text:00401045                 mov     ecx, [esp+1Ch+var_4]
.text:00401049                 mul     ecx
.text:0040104B                 sub     ecx, edx
.text:0040104D                 shr     ecx, 1
.text:0040104F                 add     ecx, edx
.text:00401051                 shr     ecx, 2
.text:00401054                 push    ecx
.text:00401055                 push    offset aDD      ; "%d%d"
.text:0040105A                 call    _printf
.text:0040105F                 push    offset aPause   ; "pause"
.text:00401064                 call    _system
.text:00401069                 xor     eax, eax
.text:0040106B                 add     esp, 28h
.text:0040106E                 retn
.text:0040
.text:00401000
.text:00401000
.text:00401000 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00401000 _main           proc near               ; CODE XREF: start+AF↓p
.text:00401000
.text:00401000 var_8           = dword ptr -8
.text:00401000 var_4           = dword ptr -4
.text:00401000 argc            = dword ptr  4
.text:00401000 argv            = dword ptr  8
.text:00401000 envp            = dword ptr  0Ch
.text:00401000
.text:00401000                 sub     esp, 8
.text:00401003                 xor     eax, eax
.text:00401005                 mov     [esp+8+var_8], eax
.text:00401009                 mov     [esp+8+var_4], eax
.text:0040100D                 lea     eax, [esp+8+var_8]
.text:00401011                 push    eax
.text:00401012                 push    offset aU       ; "%u"
.text:00401017                 call    _scanf
.text:0040101C                 lea     ecx, [esp+10h+var_4]
.text:00401020                 push    ecx
.text:00401021                 push    offset aU       ; "%u"
.text:00401026                 call    _scanf
.text:0040102B                 mov     ecx, [esp+18h+var_8]
.text:0040102F                 mov     eax, 7
.text:00401034                 mul     ecx
.text:00401036                 sub     ecx, edx
.text:00401038                 mov     eax, 24924925h
.text:0040103D                 shr     ecx, 1
.text:0040103F                 add     ecx, edx
.text:00401041                 shr     ecx, 1Fh
.text:00401044                 push    ecx
.text:00401045                 mov     ecx, [esp+1Ch+var_4]
.text:00401049                 mul     ecx
.text:0040104B                 sub     ecx, edx
.text:0040104D                 shr     ecx, 1
.text:0040104F                 add     ecx, edx
.text:00401051                 shr     ecx, 2
.text:00401054                 push    ecx
.text:00401055                 push    offset aDD      ; "%d%d"
.text:0040105A                 call    _printf
.text:0040105F                 push    offset aPause   ; "pause"
.text:00401064                 call    _system
.text:00401069                 xor     eax, eax
.text:0040106B                 add     esp, 28h
.text:0040106E                 retn
.text:0040
.text:00401000
.text:00401000
.text:00401000 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00401000 _main           proc near               ; CODE XREF: start+AF↓p
.text:00401000
.text:00401000 var_8           = dword ptr -8
.text:00401000 var_4           = dword ptr -4
.text:00401000 argc            = dword ptr  4
.text:00401000 argv            = dword ptr  8
.text:00401000 envp            = dword ptr  0Ch
.text:00401000
 
.text:00401003                 xor     eax, eax
.text:00401005                 mov     [esp+8+var_8], eax
.text:00401009                 mov     [esp+8+var_4], eax
核心位置 /-6
.text:0040102B                 mov     ecx, [esp+18h+var_8]
.text:0040102F                 mov     eax, 7
.text:00401034                 mul     ecx
.text:00401036                 sub     ecx, edx
.text:0040103D                 shr     ecx, 1
.text:0040103F                 add     ecx, edx
.text:00401041                 shr     ecx, 1Fh
.text:00401044                 push    ecx
核心位置/7
.text:00401038                 mov     eax, 24924925h
.text:00401045                 mov     ecx, [esp+1Ch+var_4]
.text:00401049                 mul     ecx
.text:0040104B                 sub     ecx, edx
.text:0040104D                 shr     ecx, 1
.text:0040104F                 add     ecx, edx
.text:00401051                 shr     ecx, 2
.text:00401054                 push    ecx
.text:00401000
.text:00401000
.text:00401000 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00401000 _main           proc near               ; CODE XREF: start+AF↓p
.text:00401000
.text:00401000 var_8           = dword ptr -8
.text:00401000 var_4           = dword ptr -4
.text:00401000 argc            = dword ptr  4
.text:00401000 argv            = dword ptr  8
.text:00401000 envp            = dword ptr  0Ch
.text:00401000
 
.text:00401003                 xor     eax, eax
.text:00401005                 mov     [esp+8+var_8], eax
.text:00401009                 mov     [esp+8+var_4], eax
核心位置 /-6
.text:0040102B                 mov     ecx, [esp+18h+var_8]
.text:0040102F                 mov     eax, 7
.text:00401034                 mul     ecx
.text:00401036                 sub     ecx, edx
.text:0040103D                 shr     ecx, 1
.text:0040103F                 add     ecx, edx
.text:00401041                 shr     ecx, 1Fh
.text:00401044                 push    ecx
核心位置/7
.text:00401038                 mov     eax, 24924925h
.text:00401045                 mov     ecx, [esp+1Ch+var_4]
.text:00401049                 mul     ecx
.text:0040104B                 sub     ecx, edx
.text:0040104D                 shr     ecx, 1
.text:0040104F                 add     ecx, edx
.text:00401051                 shr     ecx, 2
.text:00401054                 push    ecx
.text:00401038                 mov     eax, 24924925h
.text:00401045                 mov     ecx, [esp+1Ch+var_4]
.text:00401049                 mul     ecx
.text:0040104B                 sub     ecx, edx
.text:0040104D                 shr     ecx, 1
.text:0040104F                 add     ecx, edx
.text:00401051                 shr     ecx, 2
.text:00401054                 push    ecx
.text:00401038                 mov     eax, 24924925h
.text:00401045                 mov     ecx, [esp+1Ch+var_4]
.text:00401049                 mul     ecx
.text:0040104B                 sub     ecx, edx
.text:0040104D                 shr     ecx, 1
.text:0040104F                 add     ecx, edx
.text:00401051                 shr     ecx, 2
.text:00401054                 push    ecx
.text:00401038                 mov     eax, M
.text:00401045                 mov     ecx, 被除数
.text:00401049                 mul     ecx
.text:0040104B                 sub     ecx, edx
.text:0040104D                 shr     ecx, n
.text:0040104F                 add     ecx, edx
.text:00401051                 shr     ecx, n
.text:00401054                 push    ecx
.text:00401038                 mov     eax, M
.text:00401045                 mov     ecx, 被除数
.text:00401049                 mul     ecx
.text:0040104B                 sub     ecx, edx
.text:0040104D                 shr     ecx, n
.text:0040104F                 add     ecx, edx
.text:00401051                 shr     ecx, n
.text:00401054                 push    ecx

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2020-9-28 09:05 被TkBinary编辑 ,原因: 修改MD中乘法直接误认为是字符
收藏
免费 13
支持
分享
打赏 + 10.00雪花
打赏次数 1 雪花 + 10.00
 
赞赏  KevinsBobo   +10.00 2020/09/20 写作不易,下顿饭加个鸡腿!
最新回复 (11)
雪    币: 446
活跃值: (600)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
2020-9-20 13:51
0
雪    币: 950
活跃值: (9946)
能力值: ( LV13,RANK:385 )
在线值:
发帖
回帖
粉丝
3
2020-9-20 13:52
0
雪    币: 136
活跃值: (432)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
辛苦
2020-9-20 14:09
0
雪    币: 1378
活跃值: (3067)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
暂时看不懂...有时间再来学习...
2020-9-20 14:36
0
雪    币: 23081
活跃值: (3447)
能力值: (RANK:648 )
在线值:
发帖
回帖
粉丝
6
除法系列完结撒花
2020-9-20 14:49
0
雪    币: 950
活跃值: (9946)
能力值: ( LV13,RANK:385 )
在线值:
发帖
回帖
粉丝
7
KevinsBobo 除法系列完结撒花[em_93][em_93][em_93]
谢谢大佬给鸡腿吃
2020-9-20 17:03
0
雪    币: 5453
活跃值: (1492)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
支持
2020-9-23 15:53
0
雪    币: 729
活跃值: (1195)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
系列教程,先占个位啊,后面来拜读.谢谢分享...
2020-9-25 19:32
0
雪    币: 0
活跃值: (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
交叉相乘乘号写成等号了吧?
2020-9-27 15:17
0
雪    币: 950
活跃值: (9946)
能力值: ( LV13,RANK:385 )
在线值:
发帖
回帖
粉丝
11
wx_kx91578 交叉相乘乘号写成等号了吧?
谢谢提醒,文章写得多.写的比较急.有点差错.已经修改.
2020-9-27 15:39
0
雪    币: 254
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12

你这样写的有些牵强  直接copy书的公式没推 就得出公式。

补充一下 这个公式的

image-20200914234200853

设q=商 ecx=被除数 s=除数 更具汇编代码写等式计算就是 

q=(ecx*(2^32+M))/2^35 

又有 ecx/q(向下取整)=s

2^35 *q=(ecx*(2^32+M))

等式对换

2^35/2^32+M=ecx/q

替换结果

s(除数)=2^35/(2^32+M)


2021-9-8 15:38
0
游客
登录 | 注册 方可回帖
返回
//