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

2023-03-18,,

一、加法

1.Debug下:

14:     int nVarOne0 = 1 + 5 - 3 * 6;//编译时计算得到结果
00C0550E C7 45 F8 F4 FF FF FF mov dword ptr [nVarOne0],0FFFFFFF4h
15: cout << nVarOne0 << endl;
00C05515 68 9D 4A BF 00 push offset std::endl<char,std::char_traits<char> > (0BF4A9Dh)
00C0551A 8B 45 F8 mov eax,dword ptr [nVarOne0]
00C0551D 50 push eax
00C0551E B9 F8 B1 D5 00 mov ecx,offset std::cout (0D5B1F8h)
00C05523 E8 9A C1 FE FF call std::basic_ostream<char,std::char_traits<char> >::operator<< (0BF16C2h)
15: cout << nVarOne0 << endl;
00C05528 8B C8 mov ecx,eax
00C0552A E8 7C E7 FE FF call std::basic_ostream<char,std::char_traits<char> >::operator<< (0BF3CABh)
16: int nVarTwo = 0;//变量赋值,立即数
00C0552F C7 45 EC 00 00 00 00 mov dword ptr [nVarTwo],0
17: int nVarOne = argc;//赋值 变量
00C05536 8B 45 08 mov eax,dword ptr [argc]
00C05539 89 45 E0 mov dword ptr [nVarOne],eax
18: //int nVarTwo = argc;
19:
20: nVarOne = nVarOne + 1;//变量+常数
00C0553C 8B 45 E0 mov eax,dword ptr [nVarOne] //取变量
00C0553F 83 C0 01 add eax,1 //加 立即数
00C05542 89 45 E0 mov dword ptr [nVarOne],eax
21: nVarOne = 1 + 2;//编译时得到结果,立即数
00C05545 C7 45 E0 03 00 00 00 mov dword ptr [nVarOne],3
22: nVarOne = nVarOne + nVarTwo;//变量+变量
00C0554C 8B 45 E0 mov eax,dword ptr [nVarOne]
00C0554F 03 45 EC add eax,dword ptr [nVarTwo]
00C05552 89 45 E0 mov dword ptr [nVarOne],eax
23:
24: printf("nVarOne = %d \r\n", nVarOne);
00C05555 8B 45 E0 mov eax,dword ptr [nVarOne]
00C05558 50 push eax
00C05559 68 14 A3 D1 00 push offset string "nVarOne = %d \r\n" (0D1A314h)
00C0555E E8 55 C1 FE FF call _printf (0BF16B8h)
00C05563 83 C4 08 add esp,8

2.release

00854B07      | 6A F4          | push 0xFFFFFFF4                                                                | //直接计算出结果
00854B09 | B9 501A8E00 | mov ecx,<operation.std::cout> |
00854B0E | E8 2DD4FFFF | call <operation.std::basic_ostream<char,std::char_traits<char> >::operator<<> |
00854B13 | 8BF8 | mov edi,eax | edi:&"E:\\Des\\C++反汇编与逆向分析技术揭秘与随书源码\\随书相关代码\\第四章\\Operation\\Release\\Operation.exe"
00854B15 | 8B0F | mov ecx,dword ptr ds:[edi] | [edi]:"E:\\Des\\C++反汇编与逆向分析技术揭秘与随书源码\\随书相关代码\\第四章\\Operation\\Release\\Operation.exe"
00854B17 | 8B49 04 | mov ecx,dword ptr ds:[ecx+0x4] |
00854B1A | 8B4C39 30 | mov ecx,dword ptr ds:[ecx+edi+0x30] | ecx+edi*1+30:"源码\\随书相关代码\\第四章\\Operation\\Release\\Operation.exe"
00854B1E | 8B71 04 | mov esi,dword ptr ds:[ecx+0x4] | esi:__argc
00854B21 | 8BCE | mov ecx,esi | esi:__argc
00854B23 | C745 FC 000000 | mov dword ptr ss:[ebp-0x4],0x0 |//变量nVarTwo 赋值0
00854B2A | 8975 F0 | mov dword ptr ss:[ebp-0x10],esi |
····················
优化的内嵌函数
····················
00854B89 | 6A 03 | push 0x3 |//编译时进行了优化,直接得到变量nVarOne值为3
00854B8B | 68 6C938C00 | push operation.8C936C | 8C936C:"nVarOne = %d \r\n"
00854B90 | E8 1B000000 | call <operation.printf> |

二、减法:

1.Debug

29:     // 变量定义
30: int nVarOne = argc;
00046A6E 8B 45 08 mov eax,dword ptr [argc]
00046A71 89 45 F8 mov dword ptr [nVarOne],eax
31: int nVarTwo = argc;
00046A74 8B 45 08 mov eax,dword ptr [argc]
00046A77 89 45 EC mov dword ptr [nVarTwo],eax
32: scanf("%d", &nVarTwo);
00046A7A 8D 45 EC lea eax,[nVarTwo]
00046A7D 50 push eax
00046A7E 68 AC A7 15 00 push offset string "%d" (015A7ACh)
00046A83 E8 38 B3 FE FF call _scanf (031DC0h)
00046A88 83 C4 08 add esp,8
33: // 变量减常量的减法运算
34: nVarOne = nVarOne - 100;
00046A8B 8B 45 F8 mov eax,dword ptr [nVarOne]
00046A8E 83 E8 64 sub eax,64h
00046A91 89 45 F8 mov dword ptr [nVarOne],eax
35: // 减法与加法混合运算
36: nVarOne = nVarOne + 5 - nVarTwo ;
00046A94 8B 45 F8 mov eax,dword ptr [nVarOne]
00046A97 83 C0 05 add eax,5
00046A9A 2B 45 EC sub eax,dword ptr [nVarTwo]
00046A9D 89 45 F8 mov dword ptr [nVarOne],eax
37: printf("nVarOne = %d \r\n", nVarOne);
00046AA0 8B 45 F8 mov eax,dword ptr [nVarOne]
37: printf("nVarOne = %d \r\n", nVarOne);
00046AA3 50 push eax
00046AA4 68 14 A3 15 00 push offset string "nVarOne = %d \r\n" (015A314h)
00046AA9 E8 0A AC FE FF call _printf (0316B8h)
00046AAE 83 C4 08 add esp,8
38:
39: }

2.release

00C94AE0 <operati | 55                    | push ebp                         | operation.cpp:137
00C94AE1 | 8BEC | mov ebp,esp |
00C94AE3 | 56 | push esi | esi:__argc
00C94AE4 | 8B75 08 | mov esi,dword ptr ss:[ebp+0x8] | //变量nVarOne, esi:__argc
00C94AE7 | 8D45 08 | lea eax,dword ptr ss:[ebp+0x8] |
00C94AEA | 50 | push eax | eax:&"#envTSLOGSHELLEXT8692=95686944"
00C94AEB | 68 7C93D000 | push operation.D0937C | D0937C:"%d"
00C94AF0 | 8975 08 | mov dword ptr ss:[ebp+0x8],esi | //ebp+8看作nVarTwo esi:__argc
00C94AF3 | E8 58000000 | call <operation.scanf> | //输入将修改ebp+8,即nVarTwo
00C94AF8 | 2B75 08 | sub esi,dword ptr ss:[ebp+0x8] | //nVarOne-nVarTwo esi:__argc
00C94AFB | 83EE 5F | sub esi,0x5F | //nVarOne-95 esi:__argc
00C94AFE | 56 | push esi | esi:__argc
00C94AFF | 68 6C93D000 | push operation.D0936C | D0936C:"nVarOne = %d \r\n"
00C94B04 | E8 17000000 | call <operation.printf> |
00C94B09 | 83C4 10 | add esp,0x10 |
00C94B0C | 33C0 | xor eax,eax | operation.cpp:148, eax:&"#envTSLOGSHELLEXT8692=95686944"
00C94B0E | 5E | pop esi | esi:__argc
00C94B0F | 5D | pop ebp | operation.cpp:149

三、乘法:

1.debug

 43:     int nVarOne = argc;
00A8697E 8B 45 08 mov eax,dword ptr [argc]
00A86981 89 45 F8 mov dword ptr [nVarOne],eax
44: int nVarTwo = argc;
00A86984 8B 45 08 mov eax,dword ptr [argc]
00A86987 89 45 EC mov dword ptr [nVarTwo],eax
45: // 乘法运算
46: printf("nVarOne * 15 = %d\n", nVarOne * 15);//15 非2的倍数,debug下无优化
00A8698A 6B 45 F8 0F imul eax,dword ptr [nVarOne],0Fh
00A8698E 50 push eax
00A8698F 68 C0 A7 B9 00 push offset string "nVarOne * 15 = %d\n" (0B9A7C0h)
00A86994 E8 1F AD FE FF call _printf (0A716B8h)
00A86999 83 C4 08 add esp,8
47: printf("nVarOne * 16 = %d\n", nVarOne * 16);//16=2**4
00A8699C 8B 45 F8 mov eax,dword ptr [nVarOne]
00A8699F C1 E0 04 shl eax,4 //左移4位,相当于乘16
00A869A2 50 push eax
00A869A3 68 D8 A7 B9 00 push offset string "nVarOne * 16 = %d\n" (0B9A7D8h)
00A869A8 E8 0B AD FE FF call _printf (0A716B8h)
00A869AD 83 C4 08 add esp,8
48: printf("2 * 2 = %d\n", 2 * 2);
00A869B0 6A 04 push 4 //编译时直接得到结果
00A869B2 68 F0 A7 B9 00 push offset string "2 * 2 = %d\n" (0B9A7F0h)
00A869B7 E8 FC AC FE FF call _printf (0A716B8h)
00A869BC 83 C4 08 add esp,8
49: printf("nVarTwo * 4 + 5 = %d\n", nVarTwo * 4 + 5);//乘数变量为2的倍数,利用lea指令进行 乘法和加法的混合运算
00A869BF 8B 45 EC mov eax,dword ptr [nVarTwo]
00A869C2 8D 0C 85 05 00 00 00 lea ecx,[eax*4+5]
00A869C9 51 push ecx
00A869CA 68 00 A8 B9 00 push offset string "nVarTwo * 4 + 5 = %d\n" (0B9A800h)
00A869CF E8 E4 AC FE FF call _printf (0A716B8h)
00A869D4 83 C4 08 add esp,8
50: printf("nVarTwo * 9 + 5 = %d\n", nVarTwo * 9 + 5);//乘数变量不为2的倍数,debug下无优化
00A869D7 6B 45 EC 09 imul eax,dword ptr [nVarTwo],9
00A869DB 83 C0 05 add eax,5
00A869DE 50 push eax
00A869DF 68 1C A8 B9 00 push offset string "nVarTwo * 9 + 5 = %d\n" (0B9A81Ch)
00A869E4 E8 CF AC FE FF call _printf (0A716B8h)
00A869E9 83 C4 08 add esp,8
51: printf("nVarOne * nVarTwo = %d\n", nVarOne * nVarTwo);//变量之间相乘,无优化
00A869EC 8B 45 F8 mov eax,dword ptr [nVarOne]
00A869EF 0F AF 45 EC imul eax,dword ptr [nVarTwo]
00A869F3 50 push eax
00A869F4 68 38 A8 B9 00 push offset string "nVarOne * nVarTwo = %d\n" (0B9A838h)
00A869F9 E8 BA AC FE FF call _printf (0A716B8h)
00A869FE 83 C4 08 add esp,8
52: }

2.release

00AF4AE4          | 8B75 08            | mov esi,dword ptr ss:[ebp+0x8]       | operation.cpp:142
00AF4AE7 | 8BC6 | mov eax,esi |
00AF4AE9 | C1E0 04 | shl eax,0x4 |//nVarOne*15 分解为 nVarOne*16-nVarOne
00AF4AEC | 2BC6 | sub eax,esi |
00AF4AEE | 50 | push eax |
00AF4AEF | 68 8093B600 | push operation.B69380 | B69380:"nVarOne * 15 = %d\n"
00AF4AF4 | E8 67000000 | call <operation.printf> |
00AF4AF9 | 8BC6 | mov eax,esi |
00AF4AFB | C1E0 04 | shl eax,0x4 |//左移4位,即*16
00AF4AFE | 50 | push eax |
00AF4AFF | 68 9493B600 | push operation.B69394 | B69394:"nVarOne * 16 = %d\n"
00AF4B04 | E8 57000000 | call <operation.printf> |
00AF4B09 | 6A 04 | push 0x4 |
00AF4B0B | 68 A893B600 | push operation.B693A8 | B693A8:"2 * 2 = %d\n"
00AF4B10 | E8 4B000000 | call <operation.printf> |
00AF4B15 | 8D04B5 05000000 | lea eax,dword ptr ds:[esi*4+0x5] |与debug模式下处理相同
00AF4B1C | 50 | push eax |
00AF4B1D | 68 B493B600 | push operation.B693B4 | B693B4:"nVarTwo * 4 + 5 = %d\n"
00AF4B22 | E8 39000000 | call <operation.printf> |
00AF4B27 | 8D04F5 05000000 | lea eax,dword ptr ds:[esi*8+0x5] |//nVarTwo*9+5 分解为 nVarTwo*8+5+nVarTwo
00AF4B2E | 03C6 | add eax,esi |//
00AF4B30 | 50 | push eax |
00AF4B31 | 68 CC93B600 | push operation.B693CC | B693CC:"nVarTwo * 9 + 5 = %d\n"
00AF4B36 | E8 25000000 | call <operation.printf> |
00AF4B3B | 0FAFF6 | imul esi,esi |//变量之间乘法无优化
00AF4B3E | 56 | push esi |
00AF4B3F | 68 E493B600 | push operation.B693E4 | B693E4:"nVarOne * nVarTwo = %d\n"
00AF4B44 | E8 17000000 | call <operation.printf> |
00AF4B49 | 83C4 30 | add esp,0x30 |

四、除法

1.debug

 56:     int nVarOne = argc;
0032680E 8B 45 08 mov eax,dword ptr [argc]
00326811 89 45 F8 mov dword ptr [nVarOne],eax
57: int nVarTwo = argc;
00326814 8B 45 08 mov eax,dword ptr [argc]
00326817 89 45 EC mov dword ptr [nVarTwo],eax
58: // 除法运算
59: printf("nVarOne / nVarTwo = %d\n", nVarOne / nVarTwo);//两个变量之间除法,无优化
0032681A 8B 45 F8 mov eax,dword ptr [nVarOne]
0032681D 99 cdq
0032681E F7 7D EC idiv eax,dword ptr [nVarTwo] //直接使用 idiv 有符号数除法指令,商保存到eax,余数保存到edx
00326821 50 push eax
00326822 68 54 A8 43 00 push offset string "nVarOne / nVarTwo = %d\n" (043A854h)
00326827 E8 8C AE FE FF call _printf (03116B8h)
0032682C 83 C4 08 add esp,8
60: printf("nVarOne / 2 = %d\n", nVarOne / 2);//被除数为2的倍数时,使用算术移位来优化
0032682F 8B 45 F8 mov eax,dword ptr [nVarOne]
00326832 99 cdq //eax高位拓展到edx,即用变量eax的符号位来占满edx每一位
00326833 2B C2 sub eax,edx //正数无变化,负数则加1(c中有符号数除法为向零取正,正数相当于向下取整,负数相当于向上取整)
00326835 D1 F8 sar eax,1 //算术右移1位,相当于除2,(sar,高位用符号位补充)
00326837 50 push eax
00326838 68 70 A8 43 00 push offset string "nVarOne / 2 = %d\n" (043A870h)
0032683D E8 76 AE FE FF call _printf (03116B8h)
00326842 83 C4 08 add esp,8
61: printf("nVarTwo / 7 = %d\n", nVarTwo / 7);//被除数不为2的倍数时,无优化
00326845 8B 45 EC mov eax,dword ptr [nVarTwo]
00326848 99 cdq
00326849 B9 07 00 00 00 mov ecx,7
0032684E F7 F9 idiv eax,ecx
00326850 50 push eax
00326851 68 84 A8 43 00 push offset string "nVarTwo / 7 = %d\n" (043A884h)
00326856 E8 5D AE FE FF call _printf (03116B8h)
0032685B 83 C4 08 add esp,8
62: printf("nVarTwo % 7 = %d\n", nVarTwo % 7);//模运算,模数不为2的倍数时无优化
0032685E 8B 45 EC mov eax,dword ptr [nVarTwo]
00326861 99 cdq
00326862 B9 07 00 00 00 mov ecx,7
00326867 F7 F9 idiv eax,ecx
00326869 52 push edx
0032686A 68 98 A8 43 00 push offset string "nVarTwo % 7 = %d\n" (043A898h)
0032686F E8 44 AE FE FF call _printf (03116B8h)
00326874 83 C4 08 add esp,8
63: printf("nVarOne / 8 = %d\n", nVarOne / 8);
00326877 8B 45 F8 mov eax,dword ptr [nVarOne]
0032687A 99 cdq
0032687B 83 E2 07 and edx,7 //nVarOne为正数则dex为0,负数则edx为7
63: printf("nVarOne / 8 = %d\n", nVarOne / 8);
0032687E 03 C2 add eax,edx //负数除法时,相当于计算ceil(nVarOne/8)=》floor( (nVarOne+8-1)/8 )=》floor((nVarOne+7)/8);正数时,nVarOne/8
00326880 C1 F8 03 sar eax,3
00326883 50 push eax
00326884 68 AC A8 43 00 push offset string "nVarOne / 8 = %d\n" (043A8ACh)
00326889 E8 2A AE FE FF call _printf (03116B8h)
0032688E 83 C4 08 add esp,8
64: printf("nVarOne / 14 = %d\n", argc / 14);
00326891 8B 45 08 mov eax,dword ptr [argc]
00326894 99 cdq
00326895 B9 0E 00 00 00 mov ecx,0Eh
0032689A F7 F9 idiv eax,ecx
0032689C 50 push eax
0032689D 68 C0 A8 43 00 push offset string "nVarOne / 14 = %d\n" (043A8C0h)
003268A2 E8 11 AE FE FF call _printf (03116B8h)
003268A7 83 C4 08 add esp,8

计算nVarOne/2时:

0032682F 8B 45 F8             mov         eax,dword ptr [nVarOne]
00326832 99 cdq //eax高位拓展到edx,即用变量eax的符号位来占满edx每一位
00326833 2B C2 sub eax,edx //正数无变化,负数则加1(c中有符号数除法为向零取正,正数相当于向下取整,负数相当于向上取整)
00326835 D1 F8 sar eax,1

计算nVarOne/8时:

00326877 8B 45 F8             mov         eax,dword ptr [nVarOne]
0032687A 99 cdq
0032687B 83 E2 07 and edx,7 //nVarOne为正数则dex为0,负数则edx为7
0032687E 03 C2 add eax,edx //负数除法时,相当于计算ceil(nVarOne/8)=》floor( (nVarOne+8-1)/8 )=》floor((nVarOne+7)/8);正数时,nVarOne/8
00326880 C1 F8 03 sar eax,3

2.release

00224AE5          | 6A 01              | push 0x1                             | //赋值相同的变量,编译时得到结果
00224AE7 | 68 FC932900 | push operation.2993FC | 2993FC:"nVarOne / nVarTwo = %d\n"
00224AEC | E8 8F000000 | call <operation.printf> |
00224AF1 | 8B7D 08 | mov edi,dword ptr ss:[ebp+0x8] |
00224AF4 | 8BC7 | mov eax,edi |
00224AF6 | 99 | cdq |//将eax最高位拓展到edx每一位
00224AF7 | 2BC2 | sub eax,edx |正数eax不变,负数时eax+1
00224AF9 | D1F8 | sar eax,0x1 |右移1位,即/2
00224AFB | 50 | push eax |
00224AFC | 68 14942900 | push operation.299414 | 299414:"nVarOne / 2 = %d\n"
00224B01 | E8 7A000000 | call <operation.printf> |
00224B06 | B8 93244992 | mov eax,0x92492493 |//除法优化,改除为乘
00224B0B | F7EF | imul edi |
00224B0D | 03D7 | add edx,edi |
00224B0F | C1FA 02 | sar edx,0x2 |
00224B12 | 8BF2 | mov esi,edx | esi:__argc
00224B14 | C1EE 1F | shr esi,0x1F | esi:__argc
00224B17 | 03F2 | add esi,edx | esi:__argc
00224B19 | 56 | push esi | esi:__argc
00224B1A | 68 28942900 | push operation.299428 | 299428:"nVarTwo / 7 = %d\n"
00224B1F | E8 5C000000 | call <operation.printf> |
00224B24 | 8D0CF5 00000000 | lea ecx,dword ptr ds:[esi*8] | //设被除数为a,除数为b,商为q,余数为r,则 r=a-b*q ecx=(nVarTwo/7)*8
00224B2B | 8BC7 | mov eax,edi |
00224B2D | 2BCE | sub ecx,esi | //结合lea ecx,dword ptr ds:[esi*8],相当于ecx=(nVarTwo/7)*7 00224B2F | 2BC1 | sub eax,ecx | eax为被除数,减去ecx,得到余数
00224B31 | 50 | push eax |
00224B32 | 68 3C942900 | push operation.29943C | 29943C:"nVarTwo % 7 = %d\n"
00224B37 | E8 44000000 | call <operation.printf> |
00224B3C | 8BC7 | mov eax,edi |
00224B3E | 99 | cdq |
00224B3F | 83E2 07 | and edx,0x7 |负数情况下,下面要加2^n -1 =7
00224B42 | 03C2 | add eax,edx |
00224B44 | C1F8 03 | sar eax,0x3 |
00224B47 | 50 | push eax |
00224B48 | 68 50942900 | push operation.299450 | 299450:"nVarOne / 8 = %d\n"
00224B4D | E8 2E000000 | call <operation.printf> |
00224B52 | B8 93244992 | mov eax,0x92492493 |
00224B57 | F7EF | imul edi |
00224B59 | 03D7 | add edx,edi |
00224B5B | C1FA 03 | sar edx,0x3 |
00224B5E | 8BC2 | mov eax,edx |
00224B60 | C1E8 1F | shr eax,0x1F |
00224B63 | 03C2 | add eax,edx |
00224B65 | 50 | push eax |
00224B66 | 68 64942900 | push operation.299464 | 299464:"nVarOne / 14 = %d\n"
00224B6B | E8 10000000 | call <operation.printf> |
00224B70 | 83C4 30 | add esp,0x30 |

除法优化中,改除为乘的细节较多,日后再写,Orz,,

《C++反汇编与逆向分析技术揭秘》--算术运算和赋值的相关教程结束。

《《C++反汇编与逆向分析技术揭秘》--算术运算和赋值.doc》

下载本文的Word格式文档,以方便收藏与打印。