DOM(文檔對象模型)提供了操作HTML/XML文檔的接口。IE瀏覽器中跟DOM實現(xiàn)相關(guān)的代碼主要在mshtml dll中。mshtml中的CMarkup類負責(zé)構(gòu)造整個htmI樹結(jié)構(gòu),其成員函數(shù)CreateElement會調(diào)用全局的CreateElement函數(shù)束構(gòu)造不同標(biāo)簽對應(yīng)的元素。比如<object>標(biāo)簽.會構(gòu)造對應(yīng)的CObjectElement元素:<area>標(biāo)簽.會構(gòu)造對應(yīng)的CAreaElement元素。這些Element類都是CElement類的子類。接下來的逆向工作主要基于IE8 8.00.7601.17537版本的mshtml dll。
對于每個不同的標(biāo)簽,IE測覽器內(nèi)部有不同的CTagDesc結(jié)構(gòu)。這些CTagDesc結(jié)構(gòu)中的其中一項就是對應(yīng)元素的CreateElement函數(shù)指針。因此,全局的CreateElement函數(shù),會根據(jù)不同的標(biāo)簽柬獲得對應(yīng)的CTagDesc結(jié)構(gòu),然后再從里面取得對應(yīng)該標(biāo)簽的CreateElement函數(shù)指針然后call過去進行調(diào)用。具體可參看全局CreateElement函數(shù)的反匯編代碼,如圖2.2.6所示。
這里有一些小細節(jié),有的時候直接用IDA反匯編如mshtml dll這樣的dll文件的時候沒有找到對應(yīng)的符號表,可以先使用Symbol Type Viewer這樣的小工具將符號表下載下來放到跟dll同目錄然后再使用IDA對相關(guān)的dll文件進行反匯編。
接下來,以CObjectElement為例,介紹其創(chuàng)建過程,其他Elenlent的創(chuàng)建過程類似。CObjectElement的初始化是在成員函數(shù)CrcateElement函數(shù)中完成的。創(chuàng)建過程如下:先分配內(nèi)存,然后調(diào)用構(gòu)造函數(shù),最后將返回的對象指針保存在傳入的CElemen**參數(shù)中。反匯編代碼如圖。
圖2.2.9
HeapAlloc進行堆內(nèi)存分配,高版本的一些mshtml dll中可能是由ProcessHeapAllocClear這個函數(shù)進行內(nèi)存的分配。傳給HeapAlloc的字節(jié)數(shù)是0E0h可知,當(dāng)前IE瀏覽器版本中的CObjectElement大小為E0h。
接下來調(diào)用CObjectEtemem的構(gòu)造函數(shù)完成CObjectElement對象的初始化,構(gòu)造函數(shù)會自動調(diào)用父類的構(gòu)造函數(shù)。調(diào)用完構(gòu)造函數(shù)后.會將新建的CObjcctElemenl對象指針保存在傳入的參數(shù)CElemen**中。這是通過代碼
movecx,[ebp+arg_8]mov[ecx],eax
完成的。
IE瀏覽器采用引用計數(shù)束跟蹤DOM對象的生命周期。引用計數(shù)(Reference Counting)算法對每個對象計算指向它的指針的數(shù)量。當(dāng)有一個指針指向該對象時計數(shù)值加1 ,當(dāng)刪除一個指向酸對象的指針時,計數(shù)值減l。如果計數(shù)值減為0,說明不存在指向該對象的指針.此時就可以安全的銷毀潑對象。垃圾回收過程就是回收引用計數(shù)為0的對象。引用計數(shù)算法的優(yōu)點是算法實現(xiàn)簡單,并且進行垃圾回收時無需掛起應(yīng)用程序,回收速度快。
缺點是出于每一次對對象的指針操作都要對對象的引用計數(shù)進行更新,因此會減緩系統(tǒng)的整體運行速度。另外,使用引用計數(shù)算法的每個對象都需要額外的空問存儲計數(shù)值。除此之外,引用計數(shù)算法的最大缺點是無法處理循環(huán)引用。循環(huán)引用指的是兩個對象互相指向?qū)Ψ健4藭r兩個對象的引用計數(shù)都依賴于對方.因此始終無法減至0。
IE瀏覽器實現(xiàn)引用計數(shù)的核心就是IUnknown接口。該接口提供了兩個非常重要的特性:生存期控制與接口查詢。對象內(nèi)部通過引用計數(shù)來實現(xiàn)對象的生存期控制。調(diào)用程序不甩在意對象的內(nèi)部實現(xiàn)細節(jié).通過接口查詢即可獲得指向?qū)ο蟮闹羔槨E瀏覽器中的很多類都繼承于IUnknown。IUnknown有三個方法。
圖2.2.10
以上節(jié)介紹的<obiect>標(biāo)簽的內(nèi)部實現(xiàn)CObjectElement類為例.該類最終繼承于CElement。而CElement繼承于CBase,CBase則實現(xiàn)了IUnknown接口。用戶要查詢<object>標(biāo)簽對應(yīng)的CObjectElement對象,需要調(diào)用CObjectElement::QueryInterface函數(shù)。而CObjectElement的QueryIntefface函數(shù)最終會調(diào)用到CElement的QueryInterface接口.CElement的QueryInterface接口最終會調(diào)用PrivateQueryInterface 來獲得對象指針。
PrivateQueryInterface會先調(diào)用CElement::CreateTearOffThunk函數(shù)退回對象包裝后的指針.然后在接下來調(diào)用CCaret::AddRef函數(shù)(call eCX)增加引用計數(shù)。
而CElement::CreateTearOffThunk函數(shù)僅僅是簡單的調(diào)用全局的CreateTearOflThunk函數(shù)。全局的CreateTearOflThunk函數(shù)反匯編部分代碼如圖
圖 2.2.11
再來看看釋放引用時所做的工作。對于CElement,用戶不再需要其引用時,調(diào)用CElement::Release即可。CElement::Release是對CElement::PrivateRelease的封裝,而CElemem::PrivateRelease主要的工作是調(diào)用父類CBase的PrivateRelease函數(shù)。CBase::PrivateRelease負責(zé)減少引用計數(shù)。
實際上IE當(dāng)中這種對對象的創(chuàng)建和銷毀的場景比比皆是,這也是在緩沖區(qū)漏洞在IE上面幾近絕跡后UAF中興的基礎(chǔ)。
2.3 時代關(guān)鍵字
Deferred/Delayed Free Control Flow Guard Isolated Heap
上文已經(jīng)簡單的給出一個例子幫助理解UAF的成因和觸發(fā)了。但是由于IE中對象眾多調(diào)用關(guān)系復(fù)雜,微軟作為防守的一方并不能像挖掘緩沖區(qū)溢出漏洞一樣容易的窮舉并修復(fù)所有潛在的漏洞。但是微軟分別以發(fā)布補丁的方式在14年的6月和7月分別引入了隔離堆和延遲釋放的漏洞利用緩解措施。并且在Win8.1Update3和Win10中引入了新的機制Control Flow Guard。我們簡單記錄說明一下這些機制。
UAF的觸發(fā)和利用依賴于被釋放的對象的重用。利用的過程必須依賴非法IE對象被確定的分配和釋放。而隔離堆和延遲釋放分別在對象的分配和釋放的時候加入了保護。
在IE中CVE-2014-0282修補前CTextArea::CreateElement分配內(nèi)存的時候有這樣的代碼
圖2.3.1
漏洞修補之后代碼是這樣的。
圖2.3.2
可以比較明顯的看到存在UAF隱患的對象的內(nèi)存分配已經(jīng)單獨使用了隔離堆進行內(nèi)存分配。
而延遲釋放是這樣的。正常的對象釋放使用HeapFree就立即釋放了,而加入延遲釋放之后需要被釋放的對象會被統(tǒng)一記錄然后根據(jù)規(guī)則再進行延遲釋放。
再說一下CFG(Control Flow Guard)這個機制。CFG的機制是基于控制流完整性Control-Flow Integrity的設(shè)想。這里通過對二進制可執(zhí)行文件的改寫,對jmp的目的地址前插入一個在改寫時約定好的校驗ID,在jmp的時候看目的地址前的數(shù)據(jù)是不是我們約定好的校驗ID,如果不是則進入錯誤處理流程。
圖2.3.3
在Call的過程中會引入一個CFG的校驗函數(shù)。CFG需要編譯器和操作系統(tǒng)的雙重配合。當(dāng)這個校驗函數(shù)在不支持的操作系統(tǒng)上運行的時候直接就return了。當(dāng)在被支持的操作系統(tǒng)(win10和win8.1 update3)的時候就會跳轉(zhuǎn)到一個ntdll里面的一個檢測函數(shù)。檢測的機制我們不在詳細展開。
由于在溢出漏洞和UAF的大部分利用當(dāng)中都依賴于覆蓋某個地址然后劫持程序的EIP跳轉(zhuǎn)到我們的惡意代碼的地址進行執(zhí)行。CFG在控制非法地址跳轉(zhuǎn)方面直接斬斷了大部分漏洞利用的可能。
3.1 后UAF時代
就目前來看,14年之后由于新的緩解措施的加入使得攻防雙方的優(yōu)勢幾乎一邊的倒向了微軟為首的防守者的陣營。
瀏覽器的漏洞利用已經(jīng)沒有固定的套路。如瀏覽器內(nèi)部的腳本引擎的設(shè)計錯誤導(dǎo)致從腳本層面突破IE而進行漏洞的相關(guān)利用(CVE-2014-6332),對瀏覽器中flash插件的漏洞發(fā)掘利用得到ring3權(quán)限,然后配合對較老字體解析引擎代碼發(fā)掘出來的提權(quán)漏洞再進行提權(quán)拿到系統(tǒng)權(quán)限(Hacking Team相關(guān)利用)。漏洞利用方式不一而足,有機會在修訂簡史的時候一并補充。
0×03 IE漏洞防護措施關(guān)鍵時點
2015年7月 CFG編譯器支持 VS2015 RTM版本引入/guard開關(guān)對Control Flow Guard特性提供編譯器支持。
2014年11月 CFG系統(tǒng)級別支持 Windows8.1 update3 對Control Flow Guard提供系統(tǒng)層面的支持,之后的windows系統(tǒng)均在操作系統(tǒng)層面支持該特性。
2014年7月 MS14-037補丁發(fā)布引入Delayed Free特性。
2014年6月 MS14-035補丁發(fā)布引入Isolated Heap特性。
2008年1月 SEHOP系統(tǒng)級別支持 發(fā)布vista Service Pack 1補丁包,引入對SEHOP特性的操作系統(tǒng)支持。自vista sp1后的windows系統(tǒng)均在操作系統(tǒng)層面支持該特性。
2007年1月 ASLR系統(tǒng)級別支持 windows vista系統(tǒng)引入對ASLR特性操作系統(tǒng)級別的支持。自vista后的windows系統(tǒng)均在操作系統(tǒng)層面支持該特性。
2006年年初 safeseh/stack cookie/aslr/dep編譯器支持 VS2005引入/safeseh編譯開關(guān)緩和溢出漏洞對seh的攻擊,引入/GS編譯開關(guān)插入Stack Cookie緩和對返回地址的攻擊,加入/dynmicbase編譯開關(guān)引入對ASLR特性的編譯器支持,加入/NXCOMPAT編譯開關(guān)引入對DE特性的編譯器支持。自VS2005之后的編譯器均支持上述編譯開關(guān)。
2004年8月 DEP系統(tǒng)級別支持。微軟推出XP Service Pack 2補丁包引入對DEP特性的操作系統(tǒng)支持,自XP SP2后的windows系統(tǒng)均在操作系統(tǒng)層面支持該特性。
版權(quán)所有:鄭州三中網(wǎng)安科技有限公司 豫ICP備2020036495號-1 ?? | 豫公網(wǎng)安備 41019702002241號 | 站點地圖 | 人才招聘 | 聯(lián)系我們 |