IE漏洞的除錯心得

Ox9A82發表於2016-08-17

在除錯漏洞的過程中,個人感覺最棘手的就是ie瀏覽器的漏洞和flash player的漏洞了。這裡打算記錄一下學習過程中的心得(主要是基於uaf類),以方便新人學習。

首先,ie漏洞與眾不同的是,程式的執行流程是由攻擊者控制的。poc中的js指令碼反應到mshtml中的c++程式碼決定了程式的執行流程,所以對於ie漏洞來說仔細研究poc非常的關鍵。此外就是除錯ie漏洞需要對ie本身有很強的瞭解,這也是我寫這篇博文的動機,如果完全不清楚ie背後的機制,那麼ie漏洞根本沒法去調。

除錯IE漏洞的關鍵點:執行流程

CMarkup代表整個HTML樹結構

CMarkup::CreateElement——>

mshtml!CreateElement——>

CXXXElement::CreateElement

 tips:1.解構函式在windbg裡直接用符號是斷不下來的,需要找到函式地址,最好是在call free上下斷。

 

元素物件統一繼承自CElement。

0x00偏移:虛表(dword),對此處求ln會得到符號

0x08偏移:是引用計數?

0x14偏移:對應的CTreeNode物件的指標

0x24偏移:Tag (byte),0x58script 0x10body 0x2fhead

建立函式:CXXXElement::CreateElement(通用斷點:監視型別mshtml!CreateElement [call eax]、監視記憶體CElement::CElement [堆分配傳來的eax])

釋放引用函式:CXXXElement::Release(通用斷點:CBase::PrivateRelease 棧上arg_1 eax是虛表)

釋放函式:CBase::SubRelease(CElement::~CElement)(通用斷點CBase::SubRelease的jmp路徑 ecx為要釋放的物件指標)

 

DOM物件均為CTreeNode類的例項。

0x00偏移:對應的元素物件的指標(dword)

0x04偏移:指向父節點的CTreeNode(dword)

0x16偏移:指向此node的起始CTreePos

0x20偏移:指向此node的結束CTreePos

0x40偏移:引用計數?

建立函式:CTreeNode::CTreeNode(建構函式)(eax:緩衝區地址 edi:所屬物件型別)

釋放引用函式:CTreeNode::Release的if分支(通用斷點:CTreeNode::Release的if分支 [待釋放的edx],在比較處eax引用計數)

釋放函式:CTreeNode::Release的另一if分支(通用斷點:CTreeNode::Release的另一if分支 [待釋放的edx],在比較處eax引用計數)

 

CTreePos物件是一一對應於CTreeNode物件的,主要是用於構成dom樹的結構

0x00偏移:key

0x10偏移:上一個CTreePos物件(dword)

0x14偏移:下一個CTreePos物件(dword)

0x18偏移:引用計數,為0就會被釋放(dword)

0x20偏移:對應的CTreeNode(dword)

釋放函式:CMarkup::FreeTreePos

 

通用斷點原則 

 

IE中兩類重要的物件:元素物件和DOM物件

IE中每一個元素標籤都對應一個c++物件,這些類的總基類是CElement

每個元素物件都在DOM樹中,但是聯入資料結構的是CTreePos物件

 

IE瀏覽器使用引用計數來跟蹤物件的生命期,引用計數數=指向物件的指標,就是說每當增加一個指標指向它引用計數就加1。

解除引用元素物件的函式都為如下,這個方法的呼叫執行關係如下(基於IUnknown)

    • CXXXElement::Release ——>
    • CElement::Release——>
    • CElement::PrivateRelease——>
    • CBase::PrivateRelease

如果可以監視所有的IE元素建立、DOM元素建立、IE元素釋放、DOM元素釋放,那麼漏洞出在哪裡將一目瞭然

 

對於一個元素標籤,比如Object標籤。那麼對應的就是CObjectElement::CreateElement,這個函式的呼叫關係如下

元素物件建立的完整路徑

  • CDocument::createElement——>
  • CDocument::CreateElementHelper——>
  • CMarkup::CreateElement——>
  • mshtml!CreateElement——>
  • CXXXElement::CreateElement——>
  • HeapAlloc+CElement::CElement

CTreeNode::SetElement(CXXXElement*);將DOM物件與元素物件關聯起來

 CTreeNode表示一個節點,CTreePos表示一個節點的標記。dom樹就是由CTreePos表示的二叉樹。

 

如果一個物件的指標計數為0,那麼就會被垃圾清理釋放掉

 

 

CTreeNode類的成員,來自IE5洩露原始碼

    // Class Data
    CElement*   _pElement;                          // The element for this node
    CTreeNode*  _pNodeParent;                       // The parent in the CTreeNode tree

    // DWORD 1
    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;                               // 16-31:   Fancy Format

CTreeNode::CTreeNode(CTreeNode *pParent,CElement *pElement)這個建構函式的第一個引數是父CTreeNode節點,第二個引數是所屬的Element物件。其中第二個引數往往為0。

如何跟蹤CTreeNode::CTreeNode物件的建立?

斷下CTreeNode::CTreeNode函式後,eax就是分配的記憶體地址。

第一個引數為父節點CTreeNode物件的地址,第二個引數恆為0

可以在call ~的下一條,mov esi,eax下斷,這時CTreeNode已完成初始化,讀eax就可知道是屬於哪個元素

 DOM樹是由CTreePos組成的一個splay tree。

如圖所示就是一個CxxxElement::CreateElement,上面已經說過了這是由mshtml!CreateElement呼叫的。我們可以看到呼叫了HeapAlloc函式後,eax的值沒有改變直接傳遞到了CElement的建構函式——CElement::CElement中。實現了分配空間+初始化記憶體的操作。

對mshtml!CElement::CElement+0x48下斷可以通用的監測物件建立的內容。

這張圖是mshtml!CreateElement函式的關鍵部分,注意符號給出的CTagDesc *型別的常量,這是一個指標陣列經過movzx eax,byte ptr [edi+1];shl eax,4;計算偏移得出CxxxElement::CreateElement的地址,然後呼叫過去。指標陣列如下:

 

CTreeNode::Release可以獲取到所有的CTreeNode的釋放過程,edx是上面直接傳遞過來的CTreeNode物件的地址。對這個值監視即可獲得所有CTreeNode物件的釋放

 

 

 

 

<html>
  <head>
    <title>DOM 教程</title>
  </head>
  <body>
    <h1>DOM 第一課</h1>
    <p>Hello world!</p>
  </body>
</html>
mshtml!CHtmlElement::CreateElement
mshtml!CHeadElement::CreateElement
mshtml!CBodyElement::CreateElement
mshtml!CHeaderElement::CreateElement
mshtml!CParaElement::CreateElement  

下斷元素建立

1:020> bl
 0 e 6a23480f     0001 (0001)  1:**** mshtml!CElement::CElement ".echo 物件地址;r eax;gc"
 4 e 6a234be7     0001 (0001)  1:**** mshtml!CreateElement+0x41 "ln eax;gc"
1:020> g
(6a23d088)   mshtml!CHtmlElement::CreateElement   |  (6a23d0d8)   mshtml!CHtmlElement::`vftable'
Exact matches:
    mshtml!CHtmlElement::CreateElement = <no type information>
物件地址
eax=06131fd8
(6a23d359)   mshtml!CHeadElement::CreateElement   |  (6a23d3a8)   mshtml!CHeadElement::`vftable'
Exact matches:
    mshtml!CHeadElement::CreateElement = <no type information>
物件地址
eax=06154fd8
物件地址
eax=05f6afd0
(6a2465fa)   mshtml!CBodyElement::CreateElement   |  (6a246648)   mshtml!CBodyElement::CBodyElement
Exact matches:
    mshtml!CBodyElement::CreateElement = <no type information>
物件地址
eax=0302dfd0
(6a254c88)   mshtml!CHeaderElement::CreateElement   |  (6a254ce0)   mshtml!CHeaderElement::`vftable'
Exact matches:
    mshtml!CHeaderElement::CreateElement = <no type information>
物件地址
eax=0628efd0
(6a257e72)   mshtml!CParaElement::CreateElement   |  (6a257ec0)   mshtml!CParaElement::`vftable'
Exact matches:
    mshtml!CParaElement::CreateElement = <no type information>
物件地址
eax=05d83fd8

 

 

IE漏洞除錯的目的:

crash漏洞產生原因

找到發生UAF的物件

找出物件的分配釋放重利用的時機

對應到poc的js語句

推斷出UAF的本質成因

 

補丁對比!!!找出本質成因最好的辦法

相關文章