标签:color target cal lan number alt 常量 取整 ddb
接上篇:《C++反汇编与逆向分析技术揭秘》--算术运算和赋值
printf("argc / 4 = %d\n", argc / 4);
printf("argc / 5 = %d\n", argc / 5);
printf("argc / 7 = %d\n", argc / 7);
printf("argc / -4 = %d\n", argc / -4);
printf("argc / -5 = %d\n", argc / -5);
printf("argc / -7 = %d\n", argc / -7);
printf("argc % 3 = %d\n", argc % 3);
printf("argc % 4 = %d\n", argc % 4);
printf("argc % -7 = %d\n", argc % -7);
printf("argc % -8 = %d\n", 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\n" 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\n" 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\n" 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\n" 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\n" 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\n" 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\n" 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\n" 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\n" 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\n" 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)代替
对于为什么要这样优化呢?这其中涉及到一些数学知识,有兴趣的可以继续深入研究下去。
其实能够总结出各种优化的特征,遇到时可以还原操作便达到了我们逆向分析的目的。
标签:color target cal lan number alt 常量 取整 ddb
原文地址:https://www.cnblogs.com/DirWang/p/12150117.html