首页
社区
课程
招聘
[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
2020-9-9 17:13 16697

[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

2020-9-9 17:13
16697

目录

代码还原反汇编之除法除数为非2的幂

系列文章

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

一丶数学知识补充

1.1 简介

​ 除法在非2的幂优化上,采用的是除法转变为乘法 的形式. 在学习这方面知识的时候我们先了解下简单的数学知识

 

也有助于我们能看懂公式

1.2 分数

1.2.1分数加法

  • 分数加法

    相同分母加法 分子想加 分母不变 例如下

    image-20200907222151583

不同分母想加 如果是不同分母想加你就要进行寻找最小公分母

 

公分母指的是. 当两个或者以上的分数有相同的分母 那么他们便是公分母 注意这里是公分母.而不是最小公分母 最小公分母指的是两个分数以上,最小的公分母

  • 最小公分母的寻找

    最小公分母我们可以列出 分母的倍数 如果有两个分数那么都列出分母的倍数.找出相同的倍数.然后让其等价即可.

    例如:

    image-20200907222759951

    列出3的倍数: 3 6 9 12 15 .....

    列出6的倍数: 6 12 18 24 ....

    我们发现最小公倍数都是6. 所以我们的分子分母都*2转为为相同分母然后进行想加即可

    图片描述

1.2.1分数乘法

  • 分数乘法

    **分数*分数 是分子 * 分子 分母 * 分母**
    

如下:

 

image-20200907223401007

 

口诀: 乘分数 没难度 上乘上 下乘下 再约分

  • 整数相乘

    如果一个整数 * 一个分数.那么这个分数就可以看做是分子,而分母就是1

    例子:

    image-20200907223817069

    至于约分.可以寻找最小公因数.跟公倍数相反.公倍数是找出相乘 公因数就是找出可以分子/分母的数. 都去除同一个数

二丶除法优化之有符号非2的幂优化

2.1高级代码与反汇编

int main(int argc, char* argv[])
{
    /*
    除法
    */
      int NumberOne = 0;
      int NumberTwo = 0;



    scanf("%d",&NumberOne);
    scanf("%d",&NumberTwo);


     int Count1 = NumberOne / 3;

     int Count2 = NumberTwo / 5;

     int Count3 = NumberTwo / 6;      

     int Count4 = NumberTwo / 9;


    printf("%d%d%d%d%d",Count4,Count3,Count2,Count1);
    system("pause");

    return 0;
}

汇编对应代码

.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 aD       ; "%d"
.text:00401017                 call    _scanf
.text:0040101C                 lea     ecx, [esp+10h+var_4]
.text:00401020                 push    ecx
.text:00401021                 push    offset aD       ; "%d"
.text:00401026                 call    _scanf

//第一段
.text:0040102B                 mov     ecx, [esp+18h+var_8]
.text:0040102F                 mov     eax, 55555556h
.text:00401034                 imul    ecx
.text:0040103A                 mov     eax, edx
.text:0040103C                 shr     eax, 1Fh
.text:0040103F                 add     edx, eax

//第二段
.text:00401036                 mov     ecx, [esp+18h+var_4]
.text:00401041                 mov     eax, 66666667h
.text:00401047                 imul    ecx
.text:00401049                 sar     edx, 1
.text:0040104B                 mov     eax, edx
.text:0040104D                 shr     eax, 1Fh
.text:00401050                 add     edx, eax
.text:00401057                 push    edx                //这里原先是流水线优化给提到上边来了
//第三段
.text:00401052                 mov     eax, 2AAAAAABh
.text:00401058                 imul    ecx
.text:0040105A                 mov     eax, edx
.text:0040105C                 shr     eax, 1Fh
.text:0040105F                 add     edx, eax
.text:00401066                 push    edx                //同上流水线优化

//第四段
.text:00401061                 mov     eax, 38E38E39h
.text:00401067                 imul    ecx
.text:00401069                 sar     edx, 1
.text:0040106B                 mov     ecx, edx
.text:0040106D                 shr     ecx, 1Fh
.text:00401070                 add     edx, ecx
.text:00401072                 push    edx


.text:00401073                 push    offset aDDDDD   ; "%d%d%d%d%d"
.text:00401078                 call    _printf
.text:0040107D                 push    offset aPause   ; "pause"
.text:00401082                 call    _system
.text:00401087                 xor     eax, eax
.text:00401089                 add     esp, 30h
.text:0040108C                 retn
.text:0040108C _main           endp

2.2 除法非2的幂还原

​ 乍一看上面汇编代码.除法怎么变为了这样.为什么又有乘法又有除法.还有调整等. 那么这里就着重讲解一下.

 

如果想要直接还原.那么我们把代码定式提取出来 直接进行还原

  • 代码定式

    mov     ecx, 被除数
    mov     eax, M值
    imul    ecx
    sar     edx, n
    mov     eax, edx
    shr     eax, 1Fh
    add     edx, eax
    push    edx
    

    根据汇编我们只需要看三个点即可. 并且得出三个点的公式得原理

    image-20200907225550924

    其中M是编译器计算出来了. ecx是被除数. 这里sar n值.直接操作的是edx. 这里其实是除法转变为了乘法 而如果除法转变为乘法 那么在32位年代下.两个数相乘 32的值是不会放下的. 所以我们这里其实使用的是 edx,eax 来代表乘法的结果 然后我们直接操作了乘积的高位 这里右移1 等价于是 除以 image-20200907225444244

那么我们还原的时候直接记住死公式就可以. image-20200907225722139

 

直接统计n的取值. 然后用 2的32次方 + n即可. 因为乘积的低位时代表2^32次方.这里直接是对乘积高位做操作.所以我们需要加上低位的32次方的值

 

例子还原

  .text:0040102B                 mov     ecx, [esp+18h+var_8]
  .text:0040102F                 mov     eax, 55555556h
  .text:00401034                 imul    ecx
  .text:0040103A                 mov     eax, edx                //这里直接使用的是edx.而没有对edx做修改.所以我们的n值就是0 
  .text:0040103C                 shr     eax, 1Fh
  .text:0040103F                 add     edx, eax

我们套用公式

 

image-20200907230441538

 

2.99直接向上取整 = 3. 所以这里我们就寻得被除数为3

2.3 除数为非2的幂的优化与原理

首先先看我们的汇编

  .text:00401061                 mov     eax, 38E38E39h
  .text:00401067                 imul    ecx
  .text:00401069                 sar     edx, 1
  .text:0040106B                 mov     ecx, edx

  .text:0040106D                 shr     ecx, 1Fh
  .text:00401070                 add     edx, ecx
  .text:00401072                 push    edx

这里我们汇编分为两部分.上边是可以直接套用公式还原. 而下方其实是获取符号位.调整一下符号位.

 

shr 逻辑右移. 最高位以0填充. 右移31(1F)位 取得符号位 然后这里有一个加法.其实这个加法也是套路.跟我们之前讲解的无分支优化差不多. 如果结果是正数. 那么 add edx,eax 就是加0 等于什么都不干. 如果是结果是负数 那么我们就需要除法的商做调整.做加1调整.

  • 除法转化为乘法的原理

    如果想要了解为什么非2的幂代码会变成上面的代码.那么我们就要理解下原理

    设 a = 被除数 b = 除数(是一个常量值)

    那么就会有以下公式

    image-20200907231604161

    这个就是我们上面所了解的分数相关知识.

    看最后的公式

    image-20200907231634994

    其中 2n/b这个是可以在编译期中计算出来的. VC++6.0 或者VS2019 在编译 期间n的取值是大于32的.所以是可以算出来的.

    所以我们的公式可以变为如下 在这里我们把编译器可以计算出来的值记做C. 那么可以得出以下公式

    image-20200907232516529

    最终简化为就是(a * c) >> n 而反过头来看我们的汇编代码

    .text:00401061                 mov     eax, 38E38E39h
    .text:00401067                 imul    ecx
    .text:00401069                 sar     edx, 1
    

    列出公式

    ecx = 被除数

    eax = M 等价于 2n/b的值.

    ecx eax / 2^33 这条公式就正好对应着我们除法转变为乘法的原理 和我们上面的公式一样. (a c) >> n

    所以我们解方程即可. 2^n / b = M值. 那么 2^n / M = b b就是我们的要求的除数. 所以得出我们的除数

    除法还原公式为:

2.4 总结除法还原公式

  • 除法的还原公式

    image-20200908202646241

    这里的C其实就是2^n/b 在汇编中我们也设为M.所以也可以写为如下

    image-20200908202210911

  • 除法转变为乘法的公式

    image-20200908214030412

    转变为如下

    image-20200908214044445

    继续转变

    image-20200908202244082

    最终转变

    image-20200908214109643

对于上面我们记住代码定式也可以进行还原.当然熟悉除法转变为乘法的原理更好.

 

高级代码看其特征我们发现其实是一样的. 都可以使用 除法转乘法的公式来进行还原

 

除法还原公式其实就是解方程了.解开就可以得到被除数

三丶除法优化之无符号非2的幂优化

高级代码

int main(int argc, char* argv[])
{
    /*
    除法
    */
     unsigned int NumberOne = 0;
     unsigned int NumberTwo = 0;



    scanf("%u",&NumberOne);
    scanf("%u",&NumberTwo);


     unsigned int Count1 = NumberOne / 3;

     unsigned int Count2 = NumberTwo / 5;

     unsigned int Count3 = NumberTwo / 6;      

     unsigned int Count4 = NumberTwo / 9;


    printf("%d%d%d%d%d",Count4,Count3,Count2,Count1);
    system("pause");

    return 0;
}

汇编代码

.text:00401005                 mov     [esp+8+var_8], eax
.text:00401009                 mov     [esp+8+var_4], eax

.text:0040102B                 mov     eax, 2863311531
.text:00401030                 mov     ecx, [esp+18h+var_4]
.text:00401034                 mul     [esp+18h+var_8]
.text:00401038                 shr     edx, 1

.text:0040103A                 mov     eax, 3435973837
.text:0040103F                 push    edx
.text:00401040                 mul     ecx
.text:00401042                 shr     edx, 2

.text:00401045                 mov     eax, 0AAAAAAABh
.text:0040104A                 push    edx
.text:0040104B                 mul     ecx
.text:0040104D                 shr     edx, 2

.text:00401050                 mov     eax, 38E38E39h
.text:00401055                 push    edx
.text:00401056                 mul     ecx
.text:00401058                 shr     edx, 1
.text:0040105A                 push    edx

3.1 无符号非2的幂除数为正代码反汇编还原

看如上代码.根据除法转为乘法公式 (a * b) >> n .我们可以求出

 

2^n / b = M 2^n/M = b(除数常量)

 

这里只不过是换成了无符号而已.

 

还原公式还是同上

 

如:

.text:0040102B                 mov     eax, 2863311531
.text:00401030                 mov     ecx, [esp+18h+var_4]
.text:00401034                 mul     [esp+18h+var_8]
.text:00401038                 shr     edx, 1

取N 值 = 1 取M值 = 2863311531(注意这里IDA我按了下H转为10进制来查看.这样方便我们用科学计算器来进行运算)

 

操作的是edx.所以

被除数 = 2^33
除数 = M
求除数公式 =  2^n/M = b
代入公式
2^33 / 2863311531 = 2.999999999 向上取整 = 3 所以得出这里的除数为3. ecx = var4
所以这里反汇编为高级代码为 var_4 / 3

3.2 无符号非2的幂除数为负数反汇编代码还原

高级代码如下

int main(int argc, char* argv[])
{
    /*
    除法
    */
     unsigned int NumberOne = 0;
     unsigned int NumberTwo = 0;



    scanf("%u",&NumberOne);
    scanf("%u",&NumberTwo);


     unsigned int Count1 = NumberOne / -3;

     unsigned int Count2 = NumberTwo / -5;

     unsigned int Count3 = NumberTwo / -6;      

     unsigned int Count4 = NumberTwo / -9;


    printf("%d%d%d%d%d",Count4,Count3,Count2,Count1);
    system("pause");

    return 0;
}

核心代码反汇编 代码段

.text:00401005                 mov     [esp+8+var_8], eax
.text:00401009                 mov     [esp+8+var_4], eax

/-3
.text:0040102B                 mov     eax, 40000001h
.text:00401030                 mov     ecx, [esp+18h+var_4]
.text:00401034                 mul     [esp+18h+var_8]
.text:00401038                 shr     edx, 1Eh
.text:00401040                 push    edx

/-5
.text:0040103B                 mov     eax, 80000003h
.text:00401041                 mul     ecx
.text:00401043                 shr     edx, 1Fh
.text:0040104B                 push    edx

/-6
.text:00401046                 mov     eax, 7
.text:0040104C                 mul     ecx
.text:0040104E                 mov     eax, ecx
.text:00401050                 sub     eax, edx
.text:00401052                 shr     eax, 1
.text:00401054                 add     eax, edx
.text:00401056                 shr     eax, 1Fh
.text:00401059                 push    eax
/-9
.text:0040105A                 mov     eax, 80000005h
.text:0040105F                 mul     ecx
.text:00401061                 shr     edx, 1Fh
.text:00401064                 push    edx
  • 代码定式

    根据上面反汇编代码.我们看到三个地方 有我们的 疑似 (a * c) >> n的代码

    也就是除法转变为乘法的公式

    我们随便取出一处代入公式进行还原

    设 M = 40000001h =10进制的 1073741825

    设 n = 1E = 10进制的 30

    那么代入我们的还原公式为:

    image-20200908201737556

以计算器的科学计算计算出的数值是4294967292(10进制)

 

那么我们将这个数复制到以程序员计算的计算器中.(复制到Dec 10进制输入) 可以看到是一个负数

 

image-20200908202004903

 

注意输入的时候以QWORD输入.然后再点击一下变成DWORD则可以看到表达为-4

 

image-20200908202047783

 

此时直接对其NOT取反则可以得到原始的被除数. 但是这个被除数常量是负数

 

image-20200908202120166

 

你也可以让此值做+1调整 变为4294967293 那么就得出了数直接就是-3 可以很明确的知道我们的被除数是-3

3.3 特殊汇编

看到上面有一段代码.我们特别不理解 为什么/-6汇编变了

 

这些后面有专题转么讲解特殊的怎么还原

 

现在可以看一下我算的

 

2^64 / 4,294,967,302 = 0x100000006 最高位为符号位 代表这是个负数也就是-6

 

如果根据定式还原得出的结果为 0xFFFFFFF9 然后对其取反得到6

 

但是也有代码定式

mov regA,[ebp - xxx]
mov reg,M
mul regA
sub regA,edx
shr regA,n
add regA,edx
shr regA,(n-1)

观看代码定式可以得出

 

乘减移加移

 

这种先使用定式还原

 

image-20200908205529875

 

这里取出两个n值. 1+31 = 32所以n值为32

 

代入公式得

 

2^64 / 4,294,967,303 = 0XFFFFFFF9

 

关于特殊汇编在下一篇应该会详细讲解.

四丶为什么学习除法优化

4.1 为什么学习除法优化

​ 还是那句话为什么学习除法优化. 好就以我们上面的例子为例.那么使用IDA F5查看

 

image-20200908205952566

 

请问看到这种代码你怕了吗. 直接反汇编可以得出这一段代码我是干啥.用IDA反汇编就会得出 右移等等.在我们看来就是硬汇编

 

也就是硬着头皮还原的.所以说这就是我们学习的意义所在 当然F5还是很强大的.但是我们学会了能更好的帮助我们进行反汇编,更好的通过反汇编从而还原为高级代码

五丶高级Vs编译器与linux下的gcc优化

其实还是老生常谈.拿高版本与低版本做个对比.看看优化方式是否发生了改变.

5.1 vs2019 x86 有符号非2的幂优化

高级代码

int main(int argc, char* argv[])
{
    /*
    除法
    */
      int NumberOne = 0;
      int NumberTwo = 0;
    scanf("%d",&NumberOne);
    scanf("%d",&NumberTwo);

     int Count1 = NumberOne / 3;
     int Count2 = NumberTwo / 5;
     int Count3 = NumberTwo / 6;      
     int Count4 = NumberTwo / 9;
    printf("%d%d%d%d%d",Count4,Count3,Count2,Count1);
    system("pause");

    return 0;
}

汇编

.text:00401080                 push    ebp
.text:00401081                 mov     ebp, esp
.text:00401083                 sub     esp, 8
.text:00401086                 lea     eax, [ebp+var_4]
.text:00401089                 mov     [ebp+var_4], 0
.text:00401090                 push    eax
.text:00401091                 push    offset unk_41ECDC
.text:00401096                 mov     [ebp+var_8], 0
.text:0040109D                 call    sub_401050
.text:004010A2                 lea     eax, [ebp+var_8]
.text:004010A5                 push    eax
.text:004010A6                 push    offset unk_41ECDC
.text:004010AB                 call    sub_401050

.text:004010B0                 mov     ecx, [ebp+var_8]
.text:004010B3                 mov     eax, 55555556h
.text:004010B8                 imul    [ebp+var_4]
.text:004010BB                 mov     eax, edx
.text:004010BD                 shr     eax, 1Fh
.text:004010C0                 add     eax, edx
.text:004010C2                 push    eax

.text:004010C3                 mov     eax, 66666667h
.text:004010C8                 imul    ecx
.text:004010CA                 sar     edx, 1
.text:004010CC                 mov     eax, edx
.text:004010CE                 shr     eax, 1Fh
.text:004010D1                 add     eax, edx
.text:004010D3                 push    eax

.text:004010D4                 mov     eax, 2AAAAAABh
.text:004010D9                 imul    ecx
.text:004010DB                 mov     eax, edx
.text:004010DD                 shr     eax, 1Fh
.text:004010E0                 add     eax, edx
.text:004010E2                 push    eax

.text:004010E3                 mov     eax, 38E38E39h
.text:004010E8                 imul    ecx
.text:004010EA                 sar     edx, 1
.text:004010EC                 mov     eax, edx
.text:004010EE                 shr     eax, 1Fh
.text:004010F1                 add     eax, edx
.text:004010F3                 push    eax
.text:004010F4                 push    offset aDDDDD   ; "%d%d%d%d%d"
.text:004010F9                 call    sub_401020
.text:004010FE                 push    offset aPause   ; "pause"
.text:00401103                 call    sub_4048E7
.text:00401108                 add     esp, 28h
.text:0040110B                 xor     eax, eax
.text:0040110D                 mov     esp, ebp
.text:0040110F                 pop     ebp

这里流水线优化等也不去掉了.可以发现跟VC6.0无任何区别

5.2 vs2019 x64有符号非2的幂优化

高级代码

int main(int argc, char* argv[])
{
    /*
    除法
    */
    __int64 NumberOne = 0;
    __int64 NumberTwo = 0;
    scanf("%I64d", &NumberOne);
    scanf("%I64d", &NumberTwo);

    __int64 Count1 = NumberOne / 3;
    __int64 Count2 = NumberTwo / 5;
    __int64 Count3 = NumberTwo / 6;
    __int64 Count4 = NumberTwo / 9;
    printf("%I64d%I64d%lld%lld", Count4, Count3, Count2, Count1);
    system("pause");

    return 0;
}

反汇编

text:00000001400010D0                 sub     rsp, 38h
.text:00000001400010D4                 xor     eax, eax
.text:00000001400010D6                 lea     rdx, [rsp+38h+arg_10]
.text:00000001400010DB                 lea     rcx, aI64d      ; "%I64d"
.text:00000001400010E2                 mov     [rsp+38h+arg_10], rax
.text:00000001400010E7                 mov     [rsp+38h+arg_18], rax
.text:00000001400010EC                 call    sub_140001080
.text:00000001400010F1                 lea     rdx, [rsp+38h+arg_18]
.text:00000001400010F6                 lea     rcx, aI64d      ; "%I64d"
.text:00000001400010FD                 call    sub_140001080
.text:0000000140001102                 mov     rcx, [rsp+38h+arg_18]

.text:0000000140001107                 mov     rax, 5555555555555556h
.text:0000000140001111                 imul    [rsp+38h+arg_10]
.text:0000000140001116                 mov     rax, 6666666666666667h
.text:0000000140001120                 mov     r10, rdx
.text:0000000140001123                 shr     r10, 3Fh
.text:0000000140001127                 add     r10, rdx
.text:000000014000112A                 imul    rcx
.text:000000014000112D                 mov     [rsp+38h+var_18], r10
.text:0000000140001132                 mov     r9, rdx
.text:0000000140001135                 sar     r9, 1
.text:0000000140001138                 mov     rax, r9
.text:000000014000113B                 shr     rax, 3Fh
.text:000000014000113F                 add     r9, rax

.text:0000000140001142                 mov     rax, 2AAAAAAAAAAAAAABh
.text:000000014000114C                 imul    rcx
.text:000000014000114F                 mov     rax, 1C71C71C71C71C72h
.text:0000000140001159                 mov     r8, rdx
.text:000000014000115C                 shr     r8, 3Fh
.text:0000000140001160                 add     r8, rdx
.text:0000000140001163                 imul    rcx
.text:0000000140001166                 lea     rcx, aI64dI64dLldLld ; "%I64d%I64d%lld%lld"
.text:000000014000116D                 mov     rax, rdx
.text:0000000140001170                 shr     rax, 3Fh
.text:0000000140001174                 add     rdx, rax
.text:0000000140001177                 call    sub_140001020
.text:000000014000117C                 lea     rcx, aPause     ; "pause"
.text:0000000140001183                 call    sub_1400045C4
.text:0000000140001188                 xor     eax, eax
.text:000000014000118A                 add     rsp, 38h
.text:000000014000118E                 retn

观看反汇编其实跟x86一致

 

这里还是去掉流水线优化 提取核心代码位置进行反汇编

.text:0000000140001107                 mov     rax, 5555555555555556h
.text:0000000140001111                 imul    [rsp+38h+arg_10]
.text:0000000140001120                 mov     r10, rdx
.text:0000000140001123                 shr     r10, 3Fh
.text:0000000140001127                 add     r10, rdx

M数值变大.还是代入公式即可. 这里使用的mov r10,rdx 说明直接使用的rdx. rdx是一个64位数. 所以 2^64 / M = 2.9999999 向上取整 = 3

5.3 linux gcc x86 有符号非2的幂

高级代码

#include<stdio.h>

int main()
{

    int NumberOne = 0;
    int NumberTwo = 0;
    scanf("%d", &NumberOne);
    scanf("%d", &NumberTwo);
    int Count1 = NumberOne / 3;
    int Count2 = NumberTwo / 5;
    int Count3 = NumberTwo / 6;
    int Count4 = NumberTwo / 9;
    printf("%d%d%d%d", Count4, Count3, Count2, Count1);
    scanf("%d", &Count4);
    scanf("%d", &Count3);
    scanf("%d", &Count2);
    scanf("%d", &Count1);
    printf("%d%d%d%d", Count4, Count3, Count2, Count1);
    return 0;
}

如果你是64位系统.那么你使用gcc命令如下

gcc xxx.c -o2 -m32

编译出来即可. 其实下面反汇编跟x86 vc++6.0 vs2019 一样.可以不用看了.

 

反汇编

.text:080484BB ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:080484BB                 public main
.text:080484BB main            proc near               ; DATA XREF: _start+17↑o
.text:080484BB
.text:080484BB var_24          = dword ptr -24h
.text:080484BB var_20          = dword ptr -20h
.text:080484BB var_1C          = dword ptr -1Ch
.text:080484BB var_18          = dword ptr -18h
.text:080484BB var_14          = dword ptr -14h
.text:080484BB var_10          = dword ptr -10h
.text:080484BB var_C           = dword ptr -0Ch
.text:080484BB argc            = dword ptr  8
.text:080484BB argv            = dword ptr  0Ch
.text:080484BB envp            = dword ptr  10h
.text:080484BB
.text:080484BB ; __unwind {
.text:080484BB                 lea     ecx, [esp+4]
.text:080484BF                 and     esp, 0FFFFFFF0h
.text:080484C2                 push    dword ptr [ecx-4]
.text:080484C5                 push    ebp
.text:080484C6                 mov     ebp, esp
.text:080484C8                 push    ebx
.text:080484C9                 push    ecx
.text:080484CA                 sub     esp, 20h
.text:080484CD                 mov     eax, large gs:14h
.text:080484D3                 mov     [ebp+var_C], eax
.text:080484D6                 xor     eax, eax
.text:080484D8                 mov     [ebp+var_24], 0
.text:080484DF                 mov     [ebp+var_20], 0
.text:080484E6                 sub     esp, 8
.text:080484E9                 lea     eax, [ebp+var_24]
.text:080484EC                 push    eax
.text:080484ED                 push    offset unk_80486B0
.text:080484F2                 call    ___isoc99_scanf
.text:080484F7                 add     esp, 10h
.text:080484FA                 sub     esp, 8
.text:080484FD                 lea     eax, [ebp+var_20]
.text:08048500                 push    eax
.text:08048501                 push    offset unk_80486B0
.text:08048506                 call    ___isoc99_scanf
.text:0804850B                 add     esp, 10h
.text:0804850E                 mov     ecx, [ebp+var_24]

.text:08048511                 mov     edx, 55555556h
.text:08048516                 mov     eax, ecx
.text:08048518                 imul    edx
.text:0804851A                 mov     eax, ecx
.text:0804851C                 sar     eax, 1Fh
.text:0804851F                 sub     edx, eax
.text:08048521                 mov     eax, edx
.text:08048523                 mov     [ebp+var_1C], eax
.text:08048526                 mov     ecx, [ebp+var_20]

.text:08048529                 mov     edx, 66666667h
.text:0804852E                 mov     eax, ecx
.text:08048530                 imul    edx
.text:08048532                 sar     edx, 1
.text:08048534                 mov     eax, ecx
.text:08048536                 sar     eax, 1Fh
.text:08048539                 sub     edx, eax
.text:0804853B                 mov     eax, edx
.text:0804853D                 mov     [ebp+var_18], eax
.text:08048540                 mov     ecx, [ebp+var_20]

.text:08048543                 mov     edx, 2AAAAAABh
.text:08048548                 mov     eax, ecx
.text:0804854A                 imul    edx
.text:0804854C                 mov     eax, ecx
.text:0804854E                 sar     eax, 1Fh
.text:08048551                 sub     edx, eax
.text:08048553                 mov     eax, edx
.text:08048555                 mov     [ebp+var_14], eax
.text:08048558                 mov     ecx, [ebp+var_20]

.text:0804855B                 mov     edx, 38E38E39h
.text:08048560                 mov     eax, ecx
.text:08048562                 imul    edx
.text:08048564                 sar     edx, 1
.text:08048566                 mov     eax, ecx
.text:08048568                 sar     eax, 1Fh
.text:0804856B                 sub     edx, eax
.text:0804856D                 mov     eax, edx

5.4 其它同理自己建立项目研究

自己建立项目研究.高手复习 新手学习 谢谢观看


[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

最后于 2020-9-12 09:19 被TkBinary编辑 ,原因: 修复公式截图错误
收藏
点赞24
打赏
分享
最新回复 (13)
雪    币: 1768
活跃值: (239)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Passdtab 2020-9-9 17:21
2
0
火钳刘明
雪    币: 10
活跃值: (84)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
大头哥 2020-9-9 17:28
3
0
收藏
雪    币: 2415
活跃值: (9240)
能力值: ( LV13,RANK:385 )
在线值:
发帖
回帖
粉丝
TkBinary 5 2020-9-9 17:30
4
0
大头哥 收藏
谢谢,要观看
雪    币: 22979
活跃值: (3337)
能力值: (RANK:648 )
在线值:
发帖
回帖
粉丝
KevinsBobo 8 2020-9-9 17:53
5
0

别光收藏呀,要回帖、点赞,三连走起!

最后于 2020-9-9 18:06 被KevinsBobo编辑 ,原因:
雪    币: 232
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
《张少》 2020-9-9 18:17
6
0
支持~
雪    币: 3359
活跃值: (3397)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
fengyunabc 1 2020-9-11 17:57
7
0
感谢分享!
雪    币: 3977
活跃值: (744)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
gaoan 2021-3-29 17:20
8
0

老哥这里是打错字了吧, 不应该是1F吗?

乘法的结果 然后我们直接操作了乘积的高位 这里右移1 等价于是 除以 image-20200907225444244

雪    币: 2415
活跃值: (9240)
能力值: ( LV13,RANK:385 )
在线值:
发帖
回帖
粉丝
TkBinary 5 2021-3-29 17:56
9
0
gaoan 老哥这里是打错字了吧, 不应该是1F吗?乘法的结果 然后我们直接操作了乘积的高位&nbsp;这里右移1 等价于是 除以&nbsp;
1F是调整符号位.代表是有符号除法. sar edx 是操作的 edx,eax eax = 2^32次方. 而这里对edx操作了1 那么就是 操作了2^33次方.  欢迎继续提出问题. 
雪    币: 229
活跃值: (23)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Nixiak 2021-3-29 18:05
10
0
支持~
雪    币: 3977
活跃值: (744)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
gaoan 2021-3-30 09:47
11
0
TkBinary 1F是调整符号位.代表是有符号除法. sar edx 是操作的 edx,eax eax = 2^32次方. 而这里对edx操作了1 那么就是 操作了2^33次方. 欢迎继续提出问题.
谢谢指点
雪    币: 3977
活跃值: (744)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
gaoan 2021-4-2 10:17
12
0

其中 2n/b这个是可以在编译期中计算出来的. VC++6.0 或者VS2019 在编译 期间n的取值是大于32的.所以是可以算出来的.

老哥,这里说的是2的n次方还是2*n,实在没搞明白,可以指点下吗?


雪    币: 2415
活跃值: (9240)
能力值: ( LV13,RANK:385 )
在线值:
发帖
回帖
粉丝
TkBinary 5 2021-4-2 10:44
13
0
gaoan 其中 2n/b这个是可以在编译期中计算出来的. VC++6.0 或者VS2019 在编译 期间n的取值是大于32的.所以是可以算出来的.老哥,这里说的是2的n次方还是2*n,实在没搞明白,可以指点下吗 ...
都是2^n 不是2*n 除法你都认为是2^n就行.
雪    币: 3977
活跃值: (744)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
gaoan 2021-4-2 15:20
14
0
TkBinary 都是2^n 不是2*n 除法你都认为是2^n就行.
打扰了 还有一个问题 关于 sar edx, 1 为什么除以3的时候n取值为0, 除以9的时候取值为1呢?
游客
登录 | 注册 方可回帖
返回