一位元控制所有:透過一位元繞過Windows 10保護

wyzsk發表於2020-08-19
作者: cssembly · 2015/02/12 9:24

0x00 前言


這篇文章講述了微軟最新修補的漏洞CVE-2015-0057的細節。

原文:《One-Bit To Rule Them All: Bypassing Windows’ 10 Protections using a Single Bit》

連結:http://breakingmalware.com/vulnerabilities/one-bit-rule-bypassing-windows-10-protections-using-single-bit/

今天微軟釋出了最新的補丁。這個補丁修復了漏洞CVE-2015-0057,這是我們幾個月前負責任地披露給微軟的一個重要級別的可利用漏洞。 作為研究的一部分,我們發現這個許可權提升漏洞,利用該漏洞,可使攻擊者完全控制權Windows系統。換句話說,獲得Windows訪問權的攻擊者(例如,透過網路釣魚運動)可以利用此漏洞繞過Windows所有的安全措施,擊敗緩解措施,如沙箱,核心隔離和記憶體隨機化。 有趣的是,漏洞利用僅需要修改Windows作業系統一個位元。

我們已經證實了這一漏洞對所有支援的Windows桌面版本都是可用的,包括Windows10技術預覽版。

下面開始漏洞的細節。起初,我們似乎無法利用它。但是經過一番努力,我們成功地利用了它,我們將描述整個過程。作為分析的一部分,我們也展示了利用影片。最後,透過分享我們認為有趣的死程式碼bug來總結文章。

負責任的披露:儘管這篇部落格是技術性的,但我們不會發布任何程式碼,或完整的細節,以防止任何人重現漏洞。

0x01 背景


在過去的幾年裡,許可權提升漏洞對於漏洞利用來說變得更加重要了,因為它使惡意程式碼可以在核心許可權上執行。因此,攻擊者利用許可權提升漏洞可以繞過安全防護機制,如應用程式沙箱。

伴隨著攻擊技術的發展,微軟做了大量的努力來保護核心。其理由是,即使漏洞存在,利用也是很困難的,但不是不可能。 例如,這裡僅僅是少數存在於Windows 8.1的核心保護機制:

核心DEP - 確保大多數核心資料區不能被執行

KASLR - 隨機化核心地址空間,以避免核心模組位置固定

完整性等級 - 限制非特權應用程式洩漏核心相關資訊的能力

常見攻擊向量的緩解 – 常被濫用的結構的保護(如Win32K WND PROC域)

SMEP - 防止執行核心模式到使用者模式的控制轉移

NULL解引用保護 - 禁止使用者空間前64K資料的對映

儘管存在這些保護機制,在過去的一年中,我們已經看到了一些演示,展示了繞過這些保護機制的技術。

我們在本文中描述的漏洞,就是新近披露的繞過這些保護的可利用的許可權提升漏洞。

漏洞:Win32k.sys中的模組的一個漏洞

這一漏洞出現在微軟Windows核心GUI元件中,即Win32k.sys模組中。

本文假設對Win32k.sys模組有很強的技術認識。此模組的詳細資訊,請參考Tajei Mandt的Kernel Attacks through UserMode Callbacks,Gilad Bakas 的Windows Kernel Vulnerability Research and Exploitation。

0x02 瞭解視窗捲軸


WIN32K模組實際上管理著windows捲軸。這些捲軸 - 無論是水平或垂直 – 都是為每個視窗設定的。

enter image description here

圖1

正如圖1中看到的,每個SBDATA結構定義關於一個捲軸的資訊。

WSBflags是一個位掩碼,決定了捲軸的狀態。

為了啟用和禁用一個視窗捲軸,可以使用xxxEnableWndSBArrows函式。透過簡單的函式呼叫,這個函式就可以改變捲軸的狀態。 漏洞正是存在於此功能中。

0x03 深入探究 xxxEnableWndSBArrows


xxxEnableWndSBArrows原型如下:

enter image description here

wnd - 一個指向相關視窗的指標

wSBflags - 捲軸型別(例如水平或垂直)

wArrows - 指定捲軸的箭頭是否啟用或禁用,並指示那個箭頭啟用或禁用。

為了描述漏洞,我們就來看看在xxxEnableWndSBArrows功能的第一部分,可細分為3個邏輯部分的:

1. - 分配一個新的捲軸(如果需要)


該功能首先透過檢查該視窗是否已經存在滾動資訊,並根據需要分配一個新的捲軸資訊結構。

從技術上講,該函式讀取pSBInfo域(這個欄位指向tagSBINFO結構),測試指標是否為NULL。如果該欄位為null和wArrows引數不是NULL,則為視窗分配一個tagSBINFO結構,捲軸的舊標誌被設定為0,否則從現有的視窗捲軸的資訊中複製舊的標誌。該程式碼可以在圖2中找到。

enter image description here

2. 設定水平捲軸的狀態


流程繼續測試是否應該改變水平滾動的狀態。

根據設定的wArrows引數是什麼,函式啟用或禁用的箭頭(圖3)。

enter image description here

3. 測試滾動箭頭的狀態


流程繼續檢查箭頭的狀態是否發生了變化。

從技術上講,這是透過檢查箭頭的標誌來做的(注意,有幾個標誌的檢查 - 但這些對於我們的目的來說都不是很有趣)。如果標誌已經改變,同時該視窗可見,則xxxDrawScrollbar被呼叫。

這正是事情變得有趣的地方。

當深入研究程式碼,似乎xxxDrawScrollBar可能會導致使用者模式回撥(圖4)。

enter image description here

呼叫鏈中的關鍵函式是ClientLoadLibrary。這個函式執行回撥到使用者模式函式__ClientLoadLibrary。

現在,讓我們回到xxxEnableWndSBArrows的程式碼。

我們的檢查表明tagSBINFO指標在回撥後,不任何驗證就使用了。最終,這可能會導致使用後釋放(UAF)漏洞,因為該函式可能繼續使用被釋放了的捲軸資訊(圖5)。

enter image description here

0x04 漏洞利用:操縱窗戶屬性


回撥之後,xxxEnableWndSBArrows函式繼續並且改變垂直捲軸的狀態。

在這個階段中,函式試圖啟用或禁止標誌。然而,由於該結構已經被釋放,我們可以用它來將位於釋放的緩衝區的第一個DWORD與0xC按位或(如果我們禁止箭頭)或者清除第3位和第4(如果啟用箭頭)。見圖6。

enter image description here

為了簡便起見,我們將展示如何操縱2個位元位來完全控制系統。其實,操縱其中之一就足夠了。

似乎位操作起初還不足以造成任何顯著影響,但我們還是決定繼續嘗試。最需要去嘗試的事情是,或者增加一些緩衝(使用按位OR)的大小或者減少一定的參考計數器(使用按位AND)。

短暫的搜尋後,我們發現了滿足第一個要求的物件。這個物件是一個視窗的屬性列表。

在視窗屬性列表


每個視窗都有一個屬性列表。通常GUI應用程式可以使用這些屬性來儲存任意值, Win32K也使用屬性列表以便儲存內部資料。

enter image description here

用於儲存視窗的屬性的資料結構可以在圖7中看到。第一個域cEntries,是屬性陣列中的條目數; iFirstFree是屬性列表中的第一空閒單元的索引;和props 是PROP陣列。

應用程式可以使用SetProp API設定視窗的屬性。該函式的原型如下:

enter image description here

hWnd -視窗控制程式碼。

lpString – 屬性或ATOM。

HDATA – 要儲存的資料。

新增屬性到一個視窗是透過CreateProp函式來完成,它在Win32K模組中。

如圖8所示它的分配演算法是相當簡單的。如果沒有空間可用於屬性列表中的新條目,則函式分配多一個條目的新列表。該函式然後將舊屬性的緩衝區複製到新的緩衝區,釋放舊的緩衝區,並增加條目計數。

enter image description here

這段程式碼中還有幾個重要的點要注意: 首先,屬性是從桌面堆中分配(使用DesktopAlloc)。tagSBINFO也從該堆中分配。如果我們想用UAF漏洞來改變屬性結構,這是至關重要的。 第二,每一個新的條目都觸發緩衝區的重新分配。這意味著我們可以很容易地觸發緩衝區的重新分配,來達到tagSBINFO結構的大小。這樣做增加了緩衝區將被分配在釋放了的tagSBINFO結構的地址的機會。 第三,也是最重要的是,cEntries域位於該結構的第一個DWORD。這意味著我們可以增加它的大小(用按位OR)。增加屬性陣列的大小後,我們基本上實現了經典的緩衝區溢位。

0x05 概念證明影片


上面研究了許可權提升漏洞的利用。我們就此停止,同時避免釋出任何敏感程式碼。 我們在64位Windows10技術預覽版上提供了概念證明。

視屏地址:https://www.youtube.com/watch?v=ukAr6MiA788

0x06 總結


經過一番工作,我們成功地建立針對Windows所有版本的一個穩定利用 - Windows XP到Windows10預覽都可用(SMEP和其他保護都開啟)。我們已經表明即使是微小的缺陷也可以用來完全控制任何Windows作業系統。

儘管如此,我們認為微軟在使其作業系統更安全方面做的努力起到了顯著作用,編寫可靠的攻擊程式碼比以往更難了。 不幸的是,這些措施不能完全阻止攻擊者。我們預計,攻擊者將繼續整合漏洞利用到他們的犯罪工具包,使得妥協在所難免。

最後旁註:有趣的程式碼


檢查xxxEnableWndSBArrows函式的程式碼,可以看到有呼叫xxxWindowEvent函式。

乍一看,似乎這兩個函式會比xxxDrawScrollbar函式更容易用於漏洞利用,具體如上所述。

但是,在深入研究程式碼之後,很快就明白,在程式碼中的橫向捲軸部分呼叫xxxWindowEvent實際上是死程式碼(圖9)。

enter image description here

看程式碼,有兩個條件呼叫xxxWindowEvent函式。僅當捲軸資訊的舊標記與新的標誌不同時,這些呼叫才執行。然而,在這些條件出現時,舊的標誌的值與新的標誌總是相等的。因此,呼叫xxxWindowEvent的條件是永遠不會滿足的。這實際上意味著,這個死碼在那裡大約15年沒有做任何事。

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章