引言:

在上個月微軟的安全補丁中,包含一個在野利用的win32k 提權漏洞。該漏洞似乎不能在win11 的系統版本上觸發,僅存在於早期系統。

這類漏洞的利用來源已久,此次,我們希望分析這類在當前新緩解措施不斷改善的背景下,攻擊組織是可能如何繼續利用這個漏洞。

我們在server2016 下完成整個分析過程。

背景補充:

0day 漏洞,即零日漏洞,指未被披露和修補的漏洞,時間概念上類比於Web3 更為人熟知的概念,是T+0 交易。 0day 漏洞被發現後可以在未被察覺的情況惡意利用,這類攻擊往往具備極大的破壞性。

Numen Cyber 本次發現的0day 漏洞是微軟Windows 系統層面的漏洞,通過該漏洞,黑客可獲取Windows 的完全控制權。

被黑客控制所有權的後果,包括不限於個人信息竊取、系統崩潰數據丟失、財務損失、惡意軟件植入等,小範圍說,你的私鑰可以被竊取,以及數字資產被轉移。大範圍說,這個漏洞能掀掉基於Web2 基礎設施運行的Web3 牌局。

Numen 獨家:微軟 0day 漏洞可系統+物理層面掀掉 Web3 牌局

圖標僅為示意

補丁分析

分析補丁,我們似乎並不能太直觀看出是什麼問題,這裡僅僅似乎是一個對象的引用計數被多處理了一次:

Numen 獨家:微軟 0day 漏洞可系統+物理層面掀掉 Web3 牌局

但因為win32k是比較古老的代碼,我們能找到一些早期的源碼註釋:

Numen 獨家:微軟 0day 漏洞可系統+物理層面掀掉 Web3 牌局

這樣就非常好理解了,這裡說明以前的代碼只是鎖定了窗口對象,沒有鎖定窗口對像中的菜單對象,這裡菜單對象可能被錯誤引用。

實現poc

https://github.com/numencyber/Vulnerability_PoC/blob/main/CVE-2023-29336/poc.cpp

如何錯誤的引用這個窗口中的菜單對象呢?

分析漏洞函數上下文,我們發現一個問題,傳入到xxxEnableMenuItem()的菜單,通常已經在上一層函數被鎖定,那這裡到底是要保護哪一個菜單對象呢?

Numen 獨家:微軟 0day 漏洞可系統+物理層面掀掉 Web3 牌局

繼續分析xxxEnableMenuItem 中,對菜單對象的可能處理過程,我們終於發現xxxEnableMenuItem 中的MenuItemState 函數返回的菜單有兩種可能,一種就是窗口中的主菜單,但也有可能是菜單中的子菜單,甚至子子菜單。

Numen 獨家:微軟 0day 漏洞可系統+物理層面掀掉 Web3 牌局

poc 中,我們構造一個特殊的菜單(這裡是三層,四個菜單):

Numen 獨家:微軟 0day 漏洞可系統+物理層面掀掉 Web3 牌局

上面相鄰的菜單都是父子關係,如菜單D 是菜單C 的子菜單。

並且這些菜單有以下一些特點(這些特徵都是為了通過xxxEnableMenuItem 函數中的檢測和判斷,因為這和該漏洞產生原理有關):

  1. 菜單D 中,必須其ID 類型必須為系統菜單類型的一種,如:0xf060(關閉菜單).
  2. 菜單A 也必須是系統菜單,為了在後續的菜單遍歷過程中在菜單C 中的子菜單中尋找到我們指定的系統菜單類型0xf060(菜單A 中如果包含我們要找的系統菜單類型,會提前結束菜單查找過程)。我們需要刪除菜單A 中的對應系統菜單類型0xf060。
  3. 刪除掉菜單C 在菜單B 中的引用,才能在返回用戶層的過程中徹底釋放菜單C。
  4. 為什麼需要菜單B,這裡我們並不確認這是否是必須以及原理,但如果沒有菜單B 這一層,似乎菜單C 的釋放仍有一些不順利。

在xxxRedrawTitle 返回用戶層的時候,刪除菜單C 和菜單B 的引用關係,然後成功釋放該菜單C。

最後,回到內核中的xxxEnableMenuItem 函數的xxxRedrawTitle 函數返回點時,後面即將引用的菜單C 對像已經無效。

實現exp

A. 整體思路

在確定使用哪種利用思路之前,我們通常希望做一些理論上的前期判斷,以避免一些不能繞過關鍵問題的方案會浪費大量嘗試時間。這也是在分析其他漏洞poc 或者exp 的一個常規過程。

本次漏洞exp 構造前,我們主要有以下兩種考量方向:

執行shellcode 代碼:

這個思路參考早期的CVE-2017-0263 和CVE-2016-0167。這種方式我們並沒有嘗試,因為在該漏洞的這個方案下,執行shellcode 的入口點以及一些例如SMEP 的安全機制問題在高版本windows 中,可能並沒有一些方便且已經公開的解決方式。

利用讀寫原語修改token 地址:

即使在最近的兩年,依然已經有公開的exp 可以參考。其中對於桌面堆內存佈局以及桌面堆中的讀寫原語具有長久的通用性。我們現在唯一需要花更多時間完成的只是分析出UAF 內存被重用時,如何第一次控制cbwndextra 為一個特別大的值。

所以,這裡我們將整個exp 利用拆分為兩個問題。一個是如何利用UAF 漏洞控制cbwndextra 的值,另一個則是控制cbwndextra 值後,穩定的讀寫原語方式。

B. 如何寫入第一次數據

當我們最開始觸發漏洞時,系統並不總會crash。因為我們的漏洞觸發方式裡,我們已經去掉了被重用漏洞在系統中所有的其他關聯。

系統可能錯誤使用這個被我們控制內存的窗口對像數據基本只有xxxEnableMenuItem 函數中的MNGetPopupFromMenu() 和xxxMNUpdateShownMenu()。

我們使用窗口類WNDClass 中的窗口名稱對象來佔用漏洞觸發中我們釋放的菜單對象。

我們能夠實現第一次的數據寫入時機也在這其中。

我們需要做的只有一件事,就是找到一個可以由我們構建的地址結構中,能夠被任意寫入數據的地方。哪怕僅僅一個字節(我們可以將這個字節寫入到cbwndextra 的高位)。

此過程如在迷宮中尋找一條出路,不再贅述。

Numen 獨家:微軟 0day 漏洞可系統+物理層面掀掉 Web3 牌局

最終我們有xxxRedrawWindow 函數中的兩個預備的方案。

如果使用GreCreateRectRgnIndirect,交換相鄰內存數據的方式有兩個困難。

一是cbwndextra 的前一個8位是一個非常不易控制的參數,並且似乎只能在有限的條件下短暫為1.另外使用這種方式時,cbwndextra 的其他相對偏移會定位到前一個對象(無論任何對象,因為這裡只和窗口對象cbwndextra 偏移本身大小有關)的最後8位,這是一個堆鍊錶尾的安全字節,其不易受控。

所以我們使用了第二個地址寫入點,即依靠一個標誌位的AND 2 操作。但同樣,由於上述的堆鍊錶尾的安全字節不易受控的原因,我們變換以下思路:

我們並不寫入窗口對象的cb-extra,而是寫入HWNDClass 的cb-extra。這是因為後者的cb-extra 偏移相對於前者的cb-extra 偏移更小,我們可以通過佈局內存,控制前一個對象的內存數據來當作通過xxxRedrawWindow 函數中,對對象標誌判斷的參數。

C. 穩定的內存佈局

Numen 獨家:微軟 0day 漏洞可系統+物理層面掀掉 Web3 牌局

我們設計內存至少是連續三個0x250 字節的HWND 對象。釋放掉中間那一個,構造一個0x250 字節的HWNDClass 對象去佔用釋放掉的HWND 對象。

前一個HWND 對像其尾部數據作為通過xxxRedrawWindow 中標誌檢驗的參數。後一個HWND 對像其菜單對象和其HWNDClass 對像作為最終讀寫原語的媒介。

我們盡量控制窗口對象和我們的的HWNDClass 對象盡量大小一致,窗口對象的擴展數據大小也要足夠大,以通過前面提到的修改第一個窗口class 對象的額外數據大小參數。

我們通過堆內存中的洩露的內核句柄地址來精確判斷(計算按順序排列的相鄰對象的間距)我們申請的窗口對像是否按照我們預期的順序排列。

D. 讀寫原語的一些修改

任意讀原語我們仍然使用GetMenuBarInfo();

任意寫原語我們則使用SetClassLongPtr();

除了替換TOKEN 的寫入操作是依賴第二個窗口的class 對象,其他寫入都是利用第一個窗口對象的class 對象使用偏移來寫入。

EXP 鏈接

https://github.com/numencyber/Vulnerability_PoC/tree/main/CVE-2023-29336

總結

A. win32k 現狀

win32k 漏洞歷史眾所周知。但在最新的windows11 預覽版中,微軟已經在嘗試使用Rust 重構該部分內核代碼。未來該類型的漏洞在新系統可能被杜絕。

B. 漏洞利用過程基本不太困難

唯有如何使用釋放內存重新佔用的數據去控制第一次寫入的方法需要比較細心的嘗試外,基本不要需要使用到任何新的利用技術,該類漏洞嚴重依賴桌面堆句柄地址的洩露。

雖然其較以往有改動,但如果不徹底解決這個問題,對於老舊系統始終是一個不安全的隱患。

C. 漏洞的發現

分析該漏洞,我們擅自猜測該漏洞的發現可能依賴於更加完善的代碼覆蓋率檢測。一旦系統API 在目標函數的執行路徑能夠到達最深處的漏洞點,並且目前窗口對象本身也是一個多重嵌套引用狀態,這個漏洞就可能被fuzz 發現。

D. 其他發現途徑

對於漏洞利用檢測來說,除了對於漏洞觸發函數的關鍵點的檢測,對於這類不常見的對內存佈局以及對窗口或者窗口類額外數據的異常偏移讀寫的針對檢測將是發現此類型同種漏洞的可能途徑之一。

參考:

1.https://github.com/0x5bfa/NT5.1/blob/1b390dddff9fe017e9c11a7845c67a887c3483dc/Source/XPSP1/NT/windows/core/ntuser/kernel/mnsys.c#L511

2.https://github.com/L4ys/CVE-2022-21882/blob/main/CVE-2022-21882.cpp

3.https://github.com/KaLendsi/CVE-2022-21882/blob/main/ExploitTest.cpp

4.https://www.zerodayinitiative.com/blog/2023/5/8/the-may-2023-security-update-review

5.https://www.real-sec.com/2022/01/technical-analysis-of-cve-2021-1732/