0%

C++反汇编与逆向分析 - IF

流程控制语句的识别是进行逆向分析和还原高级代码的基础;

运行环境:

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

流程控制

if语句

单分支

单分支循环还原比较容易,要点如下:

如果条件跳转为增量跳转(增量跳转向下跳转),且跳转目标上代码没有jmp,则为单分支;

将条件取反,进行还原

多分支

这样做的好处是可以将公共流程代码C合并为一个节点,减少了节点,增加了分支;

像这样的分支是有优化空间的;

编译器还会成这样的代码:

增加了节点,减少了分支;

源代码:

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// Test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

int main(int argc, char* argv[])
{
if (argc > 0)
{
printf("argc > 0\n");
}
else if (argc == 1)
{
printf("argc == 1\n");
}
else if (argc == 2)
{
printf("%d\n",argc * 9);
}
else if (argc == 3)
{
printf("argc == 3\n");
}
else if (argc == 4)
{
printf("argc == 4\n");
}
printf("HelloWorld\n");
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 argc = dword ptr 8
.text:00401000 argv = dword ptr 0Ch
.text:00401000 envp = dword ptr 10h
.text:00401000
.text:00401000 push ebp
.text:00401001 mov ebp, esp
.text:00401003 cmp [ebp+argc], 0
.text:00401007 jle short loc_401018
.text:00401009 push offset aArgc0 ; "argc > 0\n"
.text:0040100E call sub_401082
.text:00401013 add esp, 4
.text:00401016 jmp short loc_401071
.text:00401018 ; ---------------------------------------------------------------------------
.text:00401018
.text:00401018 loc_401018: ; CODE XREF: _main+7↑j
.text:00401018 cmp [ebp+argc], 1
.text:0040101C jnz short loc_40102D
.text:0040101E push offset aArgc1 ; "argc == 1\n"
.text:00401023 call sub_401082
.text:00401028 add esp, 4
.text:0040102B jmp short loc_401071
.text:0040102D ; ---------------------------------------------------------------------------
.text:0040102D
.text:0040102D loc_40102D: ; CODE XREF: _main+1C↑j
.text:0040102D cmp [ebp+argc], 2
.text:00401031 jnz short loc_401049
.text:00401033 mov eax, [ebp+argc]
.text:00401036 imul eax, 9
.text:00401039 push eax
.text:0040103A push offset aD ; "%d\n"
.text:0040103F call sub_401082
.text:00401044 add esp, 8
.text:00401047 jmp short loc_401071
.text:00401049 ; ---------------------------------------------------------------------------
.text:00401049
.text:00401049 loc_401049: ; CODE XREF: _main+31↑j
.text:00401049 cmp [ebp+argc], 3
.text:0040104D jnz short loc_40105E
.text:0040104F push offset aArgc3 ; "argc == 3\n"
.text:00401054 call sub_401082
.text:00401059 add esp, 4
.text:0040105C jmp short loc_401071
.text:0040105E ; ---------------------------------------------------------------------------
.text:0040105E
.text:0040105E loc_40105E: ; CODE XREF: _main+4D↑j
.text:0040105E cmp [ebp+argc], 4
.text:00401062 jnz short loc_401071
.text:00401064 push offset aArgc4 ; "argc == 4\n"
.text:00401069 call sub_401082
.text:0040106E add esp, 4
.text:00401071
.text:00401071 loc_401071: ; CODE XREF: _main+16↑j
.text:00401071 ; _main+2B↑j ...
.text:00401071 push offset aHelloworld ; "HelloWorld\n"
.text:00401076 call sub_401082
.text:0040107B add esp, 4
.text:0040107E xor eax, eax
.text:00401080 pop ebp
.text:00401081 retn
.text:00401081 _main endp

1)多层if

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// Test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

int main(int argc, char* argv[])
{
if (argc == 1)
{
printf("argc == 1\n");
}
else
{
printf("else\n");
if (argc == 2)
{
printf("argc == 2\n");
}
else
{
if (argc == 3)
{
printf("argc == 3\n");
}
}

}

printf("HelloWorld\n");
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 argc = dword ptr 4
.text:00401000 argv = dword ptr 8
.text:00401000 envp = dword ptr 0Ch
.text:00401000
.text:00401000 push esi
.text:00401001 mov esi, [esp+4+argc]
.text:00401005 cmp esi, 1
.text:00401008 jnz short loc_401011
.text:0040100A push offset aArgc1 ; "argc == 1\n"
.text:0040100F jmp short loc_401034
.text:00401011 ; ---------------------------------------------------------------------------
.text:00401011
.text:00401011 loc_401011: ; CODE XREF: _main+8↑j
.text:00401011 push offset aElse ; "else\n"
.text:00401016 call sub_401050
.text:0040101B add esp, 4
.text:0040101E cmp esi, 2
.text:00401021 jnz short loc_40102A
.text:00401023 push offset aArgc2 ; "argc == 2\n"
.text:00401028 jmp short loc_401034
.text:0040102A ; ---------------------------------------------------------------------------
.text:0040102A
.text:0040102A loc_40102A: ; CODE XREF: _main+21↑j
.text:0040102A cmp esi, 3
.text:0040102D jnz short loc_40103C
.text:0040102F push offset aArgc3 ; "argc == 3\n"
.text:00401034
.text:00401034 loc_401034: ; CODE XREF: _main+F↑j
.text:00401034 ; _main+28↑j
.text:00401034 call sub_401050
.text:00401039 add esp, 4
.text:0040103C
.text:0040103C loc_40103C: ; CODE XREF: _main+2D↑j
.text:0040103C push offset aHelloworld ; "HelloWorld\n"
.text:00401041 call sub_401050
.text:00401046 add esp, 4
.text:00401049 xor eax, eax
.text:0040104B pop esi
.text:0040104C retn
.text:0040104C _main endp
  • 单分支

    • jxx目标上一行没有jmp
    • 反条件还原
    • jxx作为if语句块上界,jxx目标作为下界
    • jxx IF_END
    • IF_BEGIN:
    • …..代码
    • IF_END
  • 双分支

    • jxx目标上一行有jmp
    • 反条件还原
    • jxx作为if语句块上界,jxx目标作为下界
    • jxx IF_END
    • IF_BEGIN
    • …..
    • jmp ELSE_END
    • IF_END
    • ELSE_END
  • 多分支

    • jxx目标上一行有jmp,地址增量jmp,高凉后发现不止一个分支是同样目标,且地址没有骑跨
    • jxx IF_END1
    • IF_BEGIN1
    • ……
    • JMP ELSE_END
    • IF_END1
    • ELSE_BEGIN
    • jxx IF_END2
    • …..
    • JMP ELSE_END
    • IF_END2