類型混淆漏洞一般是將數據類型A當做數據類型B來解析引用,這就可能導致非法訪問數據從而執行任意代碼。
本文通過IE類型混淆漏洞實例和Word類型混淆漏洞實例進行分析,來學習理解類型混淆漏洞原理。
實例一:IE/Edge類型混淆漏洞(CVE-2017-0037)
漏洞原因:函數處理時,沒有對對象類型進行嚴格檢查,導致類型混淆。
分析環境: Win7、IE11
分析工具: Windbg、od、IDA Pro
在PoC中定義了一個table,標簽中定義了表id為th1,在boom()中引用,然后是setInterval設定事件。
漏洞成因分析
運行PoC,用OD或Windbg附加并加載運行,出現崩潰,如下圖
從崩潰點可以看到eax作為指針,引用了一個無效地址,導致崩潰,而上一條指令是一個call,如下
這個無效的返回值來自這個call,此時我們進行逆推,在這個call處下斷點,
ecx作為參數,存放的對象是一個Layout::FlowItem::`vftable虛表
這個值會在Readable函數中引用,如下圖
這里讀取虛表中+4的值,為0時this指針賦值v1,隨后v1+16后返回,因此,Layout::FlowItem::`vftable所屬指針的這個情況是正常的,函數會正常返回進入后續處理邏輯。
讓程序繼續運行,會再次調用該函數,此時ecx并不是一個虛表對象,而是一個int Array對象,這里我們可以通過條件斷點來跟蹤兩個對象的創建過程,重點關注兩個對象創建的函數,一個是FlowItem::`vftable對應的虛表對象,另一個是引發崩潰的int Array對象。這兩個函數的返回值,也就是eax寄存器中存放的指向這兩個創建對象的指針。
通過條件斷點,輸出每一次int Array object創建的對象信息
通過跟蹤可以看到第一次調用Readable函數時ecx是一個正常的FlowItem對象,而第二次調用的時候ecx是一個int Array Object。Layout::Patchable >::Readable函數是處理虛表對象的函數,由于boom()函數中引用th1.align導致Readable函數得到第二次引用,由于沒有進行對象屬性檢查,導致第二次調用時將table對象傳入,最終發生類型混淆崩潰。
分析利用關鍵點
首先我們分析崩潰點上下文,通過流程走向看看是否有可利用的點,
在判斷eax返回值不等于0后,會繼續往下調用Readable函數,且eax會連續引用,后面看到一個call edi,這是一個虛函數,如果我們能控制edi就有可能在這里達到代碼執行的效果。其中有一個控制流保護機制CFG(call __guard_check_icall_fptr),Win7系統未開啟所以這里不用考慮pass。
edi是由ecx(Array Object)傳遞過來的,通過修改th1對象中的width值為2000000,允許我們將EAX的值移動到堆噴射中的受控內存位置。
PoC中設置eip為0x41414141
這里eax=0bebc2d8,我們的受控位置為0Xbebc200=(2000000*100),在可控范圍。
EIP被設置為0x41414141,由于加載的所有模塊均啟用了ASLR,目前仍沒有繞過的方法。
實例二:Word類型混淆漏洞(CVE-2015-1641)
漏洞原因:Word在解析docx文檔的displacedByCustomXML屬性時未對customXML對象進行驗證,導致可以傳入其他標簽對象進行處理,造成類型混淆。
分析環境: Win7、Word2007
分析工具: Windbg、od、oletools、notepad++、WinHex
樣本:https://github.com/houjingyi233/office-exploit-case-study/blob/master/CVE-2015-1641/8bb066160763ba4a0b65ae86d3cfedff8102e2eacbf4e83812ea76ea5ab61a31.bin.gz
首先解壓樣本并改后綴名為doc,用oletools的rtfobj分析結果為4個文件,分離保存。
在樣本中提取第三個OLE,構造成rtf文件(上圖為文件前半部分截圖),打開該文件后出錯,如下圖,可以看到故障模塊為wwlib.dll,異常偏移為0x9d30。
運行word,用windbg附加word進程,再打開rtf文件,異常出現在wwlib模塊中的0x5c4a9d30,代碼為mov esi,dword ptr [ecx],崩潰原因是[ecx]引用到無效地址。
這里ecx=0x7c38bd50,指向何處? 接下來分析保存出來的ole文件,解壓后在資源文件“document.xml”中發現ecx的值正是smarttTag標簽的element的屬性值。
smartTag是一個智能標簽,可針對人名、日期、時間、地址、電話號碼等進行智能識別并允許用戶執行特定操作的標簽,displacedByCumtomXml屬性表示此處要替換為另一個customxml標簽,樣本作者在smartTag的element中構造了0x7c38bd50,Word在解析docx文檔處理displacedByCustomXML屬性時未對customXML對象進行驗證,所以能傳入smartTag標簽對象。
由于是單獨加載觸發漏洞OLE引用到無效地址,因為這個地址位于” MSVCR71.DLL”模塊中,而這個DLL正是通過第一個OLE對象“otkloadr.wRAssembly.1”引入的。將第一個OLE對象:{\object\objocx{\*\objdata180115000002000000160000006f746b6c6f6164722e5752417373656d626c792e3100000000000000000001000000400105000000000000}},添加到觸發漏洞的OLE前面,構建成RTF運行,再通過Windbg下條件斷點,這里先記錄下crash發生的時候“0x7c38bd50 “所在的模塊地址,通過它來下條件斷點:
0x7C38BD50是smartTag標簽的element值,4294960790(0xFFFFE696)是moveFromRangeStart的值,隨后對這兩個值進行計算得到一個地址0x7C38BD74。計算過程如下:
第二個smartTag,smartTag標簽的element值此時為0x7C38BD68,moveFromRangeStart的值為0x7C376FC3(十進制為2084007875),計算出的地址為0x7C38A428,最后通過memcpy函數將0x7C376FC3覆蓋到地址0x7C38A428中,在調試器可以看到,0x7C38A428為虛表指針:
接著往下執行會先經過一大片地址為“7C342404”的“ret”,然后進入ROP鏈,再往后就是shellcode。
將id為1的OLE解壓后,在解壓目錄的“activeX1.bin“中看到用來堆噴的數據塊:nop指令上面的是ROP鏈,heapspary前會使用大量地址為0x7c342404 的ret-sled,
以上兩實例分析文章在網上較多,這里只做一個淺析,不做深入分析。