ღ Miranda

CVE-2012-4969 UAF漏洞分析与利用

前言

CVE-2012-4969是一个IE0day漏洞,Microsoft Internet Explorer 6至9版本中的mshtml.dll中的CMshtmlEd::Exec函数中存在UAF漏洞,可以制造特定的网页,执行任意代码。

环境

这里的环境是XP SP3,安装了IE8IE CollectionwindbgIDA等工具,IE8默认开启了DEP,当然换到win7下情况差不多。

POC

首先用poc验证一下漏洞。

trigger.htm:

poc.htm:

trigger.htm拖到IE8中浏览器崩溃,用windbg调试看到:

看到edi的值可控,下面会详细分析,先做一些调试前的准备。

开启页堆和栈回溯

为了更好的追踪内存分配过程,需要打开IE的full pageheap,在windbg工具包里有个gflag.exe,被称为全局标志编辑器,是windows调试工具集的一部分,该程序是用于对各个全局标志选项的集中式配置工具,有图形化界面,里面有很多选项,也有命令行参数,开启IE页堆的命令:

iexplore.exe是IE可执行文件的位置,根据具体情况确定,这样就为IE开启了页堆,同时也可以开启栈回溯:

虽然开启页堆和栈回溯会便于调试,但开启后内存布局可能会发生变化,之前的poc可能会和之前得到不一样的结果,在调试后可以关闭这两个标志再进行exp的测试,关闭就是把加号换成减号。

IDA配置符号表

为了在IDA里正确的查看dll的函数,需要正确的配置符号表。第一种方法是配置环境变量_NT_SYMBOL_PATH,配置为:

第二种方法,在IDA目录下有个cfg目录,里面有个文件是pdb.cfg,这是IDA符号表的配置文件,内容如下:

将如下两行取消注释:

这样加载dll文件时,会有对话框询问是否要下载符号表,点击确定后IDA就会自动从微软的服务器上下载符号表了,这样所有函数都会有正确的名称,查找函数很方便。

静态分析

看一下CMshtmlEd::Exec的定义:

查看这个函数的汇编,崩溃点在0x637d464e,最开始传入edi的是0x637d45c4处的mov指令,传入的是函数第一个参数:

IDA里可以看到传给edi的是this,也就是CMshtmlEd类的一个实例:

根据函数流程大致推测这个函数先从CMshtmlEd类中取得一个成员类,然后调用类中的某个虚函数,之后从CCommandTable中取得对象实例,然后调用CCommand::Exec函数。

看一下这个关于这个类的函数:

大致看一下,下面分析时可能会看到这些函数。

调试分析

先不打开页堆和栈回溯,在崩溃点前设断点,然后单步看看:

看到了我们的payload,这样看不出什么。

附加上IE,在CMshtmlEd::Exec函数开头下断点单步调试,重点关注这三条指令:

通过这段信息我们知道[edi+8]处是CMshtmlEd的一个成员变量CComObject<CHTMLEditorProxy>0x637d45ca处的指令取得这个类的虚函数表,并执行其中一个函数,对应:

后面可以一直单步到0x637d4644处的CCommand::Exec函数调用:

此时esi=038302e0 edi=038e7aa0,分别是CCommandTable中的对象实例和CMshtmlEd对象实例,这时0x038e7aa0内存中内容为:

执行完CCommand::Exec后这段内存变为:

变成了我们的payload,那么应该是在CCommand::Exec函数中发生了UAF,回头看poc.htm:

我猜测在document.execCommand("selectAll");这句话执行后会触发onselect事件,调用了Trigger函数,而document.write("1");这行会释放页面对象,刷新页面,写入1,然后对parent.arr[0].src的赋值覆盖了已经被释放的内存,然后导致了CCommand::Exec执行完后的UAF

根据静态分析,对象的释放函数很可能是CMshtmlEd::Release,我们在这个函数上下断点重新调试。

0x637d45c7处下断点可知这次对象的地址为0x0022b530,在CCommand::Exec中的这句话时触发了CMshtmlEd::Release,现在断在了CMshtmlEd::Release:

可以一直跟到调用HeapFree的地方,HeapFree的定义为:

看看此时的栈情况

第三个参数就是CMshtmlEd结构体的地址,然后的再次对CMshtmlEd对象中的赋值就能够触发漏洞,当CCommand::Exec执行完后就会进入下面的流程:

此时edi指向的就是已经释放的内存,通过占位我们首先控制了edi+8,然后控制[edi+8]处的内容,最终只要[eax+8]处指向shellcode地址就可以成功执行代码。

exp

这里涉及到了虚表,十分适合使用堆喷射技术,可以把edi+8处覆盖为0x0c0c0c0c,然后用%u\0c0c%u\0c0c填满堆内存,这样经过两次跳转,eip最终能够指向0x0c0c0c0c,在trigger.htm加入堆喷射的脚本然后再次调试:

成功把0x0c0c0c0c填入了eax,然后成功控制了eip:

trigger.htm,使用了heaplib.js:

poc.htm:

在关闭了DEP的IE7上能够成功弹出计算器。

未命名.png

绕过DEP

对于开启了DEP的IE需要实现精准堆喷射和ROP链的构造,根据这里的汇编:

首先用下面的脚本可以精确控制0x0c0c0c0c的内容。

trigger.htm,偏移根据系统不同需要更改:

poc.htm:

最后效果:

我的做法是,内存还是用0c0c0c0c填充,但将edi的数值改为0x0c0c0c00,在ROP链之前加入,这段现在是0c0c0c0c的内容:

这样:

由于我们的ROP在堆中,所以需要把栈转移到堆中,这里就用到下面的指令:

这时eax=0x0c0c0c10,执行完后栈顶变为eax,所以ret到的地址是0x7d5d404b:

把中间的junk跳过后retROP内,直接在后面接上ROP链即可,改变的行只有:

还有把poc.htm中改成\u0c0c\u0c00,效果如下:

我使用mona这个immunity debugger的插件生成了可能的ROP链,经过修改和补全,最终的exp如下,生成的会缺少一些部分,需要自己去寻找地址,还要经过调试使得适合之前的代码。

trigger.htm:

poc.htm:

能够成功弹出计算器。

未命名1.png

总结

这个漏洞利用起来还是较为容易的,通过构造的网页可能会造成大面积攻击,可能针对win7攻击时需要寻找关闭了ASLR的模块写rop链,对于这个漏洞msf里有现成的模块,但经过试验攻击并不成功,可能系统的某些地址发生了变化,微软在2012年9月17日发布了安全更新修复了这个漏洞。

发表评论

电子邮件地址不会被公开。