zoukankan      html  css  js  c++  java
  • c++ 反汇编 除法优化

    接上篇:《C++反汇编与逆向分析技术揭秘》--算术运算和赋值

    printf("argc / 4 = %d ", argc / 4);
    printf("argc / 5 = %d ", argc / 5);
    printf("argc / 7 = %d ", argc / 7);
    printf("argc / -4 = %d ", argc / -4);
    printf("argc / -5 = %d ", argc / -5);
    printf("argc / -7 = %d ", argc / -7);
    printf("argc % 3 = %d ", argc % 3);
    printf("argc % 4 = %d ", argc % 4);
    printf("argc % -7 = %d ", argc % -7);
    printf("argc % -8 = %d ", argc % -8);

    01334B50 <ope | 55                 | push ebp                         | operation.cpp:156
    01334B51      | 8BEC               | mov ebp,esp                      |
    01334B53      | 56                 | push esi                         | esi:__argc
    01334B54      | 57                 | push edi                         |
    01334B55      | 8B7D 08            | mov edi,dword ptr ss:[ebp+0x8]   | operation.cpp:162
    01334B58      | 8BC7               | mov eax,edi                      |除数为2的幂时采用sar,算术右移,相当于向下取整,负数情况下需要调整
    01334B5A      | 99                 | cdq                              |
    01334B5B      | 83E2 03            | and edx,0x3                      |考虑被除数为负数时,要加上(2^n)-1,
    01334B5E      | 03C2               | add eax,edx                      |
    01334B60      | C1F8 02            | sar eax,0x2                      |
    01334B63      | 50                 | push eax                         |
    01334B64      | 68 FC933A01        | push operation.13A93FC           | 13A93FC:"argc / 4 = %d
    "
    01334B69      | E8 02010000        | call <operation.printf>          |
    01334B6E      | B8 67666666        | mov eax,0x66666667               |
    01334B73      | F7EF               | imul edi                         |
    01334B75      | D1FA               | sar edx,0x1                      |
    01334B77      | 8BC2               | mov eax,edx                      |>>>2**33/0x66666667 =4.99999999825377
    01334B79      | C1E8 1F            | shr eax,0x1F                     |
    01334B7C      | 03C2               | add eax,edx                      |
    01334B7E      | 50                 | push eax                         |
    01334B7F      | 68 0C943A01        | push operation.13A940C           | 13A940C:"argc / 5 = %d
    "
    01334B84      | E8 E7000000        | call <operation.printf>          |
    01334B89      | B8 93244992        | mov eax,0x92492493               |
    01334B8E      | F7EF               | imul edi                         |
    01334B90      | 03D7               | add edx,edi                      |
    01334B92      | C1FA 02            | sar edx,0x2                      |
    01334B95      | 8BF2               | mov esi,edx                      | >>> 2**34/0x92492493=6.999999997962732
    01334B97      | C1EE 1F            | shr esi,0x1F                     | esi:__argc
    01334B9A      | 03F2               | add esi,edx                      | esi:__argc
    01334B9C      | 56                 | push esi                         | esi:__argc
    01334B9D      | 68 1C943A01        | push operation.13A941C           | 13A941C:"argc / 7 = %d
    "
    01334BA2      | E8 C9000000        | call <operation.printf>          |
    01334BA7      | 8BC7               | mov eax,edi                      |
    01334BA9      | 99                 | cdq                              |
    01334BAA      | 83E2 03            | and edx,0x3                      |
    01334BAD      | 03C2               | add eax,edx                      |
    01334BAF      | C1F8 02            | sar eax,0x2                      |
    01334BB2      | F7D8               | neg eax                          |//多一步取反
    01334BB4      | 50                 | push eax                         |
    01334BB5      | 68 2C943A01        | push operation.13A942C           | 13A942C:"argc / -4 = %d
    "
    01334BBA      | E8 B1000000        | call <operation.printf>          |
    01334BBF      | B8 99999999        | mov eax,0x99999999               |
    01334BC4      | F7EF               | imul edi                         |
    01334BC6      | D1FA               | sar edx,0x1                      |
    01334BC8      | 8BC2               | mov eax,edx                      |>>> 2**33/(2**32-0x99999999)=4.99999999825377
    01334BCA      | C1E8 1F            | shr eax,0x1F                     |
    01334BCD      | 03C2               | add eax,edx                      |
    01334BCF      | 50                 | push eax                         |
    01334BD0      | 68 3C943A01        | push operation.13A943C           | 13A943C:"argc / -5 = %d
    "
    01334BD5      | E8 96000000        | call <operation.printf>          |
    01334BDA      | B8 6DDBB66D        | mov eax,0x6DB6DB6D               |
    01334BDF      | F7EF               | imul edi                         |
    01334BE1      | 2BD7               | sub edx,edi                      |
    01334BE3      | C1FA 02            | sar edx,0x2                      |
    01334BE6      | 8BC2               | mov eax,edx                      |>>> 2**34/(2**32-0x6db6db6d)=6.999999997962732
    01334BE8      | C1E8 1F            | shr eax,0x1F                     |
    01334BEB      | 03C2               | add eax,edx                      |
    01334BED      | 50                 | push eax                         |
    01334BEE      | 68 4C943A01        | push operation.13A944C           | 13A944C:"argc / -7 = %d
    "
    01334BF3      | E8 78000000        | call <operation.printf>          |
    01334BF8      | B8 56555555        | mov eax,0x55555556               |
    01334BFD      | 8BCF               | mov ecx,edi                      |
    01334BFF      | F7EF               | imul edi                         |
    01334C01      | 8BC2               | mov eax,edx                      |>>> 2**32/0x55555556=2.999999998603016
    01334C03      | C1E8 1F            | shr eax,0x1F                     |
    01334C06      | 03C2               | add eax,edx                      |
    01334C08      | 8D0440             | lea eax,dword ptr ds:[eax+eax*2] |
    01334C0B      | 2BC8               | sub ecx,eax                      |
    01334C0D      | 51                 | push ecx                         |
    01334C0E      | 68 5C943A01        | push operation.13A945C           | 13A945C:"argc % 3 = %d
    "
    01334C13      | E8 58000000        | call <operation.printf>          |
    01334C18      | 8BC7               | mov eax,edi                      |
    01334C1A      | 25 03000080        | and eax,0x80000003               |对2的N次方数取余使用and操作,x%2^N 使用位运算x & (2^N - 1)代替
    01334C1F      | 79 05              | jns operation.1334C26            |
    01334C21      | 48                 | dec eax                          |减一
    01334C22      | 83C8 FC            | or eax,0xFFFFFFFC                |相当于取反
    01334C25      | 40                 | inc eax                          |加一
    01334C26      | 50                 | push eax                         |
    01334C27      | 68 6C943A01        | push operation.13A946C           | 13A946C:"argc % 4 = %d
    "
    01334C2C      | E8 3F000000        | call <operation.printf>          |
    01334C31      | 83C4 40            | add esp,0x40                     |
    01334C34      | 8D0CF5 00000000    | lea ecx,dword ptr ds:[esi*8]     |
    01334C3B      | 2BCE               | sub ecx,esi                      | esi:__argc
    01334C3D      | 8BC7               | mov eax,edi                      |
    01334C3F      | 2BC1               | sub eax,ecx                      |
    01334C41      | 50                 | push eax                         |
    01334C42      | 68 7C943A01        | push operation.13A947C           | 13A947C:"argc % -7 = %d
    "
    01334C47      | E8 24000000        | call <operation.printf>          |
    01334C4C      | 81E7 07000080      | and edi,0x80000007               |
    01334C52      | 79 05              | jns operation.1334C59            |
    01334C54      | 4F                 | dec edi                          |减一
    01334C55      | 83CF F8            | or edi,0xFFFFFFF8                |
    01334C58      | 47                 | inc edi                          |
    01334C59      | 57                 | push edi                         |
    01334C5A      | 68 8C943A01        | push operation.13A948C           | 13A948C:"argc % -8 = %d
    "
    01334C5F      | E8 0C000000        | call <operation.printf>          |
    01334C64      | 83C4 10            | add esp,0x10                     |
    01334C67      | 33C0               | xor eax,eax                      | operation.cpp:167
    01334C69      | 5F                 | pop edi                          |
    01334C6A      | 5E                 | pop esi                          | esi:__argc
    01334C6B      | 5D                 | pop ebp                          | operation.cpp:168
    01334C6C      | C3                 | ret                              |
     除数为正数时:
         除数为2的幂时
             mov eax,edi                      
             cdq                              
             and edx,0x3                     
             add eax,edx                     
             sar eax,0x2                     /4
         
         除数不为2的幂时:
             magicnumber<=0x7fffffff时:
             mov eax,0x66666667               |
             imul edi                         |
             sar edx,0x1                      |
             mov eax,edx                      |>>>2**33/0x66666667 =4.99999999825377
             shr eax,0x1F                     |
             add eax,edx
         
             magicnumber>0x7fffffff时:
             mov eax,0x92492493               |
             imul edi                         |
             add edx,edi                      |
             sar edx,0x2                      |
             mov esi,edx                      | >>> 2**34/0x92492493=6.999999997962732
             shr esi,0x1F                
             add esi,edx
     
     
     除数为负数时:
         除数为2的幂时
             mov eax,edi                      
             cdq                              
             and edx,0x3                      
             add eax,edx                      
             sar eax,0x2                      
             neg eax                           /-4
         
         除数不为2的幂时
             magicnumber<=0x7fffffff时:
             mov eax,0x6DB6DB6D               |
             imul edi                         |
             sub edx,edi                      |
             sar edx,0x2                      |
             mov eax,edx                      |>>> 2**34/(2**32-0x6db6db6d)=6.999999997962732     -7
             shr eax,0x1F                     |
             add eax,edx
         
             magicnumber>0x7fffffff时:
             mov eax,0x99999999               |
             imul edi                         |
             sar edx,0x1                      |
             mov eax,edx                      |>>> 2**33/(2**32-0x99999999)=4.99999999825377      -5
             shr eax,0x1F                     |
             add eax,edx 
     
     
     模运算
         模数为2的幂时                      
             mov eax,edi                      |%4
             and eax,0x80000003               |对2的N次方数取余使用and操作,x%2^N 使用位运算x & (2^N - 1)代替
             jns operation.1334C26            |
             dec eax                          |减一
             or eax,0xFFFFFFFC                |相当于取反
             inc eax                          |加一           
         
         模数不为2的幂时
             mov eax,0x55555556               |%3
             mov ecx,edi                      |
             imul edi                         |
             mov eax,edx                      |>>> 2**32/0x55555556=2.999999998603016
             shr eax,0x1F                     |
             add eax,edx                      |
             lea eax,dword ptr ds:[eax+eax*2] |
             sub ecx,eax                      |
             push ecx    
        模数为负时实现相同

    除数为正数时,使用公式o=2^n/c,将MagicNumber作为c值代入公式求解常量除数o,即可恢复除法原型

    特殊情况:

     

     除数为负数时:统计右移的总次数以确定公式中的n值,然后使用公式|o|=(2^n) / (2^32 -c)。,将MagicNumber作为c值代入公式求解常量除数lol,即可恢复除法原型。

    模运算:对两个变量取模或者对非2的幂取模,可直接使用div或idiv指令完成,余数在dx或者是edx中。

    对2的k次方取余,余数的值只需取得被除数二进制数值中的最后k位的值即可,负数则还需在k位之前补1,

    x % 2^N  使用 x & (2^N - 1)代替

     对于为什么要这样优化呢?这其中涉及到一些数学知识,有兴趣的可以继续深入研究下去。

    其实能够总结出各种优化的特征,遇到时可以还原操作便达到了我们逆向分析的目的。

  • 相关阅读:
    EntityFramework Code-First 简易教程(五)-------领域类配置
    EntityFramework Code-First 简易教程(四)-------继承策略
    Springboot整合mybatis:Invalid bound statement (not found)
    centos7服务器安装mysql8
    redis-Jedis
    redis学习-集群模式cluster
    redis学习-发布订阅
    redis学习-持久化机制
    redis学习-简单事务
    redis学习-哨兵模式
  • 原文地址:https://www.cnblogs.com/DirWang/p/12150117.html
Copyright © 2011-2022 走看看