產生原因:
UAF漏洞的成因是一塊堆記憶體被釋放了之後又被使用。又被使用指的是:指標存在(懸垂指標被引用)。這個引用的結果是不可預測的,因為不知道會發生什麼。由於大多數的堆記憶體其實都是C++物件,所以利用的核心思路就是分配堆去佔坑,佔的坑中有自己構造的虛表。
分析方式:
觸發UAF漏洞需要一系列的操作,而不是像傳統的溢位一個操作就會導致溢位。IE瀏覽器中的DOM標籤由一個物件來表示,並且IE自帶的類中存在了一些物件管理的方法。分析UAF漏洞的要點在於搞清楚物件是在哪裡被分配的,哪裡被釋放的,哪裡被重用的。UAF的異常觸發點是很明顯的,就是對已釋放的物件進行操作導致的異常。所以異常點也就是重用點。而由於是對物件的操作,可以列出這個物件的所有方法,找出分配和釋放的方法,對其下斷來分析到底是怎麼發生的UAF過程。
首先要說明2個概念:
- 懸垂指標:懸垂指標是指一類不指向任何合法的或者有效的(即與指標的含義不符)的物件的指標。比如一個物件的指標,如果這個物件已經被釋放或者回收但是
指標沒有進行任何的修改仍然執行已被釋放的記憶體,這個指標就叫做懸垂指標
2. UAF漏洞:Use-After-Free是一種記憶體破壞漏洞,簡單的說,漏洞的原因是使用了懸垂指標。
IE瀏覽器DOM樹的實現原理,這是根本
常見的與UAF漏洞配合使用的就是堆噴射了,堆噴射的思想就是分配大量記憶體,增大靶子的面積。使EIP能跳進分配的記憶體中。而分配的記憶體中又充滿了滑板指令,只要命中了滑板指令就可以命中Shellcode。為了利用UAF漏洞,要理解漏洞觸發的時機,涉及的物件等。然後透過Js來精心佈局記憶體並控制EIP的控制權。
注意的是,對於UAF漏洞來說,偵錯程式捕獲的異常往往都不是漏洞發生的第一現場,所以一般都要使用gflags開啟PageHeap和UST,命令如下(windbg自帶gflags工具)
gflags.exe /i 程式名.exe +hpa +ust
這樣偵錯程式就會定位到最先出錯的位置
此外有如下技巧:
- 在IDA裡查詢函式後,在Windbg裡下斷。如果知道了一個物件的一個方法卻不知道怎麼斷下它,就用IDA載入符號,搜尋方法。說不定就能找到對應的C++函式名。
- 1.開啟poc檔案後,出現crash就是物件被重用,根據crash地址來找到重用的物件起始地址。
- 2.對物件起始使用!heap -p -a 地址。就可以獲得這個物件的分配資訊,由回溯還可以知道是什麼函式分配的
- 3.對分配函式下斷來達到分配現場
- 4.如果!heap -p -a 地址 後得到的是釋放的回溯,那麼怎麼知道分配函式呢?答案是在釋放函式上下斷,然後斷到那裡時使用!heap -p -a 地址得到的就是分配的回溯了,計劃通。
- 在回溯中,所謂的分配函式一般就是RtlAllocateHeap的上層。而釋放函式一般就是FreeHeap的上層(或者RtlFreeHeap?)
一個頁面包含CMarkup物件來表示頁面的結構或者DOM數。CMarkup物件包含一個指向根CElement物件的指標。CElement物件是很多實體類的父類。在圖1中Javascript物件e_1和e_2是繼承自CElement的CObjectElement物件。CElement物件存在一個指向CTreeNode物件的指標。CTreeNode物件還存在一個與CElement物件相關的指標。CTreeNode的物件有一對指向CTreePos物件的指標。
那為什麼一個CTreePos是必須的?因為IE使用了伸展樹演算法(Splay Tree)來操控DOM樹。在伸展樹演算法樹中CTreePos物件作為一個節點。CMarkupPointer物件代表CMarkup物件中的一個地址。所以CMarkupPointer物件有一個指向CTreePos物件的指標來代表他的地址。CMarkup物件有很多與UAF相關的狀態。
l 嵌入狀態:這意味著CMarkupPointer建立了CTreePos物件並加入了伸展樹中。
l 非嵌入狀態:這意味著CMarkupPointer把CTreePos物件移出伸展樹並釋放。
下圖展示了伸展樹的互動過程:
透過