BlueKeep 漏洞利用分析

做者:SungLin@知道創宇404實驗室
時間:2019年9月18日html

0x00 信道的建立、鏈接與釋放

通道的數據包定義在MCS Connect Inittial PDU with GCC Conference Create Request中,在rdp鏈接過程以下圖所示:git

BlueKeep 漏洞利用分析

信道建立數據包格式以下:github

BlueKeep 漏洞利用分析

在MCS Connect Inittial中屬於Client Network Data數據段,MS_T120將會在鏈接一開始的時候經過函數termdd!_IcaRegisterVcBin建立一個虛擬通道id是0x1f大小爲0x18的結構體,以後就調用termdd!IcaCreateChannel開始建立大小爲0x8c的信道結構體以後將會與虛擬通道id是0x1f綁定,也就是這個結構體將會被咱們利用windows

BlueKeep 漏洞利用分析

信道的定義字段主要是名字加上配置,配置主要包括了優先級等api

BlueKeep 漏洞利用分析

在server對MCS Connect Inittial應答包,將會依次給出對應虛擬通道的id值:數組

BlueKeep 漏洞利用分析

在rdp內核中依次註冊的值對應應該是0、一、二、3, MS_T120信道將會經過咱們發送的用戶虛擬id爲3的值再一次綁定,首先經過termdd!_IcaFindVcBind找到了剛開始註冊的虛擬通道id是0x1f,以下所示:服務器

BlueKeep 漏洞利用分析

可是在termdd!_IcaBindChannel時,卻將咱們自定義的id值爲3與信道結構體再一次綁定在一塊兒了,此信道結構體就是MS_T120ide

BlueKeep 漏洞利用分析

同時咱們本身的用戶id將內部綁定的0x1f給覆蓋了函數

BlueKeep 漏洞利用分析

咱們往信道MS_T120發送數據主動釋放其分配的結構體,其傳入虛擬通道id值爲3經過函數termdd!IcaFindChannel在channeltable中查找返回對應的信道結構體:spa

BlueKeep 漏洞利用分析

下圖爲返回的MS_T120信道結構體,其中0xf77b4300爲此信道可調用的函數指針數組:

BlueKeep 漏洞利用分析

在這個函數指針數組中主要存放了三個函數,其中對應了termdd!IcaCloseChannel、termdd!IcaReadChannel、termdd!IcaWriteChannel

BlueKeep 漏洞利用分析

咱們傳入釋放MS_T120信道的數據以下,字節大小爲0x12,主要數據對應了0x02

BlueKeep 漏洞利用分析

以後將會進入nt! IofCompleteRequest函數,經過apc注入後,將會經過nt! IopCompleteRequest和nt!IopAbortRequest進行數據請求的響應,最終在termdd!IcaDispatch完成咱們發送數據的的請求,_BYTE v2就是咱們發送的數據,因此咱們發送的數據0x02將會最終調用到IcaClose函數進入IcaCloseChannel函數,最後主動釋放掉了MS_T120信道結構體

BlueKeep 漏洞利用分析BlueKeep 漏洞利用分析

0x01 經過RDPDR信道進行數據佔位

咱們先來了解下rdpdr信道,首先rdpdr信道是文件系統虛擬通道擴展,該擴展在名爲rdpdr的靜態虛擬通道上運行。目的是將訪問從服務器重定向到客戶端文件系統,其數據頭部將會主要是兩種標識和PacketId字段組成:

BlueKeep 漏洞利用分析

在這裏咱們恰好利用到了rdpde客戶端name響應的數據來進行池內存的佔位

BlueKeep 漏洞利用分析

在徹底創建鏈接後,將會建立rdpdr信道的結構體

BlueKeep 漏洞利用分析

在window7中,在創建完成後接收到server的rdpdr請求後,經過發送客戶端name響應數據,將會調用到termdd! IcaChannelInputInternal中的ExAllocatePoolWithTag分配非分頁池內存,而且其長度是咱們能夠控制的,基本知足了UAF利用的需求:

BlueKeep 漏洞利用分析

但是在windowsxp中,直接發送client name request將會致使內存分配失敗,直接進入termdd! _IcaCopyDataToUserBuffer,而且在Tao Yan and Jin Chen[1]一文中也提到了經過發送client name request在觸發必定的條件後將會繞過termdd!_IcaCopyDataToUserBuffer而進入ExAllocatePoolWithTag分配咱們想要的非分頁內存,而打破條件以下:

BlueKeep 漏洞利用分析

咱們先來看看最開始信道結構體的建立,咱們能夠發現從一開始建立信道結構體的時候,將會出現兩個標誌,而這兩個標誌是按照地址順序排列的,而在上面須要打破的條件中,只要channelstruct +0x108的地址存放的是同一個地址,循環就會被break

BlueKeep 漏洞利用分析

咱們發送一個正常的rdpdr的name request數據包,頭部標識是0x7244和0x4e43

BlueKeep 漏洞利用分析

通過termdd!_IcaCopyDataToUserBuffer以後,將會進入nt!IofCompleteRequest,在響應請求後進入rdpdr!DrSession::ReadCompletion,此函數處理邏輯以下,其將會遍歷一個鏈表,從鏈表中取出對應的vftable函數數組

BlueKeep 漏洞利用分析

遍歷第一次取出第一張函數數組

BlueKeep 漏洞利用分析BlueKeep 漏洞利用分析

傳入咱們發送的數據後,經過函數數組調用rdpdr!DrSession::RecognizePacket進行讀取

BlueKeep 漏洞利用分析

判斷頭部標誌是否爲(RDPDR_CTYP_CORE)0x7244
BlueKeep 漏洞利用分析

接着將會讀取函數vftable第二個地址,進行轉發

BlueKeep 漏洞利用分析
以下圖能夠看到rdpdr的數據包處理邏輯

BlueKeep 漏洞利用分析

rdpdr通過一系列數據包處理後最終進入了咱們關心的地方,將會傳入channelstruct經過調用termdd! _IcaQueueReadChannelRequest進行標誌位的處理

BlueKeep 漏洞利用分析

最初rdpdr的channelstruct的標誌位以下

BlueKeep 漏洞利用分析

通過函數termdd! _IcaQueueReadChannelRequest對此標誌的處理後變成以下,因此下一個數據依然會進入termdd!_IcaCopyDataToUserBuffer,致使咱們進行池噴射的失敗

BlueKeep 漏洞利用分析

回到rdpdr頭部處理函數rdpdr!DrSession::RecognizePacket,咱們發如今鏈表遍歷失敗後將會進行跳轉,最後將會進入讀取失敗處理函數rdpdr!DrSession::ChannelIoFailed,而後直接return了

BlueKeep 漏洞利用分析BlueKeep 漏洞利用分析

咱們構造一個頭部異常的數據包發送,頭部標誌咱們構造的是0x7240,將會致使rdpdr!DrSession::RecognizePacket判斷失敗,以後將會繼續遍歷鏈表依次再取出兩張函數數組

BlueKeep 漏洞利用分析

最後兩個函數數組依次調用rdpdr!DrExchangeManager::RecognizePacket和rdpdr!DrDeviceManager::RecognizePacket,都會判斷錯誤的頭部標誌0x7240,最後致使鏈表遍歷完後進行錯誤跳轉,直接繞過了termdd! _IcaQueueReadChannelRequest對標誌位的修改,將會打破循環

BlueKeep 漏洞利用分析BlueKeep 漏洞利用分析

最後咱們連續構造多個錯誤的數據包後將會進入ExAllocatePoolWithTag,分配到咱們須要的非分頁內存!

BlueKeep 漏洞利用分析BlueKeep 漏洞利用分析

0x02 win7 EXP 池噴射簡要分析

首先被釋放的MS_T120池大小包括是0x170,池的標誌是TSic

BlueKeep 漏洞利用分析

分析Win7 exp 能夠知道數據佔位是用的rdpsnd信道,做者沒有采用rdpdr信道,應該也和噴射的穩定性有關,rdpsnd噴射是再創建完了rdpdr初始化後開始的,在free掉MS_T120結構體前,發送了1044個數據包去申請0x170大小的池內存,這樣作能夠說應該是爲了防止以後被free掉的內存被其餘程序佔用了,提升free後內存被咱們佔用的生存概率

BlueKeep 漏洞利用分析

佔位被free的實際數據大小爲0x128,利用的中轉地址是0xfffffa80ec000948

BlueKeep 漏洞利用分析

以後開始池噴射,將payload噴射到能夠call [rax] == 0xfffffa80ec000948的地方,噴射的payload大小基本是0x400,總共噴射了200mb的數據大小,咱們先來看下噴射前帶標誌TSic總共佔用池內存大小是58kib左右

BlueKeep 漏洞利用分析BlueKeep 漏洞利用分析

噴射完後帶TSic標誌池內存大小大約就是201mb,池內存噴射基本是成功的,個人win7是sp1,總共內存大小是1GB,再噴射過程當中也沒有其餘干擾的,因此噴射很順利

BlueKeep 漏洞利用分析BlueKeep 漏洞利用分析

圖中能夠發現基本已經很穩定的0x400大小的池噴射payload,地址越高0x400大小的內存基本就很穩定了

BlueKeep 漏洞利用分析

最後斷開鏈接時候,被free的內存已經被咱們噴射的0x128大小的數據給佔用了
BlueKeep 漏洞利用分析

執行call指令後穩定跳轉到了咱們的payload,成功執行!

BlueKeep 漏洞利用分析

參考連接:
[0] https://github.com/rapid7/metasploit-framework/pull/12283
[1] https://unit42.paloaltonetworks.com/exploitation-of-windows-cve-2019-0708-bluekeep-three-ways-to-write-data-into-the-kernel-with-rdp-pdu/
[2] https://wooyun.js.org/drops/%E7%BE%8A%E5%B9%B4%E5%86%85%E6%A0%B8%E5%A0%86%E9%A3%8E%E6%B0%B4%EF%BC%9A%20%E2%80%9CBig%20Kids%E2%80%99%20Pool%E2%80%9D%E4%B8%AD%E7%9A%84%E5%A0%86%E5%96%B7%E6%8A%80%E6%9C%AF.html

相關文章
相關標籤/搜索