ღ Miranda

CVE-2013-1347 IE UAF分析

前言

CVE-2013-1347IE的一个uaf漏洞,安全研究人员发现这个IE80day被应用于攻击美国政府的核武器科学家和研究人员。

环境

系统: win7 SP1
浏览器: IE8

poc

poc.html:

调试分析

打开pocIE崩溃如下:

通过栈回溯可以定位到上一层调用:

通过模块基地址可以得到指令偏移为0x1bb68d,这里看起来又是一个虚函数调用,开启堆页再次调试:

这里ecx已经在6b61c83a中被释放了,这时继续执行下去就会发生刚开始的那个异常:

f0=document.createElement('span');一句创建了一个span元素,在windbg中查找有关的函数:

先在IDA中查看第一个函数:

其中调用了Document::CreateElementHelper:

调用了CMarkup::CreateElement创建元素,跟进去发现最终会调用CreateElement函数:

跟进CreateElement:

windbg里能搜索到两个CreateElement:

经过汇编比对,调用的是第二个,先在这个函数上下断点调试:

可以知道这里第一次调用的是CCommentElement::CreateElement,再次调试,在call eax的地方下断点:

可以看到确实调用了CSpanElement::CreateElement来创建span对象:

CElement::CElement:

由于每个构造对象的函数最终都会调用CElement::CElement,所以可以在74D99FF1下断点,也就是偏移0x1e处,查看edi指向的内存就是创建的对象。也同时在CreateElement偏移0x37下断点查看使用的是哪个对象的构造函数。

可以看到所有的对象创建。

创建了span后会用document.body.appendChild();插入,找找相关函数:

在第一次调用完CSpanElement::CreateElement后可以在这几个函数上都下断点,继续运行发现断在了第一个函数内:

appendChild中调用了CElement::insertBeforeCElement::insertBefore里面又调用了CElement::InsertBeforeHelper函数,单步调试这个函数:

这里获取到了CBodyElement作为被插入对象。

到这里跟进去,获取了CDoc对象:

接下去调用了CDoc::InsertElement用来插入元素:

跟进去,最后调用了CMarkup::InsertElementInternal:

CMarkup::InsertElementInternal的伪代码:

对应的汇编如下:

call CTreeNode::CTreeNode偏移为0x1de,调用后会得到所创建元素的CTreeNode对象信息。在后一句下断点,记录一下创建的元素信息,再结合之前的断点,断点信息如下:

得到的记录整理得到:

在三个span对象创建后创建了f2的子对象document.createElement('datalist'),是个CGenericElement对象,根据崩溃的回溯可以知道正是这个对象引发了崩溃。

接着看poc,搜索有关f0.offsetParent=null;的函数:

CElement::get_offsetParent中调用了CElement::GetOffsetParentHelper,去掉这句话就不会发生崩溃,对比一下创建CTreeNode后有什么变化,这次保留之前的断点,在CElement::GetOffsetParentHelperCMarkup::InsertElementInternal+0x23f下断点:

重点关注CTreeNode+8CTreeNode+c的数据,对这两处设置写入断点:

CTreeNode+0xc的值设置内存访问断点:

判断是否要跳入GetCharFormatHelper执行。

接下来看看当调用CollectGarbage()datalisttablehr三个对象的状态,这是刚分配时的:

执行完CollectGarbage()后:

而且在CElement释放后,CTreeNode仍然指向已经被释放的内存:

继续运行,崩溃后看栈回溯:

有好几个函数都把datalistCTreeNode作为参数传递,最前面的是ISpanQualifier::GetFancyFormat函数,在CollectGarbage后对ISpanQualifier::GetFancyFormat下断点,会断下好几次次,最后一次时,第二个参数就是datalistCTreeNode值,eax等于这个参数值:

根据栈回溯可以得到这个函数的上两层调用:

mshtml!SRunPointer::SpanQualifier:

那么eax的值可能来自edi,但在之前还会调用RunPointer::SpanQualifier,里面修改了eax[[eax+4]+c],可以对这里下条件断点,这时f0CTreeNode地址为0x002f4010:

会发生几次异常,然后就到了条件满足时的断点:

eax+4处是一个数组,偏移0x4是索引,0xc处是CTreeNode的地址,这个数组的来源如下:

CollectGarbage之行结束后f2的这个数组状态可以看到仍然有datalistCTreeNode:

执行完js代码后会重新渲染页面,重新计算节点,从而引用到已经释放的datalist结构,最后触发漏洞。

漏洞利用

看到之前CGenericElement被释放的内存大小为0x380x38/4=14,这里使用t:ANIMATECOLOR来进行内存填充,这个标签值是用;分割的字符串,对象的每一个元素都是一个指针,所以要除以四,能够控制eip的脚本如下:

运行:

这时CGenericElement的地址如下:

被释放后被t:ANIMATECOLOR填充,共有14个地址,分别对应由;分隔的字符串:

第一个地址就成了虚表地址,由漏洞触发引用的是偏移0x70的虚函数地址,正好是0x41414141,这样就可以构造rop来实现任意代码执行。

发表评论

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