CVE-2012-4792 IE 0day (CButton use after free)漏洞分析

前言 

首先通过网络搜索,发现国内外在谈论这个漏洞时都说是 mshtml!CDwnBindInfo对象的use-after-free。比如以下链接nsfocus。其实这些都是错误的,那为什么会被说成是mshtml!CDwnBindInfo对象的use-after-free呢,我猜测可能是由于原始的样本中有个图片文件,在图片下载时会初始化mshtml!CDwnBindInfo对象,所以误导了分析者,其实漏洞成因与mshtml!CDwnBindInfo对象没有任何关系。 

PoC 
将其保存为htm文件即可触发crash。

<!doctype html>  <html>  <head>  <script>     function exploit()  {   var e0 = null;   var e1 = null;   var e2 = null;      try {    e0 = document.getElementById("a");    e1 = document.createElement("div");    e2 = document.createElement("q");    e1.applyElement(e2);    e1.appendChild(document.createElement('button'));    e1.applyElement(e0);    e2.innerHTML = "";    e2.appendChild(document.createElement('body'));   } catch(e) { }   CollectGarbage();     }     </script>     </head>  <body onload="exploit()">  <form id="a">  </form>  </body>  </html> 

漏洞分析 
首先从宏观来观察该PoC的执行过程。 
首先PoC会创建多个子元素,并按照以下结构布局。

CVE-2012-4792 IE 0day (CButton use after free)漏洞分析

接着会将Phrase下的所有元素清空,如下图

CVE-2012-4792 IE 0day (CButton use after free)漏洞分析

最终元素布局如下图

CVE-2012-4792 IE 0day (CButton use after free)漏洞分析

以上是我们从表面看到的动作流程,可以猜测可能是 Phrase 对象的子元素销毁时发生某些 问题。至于具体的漏洞成因,还是得深入分析。下面从内存和反汇编级别来简单分析,先观察该页面内元素的创建过程。

ie 首先会依次创建以下元素,这里可以不用关注.

Addrses:0x03653160 mshtml!CCommentElement Addrses:0x0364a060 mshtml!CHtmlElement Addrses:0x03721f30 mshtml!CHeadElement Addrses:0x0364d200 mshtml!CScriptElement Addrses:0x0365ee48 mshtml!CBodyElement Addrses:0x001ae618 mshtml!CFormElement

接着根据 PoC 中 exploit()函数的代码,ie 会依次创建以下这些元素

Address:0x037222c0 mshtml!CDivElement Address:0x03722320 mshtml!CPhraseElement Address:0x0024f0a0 mshtml!CButton Address:0x0372d1b0 mshtml!CBodyElement

接着向每个结构的 firstChild 或者 parentNode 等字段内保存对应的对象,重新布局,最终结 构如图一。(具体的 Element 的对象结构,与版本相关,以及相应的偏移在之前的分析文档 中已经挖掘的差不多了,这里就不再重复,直接带过。)

接着执行 PoC 中的代码 e2.innerHTML = “”;
这导致在 mshtml!COmWindowProxy::FireEvent 事件中释放 CButton 对象

CVE-2012-4792 IE 0day (CButton use after free)漏洞分析

析构完后自然是将Buffer直接Free掉了

CVE-2012-4792 IE 0day (CButton use after free)漏洞分析

要注意的是,虽然此时CButton的内存空间已经释放,但保存在CDoc中的信息别没有删除,仍然存在,只是指向了一块已经释放的内存。

接下来在mshtml!CElement::FindDefaultElem()函数中会寻找默认的元素,根据元素的创建顺序以及焦点等相关因素,默认元素应该为我们上面最后创建的Button,保存于CDoc+0x1A8的位置。 
FindDefaultElem()函数最终从CDoc中取出DefaultElement,本例中正常时应返回CButton对象地址,但此时指向的内存正是前面释放的。 

CVE-2012-4792 IE 0day (CButton use after free)漏洞分析

此时内存内容已经不可信,继续执行虚函数调用,可能执行任意代码。 

CVE-2012-4792 IE 0day (CButton use after free)漏洞分析

漏洞利用 
和普通的Use-After-Free漏洞利用相同,可以尝试通过泄漏基址来绕过ASLR。