乾貨|微軟遠程桌面服務蠕蟲漏洞(CVE-2019-1182)分析

Alt

2019年8月,微軟發佈了一套針對遠程桌面服務的修復程序,其中包括兩個關鍵的遠程執行代碼(RCE)漏洞,CVE-2019-1181和CVE-2019-1182。與以前修復的「BlueKeep」漏洞(CVE-2019-0708)相似,也具備蠕蟲特性,即利用這些漏洞的惡意軟件可能會在無需用戶交互的狀況下在易受攻擊的機器間進行傳播。

本文主要經過對CVE-2019-1182漏洞進行分析,讓你們對於漏洞的成因及漏洞修復有一個更加全面的認識。git

系統版本:Windows 10 1903github

補丁:windows10.0-kb4512508-x64_1893edc9a11d760be11e49d2500170ceee8026d7windows

漏洞危害

公網開放RDP服務的主機數量巨大,影響面極大。危險等級:嚴重,請用戶儘快升級更新。函數

成因分析

分別提取補丁前和補丁後rds(Remote Desktop Service)進程相關bin文件及相關驅動模塊,通過ida和bindiff分析後定位到rdpbase.dll。該模塊改動不多(只有一處函數差別),能夠很快定位到問題函數,以下圖所示。大數據

Alt

分析差別函數DecompressUnchopper::Decompress發現存在一處整型溢出漏洞。加密

Alt

上圖左邊是patch以後的代碼,右邊是patch以前的代碼,能夠看到pcach以前指令eax+0x2000做爲函數new的參數使用,patch後增長了對size的校驗,會判斷edx+0x2000是否大於edx,什麼狀況下一個值加上0x2000會大於以前的值呢?對於無符號整數來講當0xffffe000<size<0xffffffff時,size+0x2000將位於(0,0x2000)這個區間,size style="font-size: inherit;color: inherit;line-height: inherit;">size+0x2000.補丁後的反編譯代碼以下</size<0xffffffff時,size+0x2000將位於(0,0x2000)這個區間,size>spa

Alt

patch的思路很簡單,當size>size+0x2000時,new(-1)後續邏輯函數直接return。3d

下面咱們根據DecompressUnchopper::Decompress的邏輯梳理一下該漏洞可能的利用思路。指針

Alt

如上圖所示,能夠看到函數尾部調用了memcpy,第一個參數dest指向的內存爲前面new分配的內存空間。若是咱們把decompressedSize設置爲[0xffffe000,0xffffffff]的一個值,當加上0x2000後decompressedSize小於原值,此時若是buff仍是原來的大小,會致使memcpy的操做覆蓋掉dest後面buff-(decompressedSize+0x2000)個字節,若是後面的地址空間保存有虛表指針之類的地址則能夠致使控制流劫持。調試

poc構造

以上的分析基於對相關模塊的逆向分析及靠經驗猜想,爲了驗證思路是否正確首先須要可以有觸達漏洞函數的rdp包。下面的敘述基於對CVE-2019-0708 poc的理解以及微軟官方提供的rdp協議文檔。

首先看一下微軟的官方公告[1]:

Alt

從公告的描述來看這個漏洞跟CVE-2019-0708相似,均可以形成蠕蟲傳播的效果,因此也是不須要進行登陸認證便可利用該漏洞遠程代碼執行,感受大部分代碼能夠複用因此決定在CVE-2019-0708的poc [2]基礎上構造CVE-2019-1182的poc。

經過研究CVE-2019-0708的poc和微軟官方文檔[3]能夠了解到rdp協議的通訊流程,以下圖所示:

Alt

此找不到觸達漏洞函數的任何線索,思路仍是要回到逆向漏洞函數週圍的處理邏輯上。交叉引用並無發現對DecompressUnchopper::Decompress的靜態調用,搜索一下DecompressUnchopper這個類相關的函數:

Alt

通過分析發現是DecompressRdp8__CreateInstance這個函數建立了DecompressUnchopper對象,繼續查看DecompressRdp8__CreateInstance沒有找到對此函數的靜態調用,發現這個函數是個導出函數,最後通過搜索發現該函數在rdpserverbase.dll中進行了導入,交叉引用發現有兩處調用:

Alt

上圖中能夠看到是在CRdpDynVC這個類的成員函數中進行了調用,所以猜想可能和rdp的dvc(Dynamic Virtual Channel)信道有關,關於dvc信道的詳細信息可參考微軟官方文檔[4]。經過查閱官方文檔初步定位到經過dvc信道發送加密數據可能會觸達漏洞函數。

dvc信道的創建流程以下:

(1) dvc init.

Alt

(2) dvc open

Alt

(3) dvc send&recv data

Alt

dvc信道可分片傳輸超大數據(最大不超過2^32-1字節),並支持非加密和加密數據傳輸。

Alt

(4) dvc close

Alt

基於以上的研究,下面嘗試構造一個可觸達漏洞函數的dvc pdu。加密的dvc pdu結構以下圖所示,詳細信息參見官方文檔。

Alt

發送的數據包:

dvc_send = ( #pdu header "0300004002F08064000503EC70322A00000003000000" #1st byte cid length "68" + channel_id[-2:] + "01110000" #data "414141414141414141414141414141414141414141414141414141" "414141414141414141414141414141414141414141414141414141" "414141414141414141414141414141414141414141414141414141" "414141414141414141414141414141414141414141414141414141" "414141414141414141414141414141414141414141414141414141" "414141414141414141414141414141414141414141414141414141" ) tls.sendall(Packer(dvc_send).bin_unpack())

對DecompressUnchopper::Decompress下斷,運行腳本,觸發斷電,證實以前的猜想是正確的。

Alt

經過調試分析及參考官方文檔,構造以下數據包可致使crash:

dvc_send2 = ( "0300004002F08064000503EC70322A00000003000000" "68" + channel_id[-2:] + "01E0FFFF" "e122550e0ffff080000002690ce0a2b9f6401070000002630d2b4fc0402" ) tls.sendall(Packer(dvc_send).bin_unpack())

崩潰現場:

Alt

調試分析致使crash的緣由以下: DecompressedSize爲0xffffe001,加0x2000以後爲1,new(1)分配了一個字節的堆空間,memcpy屢次像new分配的內存拷貝數據,致使數據一直向後覆蓋,圖中覆蓋到了RdpBoundsAccumulator對象,當執行clear操做時訪問無效地址形成memory corruption。

關於利用的一些思考:精準控制memcpy拷貝長度,覆蓋到某對象的虛表指針或其餘可劫持控制流的內存單元,可致使任意代碼執行,須要考慮cfg等漏洞利用緩解措施的bypass。

點擊【閱讀】,獲取更多信息~

References:

[1] https://msrc-blog.microsoft.c...

[2] https://github.com/algo7/blue...

[3] https://docs.microsoft.com/en...

[4] https://docs.microsoft.com/en...

Alt

Alt

相關文章
相關標籤/搜索