0%

C++反汇编与逆向分析 - 循环

VC++使用三种语法来完成循环结构,分别为do、while、for;

  • do循环:先执行循环体,后比较循环
  • while循环:先比较循环,执行循环体
  • for循环:先初始化再比较判断,最后执行循环体

运行环境:

  • 操作系统: Windows 7家庭版
  • 编译器:VC6 VS2013

循环

do

特点包括:

1
2
3
4
DO_BEGIN:
...... 代码
jxx DO_BEGIN ;减量跳转,if为增量跳转
DO_END

首先分析Debug版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// Test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdlib.h>
int main(int argc, char* argv[])
{
int n = 0;
int nSum = 0;
do
{
nSum = nSum + n;
n++;
} while (n <= 100);
printf("Hello World!\n");
return 0;
}



8: int n = 0;
00401028 mov dword ptr [ebp-4],0
9: int nSum = 0;
0040102F mov dword ptr [ebp-8],0
10: do
11: {
12: nSum = nSum + n;
00401036 mov eax,dword ptr [ebp-8]
00401039 add eax,dword ptr [ebp-4]
0040103C mov dword ptr [ebp-8],eax
13: n++;
0040103F mov ecx,dword ptr [ebp-4]
00401042 add ecx,1
00401045 mov dword ptr [ebp-4],ecx
14: } while (n <= 100);
00401048 cmp dword ptr [ebp-4],64h
0040104C jle main+26h (00401036) ;减量跳转
15: printf("Hello World!\n");
0040104E push offset string "Hello World!\n" (0042201c)
00401053 call printf (00401080)
00401058 add esp,4
16: return 0;
0040105B xor eax,eax

while

代码定式:

1
2
3
4
5
WHILE_BEGIN:
jxx WHILE_END
.....
jmp WHILE_BEGIN
WHILE_END:

首先分析Debug版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
int main(int argc, char* argv[])
{
int n = 0;
int nSum = 0;
while(n <= 100)
{
nSum = nSum + n;
n++;
}
printf("Hello World!\n");
return 0;
}


22: int n = 0;
004010B8 mov dword ptr [ebp-4],0
23: int nSum = 0;
004010BF mov dword ptr [ebp-8],0
24: while(n <= 100)
004010C6 cmp dword ptr [ebp-4],64h ;上界
004010CA jg main+40h (004010e0)
25: {
26: nSum = nSum + n;
004010CC mov eax,dword ptr [ebp-8]
004010CF add eax,dword ptr [ebp-4]
004010D2 mov dword ptr [ebp-8],eax
27: n++;
004010D5 mov ecx,dword ptr [ebp-4]
004010D8 add ecx,1
004010DB mov dword ptr [ebp-4],ecx
28: }
004010DE jmp main+26h (004010c6) ;下界
29: printf("Hello World!\n");
004010E0 push offset string "Hello World!\n" (0042201c)
004010E5 call printf (00401120)
004010EA add esp,4
30: return 0;

for

代码定式:

1
2
3
4
5
6
7
8
9
10
11
12
FOR_INIT:
n = 1;
nSum = 0;
jmp FOR_CMP
FOR_STEP:
n++;
FOR_CMP:
n <= 100; jxx
jxx FOR_END
nSum = nSum + n
jmp FOR_STEP
JMP_END:

分析Debug版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
int main(int argc, char* argv[])
{

for (int n = 1, nSum = 0;n <= 100; n++)
{
nSum = nSum + n;
}
printf("Hello World!\n");
return 0;
}


36:
37: for (int n = 1, nSum = 0;n <= 100; n++)
0040D7C8 mov dword ptr [ebp-4],1
0040D7CF mov dword ptr [ebp-8],0
0040D7D6 jmp main+31h (0040d7e1) //初始化部分
0040D7D8 mov eax,dword ptr [ebp-4]
0040D7DB add eax,1 //循环加1
0040D7DE mov dword ptr [ebp-4],eax
0040D7E1 cmp dword ptr [ebp-4],64h
0040D7E5 jg main+42h (0040d7f2) //比较部分
38: {
39: nSum = nSum + n;
0040D7E7 mov ecx,dword ptr [ebp-8] //循环体
0040D7EA add ecx,dword ptr [ebp-4]
0040D7ED mov dword ptr [ebp-8],ecx
40: }
0040D7F0 jmp main+28h (0040d7d8) //跳回比较
41: printf("Hello World!\n");
0040D7F2 push offset string "Hello World!\n" (0042201c)
0040D7F7 call printf (00401120)
0040D7FC add esp,4
42: return 0;
0040D7FF xor eax,eax

所有的循环在Release中都会被优化为do.while

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.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 argc = dword ptr 4
.text:00401000 argv = dword ptr 8
.text:00401000 envp = dword ptr 0Ch
.text:00401000
.text:00401000 mov eax, 1
.text:00401005 xor ecx, ecx
.text:00401007
.text:00401007 loc_401007: ; CODE XREF: _main+D↓j
.text:00401007 add ecx, eax
.text:00401009 inc eax
.text:0040100A cmp eax, 64h
.text:0040100D jle short loc_401007
.text:0040100F xor eax, eax
.text:00401011 retn
.text:00401011 _main endp
.text:00401011