者:興趣使然的小胃
預估稿費:200RMB
投稿方式:發送郵件至linwei#360.cn,或登陸網頁版在線投稿
一、前言
虛擬機指的是安裝在正常宿主機操作系統內的一個完全隔離的客戶機操作系統。虛擬機逃逸指的是突破虛擬機的限制,實現與宿主機操作系統交互的一個過程,攻擊者可以通過虛擬機逃逸感染宿主機或者在宿主機上運行惡意軟件。在最近舉辦的PwnFest黑客大會上(由Power of Community組織,在韓國首爾舉辦),研究人員成功實現了VMware的虛擬機逃逸,這也是VMware首次在公開場合被攻陷,我們對此很感興趣,因此,McAfee IPS漏洞研究團隊決定深入研究這個過程,加深對該漏洞的理解。
二、背景知識
VMware反應非常迅速,他們很快發布了一個安全補丁修復這些漏洞,同時公布了一份安全公告。根據我們在閉源軟件安全問題方面的一貫做法,我們研究了一下這份公告。公告里面提到這樣一段話:
“VMware Workstation和Fusion的拖放(drag-and-drop,DnD)功能中存在一個越界內存訪問漏洞。在運行Workstation或Fusion的操作系統上,攻擊者可以利用這個漏洞實現客戶機逃逸,在宿主機上執行代碼。在Workstation Pro和Fusion上,如果拖放功能和復制粘貼(copy-and-paste,C&P)功能都被禁用,那么這個漏洞就無法利用”。
這個漏洞存在于拖放和復制粘貼功能中。這兩個功能都用到了VMware遠程過程調用(remote procedure call,RPC)機制。VMware的RPC機制一直以來都是一個非常容易被攻破的點,容易實現客戶機到宿主機的逃逸。
在我們深入分析VMSA-2016-0019(CVE-2016-7461)的補丁之前,我們必須先對VMware Workstation如何處理客戶機到宿主機或者宿主機到客戶機之間的復制粘貼操作有所了解。
下圖從類的層次化角度描述了VMware的拖放和復制粘貼(DnDCP)模式(來源:VM Tools開源代碼):
為了無縫實現宿主機與客戶機之間的拷貝粘貼操作,客戶機操作系統需要安裝VMware tools。VMware tools負責處理客戶機到宿主機或者宿主機到客戶機之間的通信。在我們研究過程中,我們使用的環境為Windows客戶機以及Windows宿主機。在Windows客戶機中,tools的主進程為vmtoolsd.exe。
宿主機與客戶機之間相互通信的一種方法是借助RPC接口。VMware使用了一種名為后門(Backdoor)的RPC接口。
2.1 客戶機的RPC機制
讓我們好好研究一下客戶機與宿主機系統彼此如何通過RPC接口進行通信。為了理解客戶機的RPC機制,我們參考了VMware tools的開源組件,即open-vm-tools,這個組件使用如下函數來處理客戶機的RPC調用:
從理論上講,任何用到RpcChannel_Send()或者RpcOut_send()函數的報文都可以使用rpctools.exe工具來發送,這個工具是VMWare Workstation內置的一個命令行工具。
RpcOut_Send()調用了Message_Send(),后者會調用Backdoor()函數。
Backdoor函數負責通過VMware專用的I/O端口來發送消息。
當調用Backdoor函數從客戶機往宿主機發送消息時,通常情況下我們可以看到如下指令集:
安裝完VMware tools后,我們可以在vmtools.dll中找到這個函數。如下圖所示,我們可以看到Backdoor()正在調用sub_10050190函數:
深入研究后,我們發現這個函數會執行特權指令“in.”。
讓我們回到漏洞上來。我們之所以對DnDCP RPC消息感興趣,原因是根據安全公告,該漏洞位于DnDCP RPC中。在VM Tools源碼中,我們可以找到DnDCP RPC消息的具體結構:
從源碼中,我們可知該結構體的第一個成員為RPC命令。如果我們研究客戶機中vmtoolsd.exe的vmtools!RpcOut_send(x,x,x,)函數,我們也會看到相同的信息。
Bool RpcOut_send(RpcOut *out,
char
const
*request,
size_t
reqLen,
char
const
**reply,
size_t
*repLen);
RpcOut_Send()函數的第二個參數是request-RPC報文。如果我們從客戶機操作系統的vm-tools進程中導出相關報文,在數據報文中我們首先可以看到一個RPC命令(也就是DnDCPMsgHrV4結構中的第一個成員),我們也可以看到一個復制粘貼請求報文,這個報文與我們放在客戶機桌面上的debasish.txt測試文件有關。
2.2 客戶機中RPC報文的處理過程
我們來看看宿主機操作系統如何處理RPC請求。在宿主機中,正在運行的每個虛擬機都有一個獨立的進程,進程名為vmware-vmx.exe。
當客戶機發起RPC請求時,vmware-vmx.exe內部的代碼會搜索客戶機的RPC處理表,找到與請求對應的處理程序。
如果我們使用IDA Pro反匯編vmware-vmx.exe,從中查找原始字符串信息,我們可以找到大部分處理程序。
三、漏洞分析
根據以上信息,我們可知vmware-vmx.exe是宿主機上的主要組件,負責處理存在漏洞的復制粘貼RPC組件。接下來,我們從二進制角度對比了已打補丁和未打補丁的程序。VMware Workstation從12.5.2版本起就打上了漏洞補丁,因此我們從二進制角度對比了12.5.2版和12.5.1版的vmware-vmx.exe之間的區別。
我們發現補丁修改了vmware-vmx.exe中的幾個函數,如下圖所示。
其中比較有趣的一個函數是vmware_vmx!sub_140621520。
這個函數之所以會引起我們的注意,原因在于該函數內部調用了memcpy()函數,這個地方是觸發越界漏洞的完美場景。
經過一番調試及逆向分析后,我們確認vmware_vmx!sub_140621520函數負責處理RPC報文,并且我們在客戶機系統中可以控制該函數的某個參數。該參數為指向某個結構體的一個指針,因此我們得以控制傳入的結構體的具體內容。
具體情況如下圖所示。左圖表示的是客戶虛擬機,右圖表示我們已將windbg附加到vmware_vmx.exe進程上。
如上圖所示,我們在vmtoolsd.exe進程運行期間修改了一個RPC報文,隨后該報文被vmware-vmx.exe進程中的vmware_vmx!sub_140621520函數接收。
讓我們反編譯已打上補丁的函數,看看函數添加了哪些代碼來解決這個問題。
為了能夠發送一個有效的RPC報文,我們參考了VM Tools的源碼,源碼中定義了RPC報文的具體結構。RPC報文頭部結構如下圖所示,我們可知該報文頭部大小為0x38。
binarySize以及payloadSize字段對應的是反匯編代碼中的v6及v5變量。我們可以控制這兩個字段的值,觸發越界訪問漏洞。為了能從客戶機往宿主機發送任意RPC報文,我們開發了一個獨立工具,該工具利用Backdoor函數,可以實現從客戶機往宿主機發送RPC報文。經過完整的逆向分析后,我們發現利用存在漏洞的這個函數,可以實現vmware-vmx.exe進程中的越界讀取及寫入目標。
3.1 越界讀取
根據前文分析,我們可以控制payloadSize字段。在發送報文時,如果我們使用了一個以非常大的payloadSize,同時又沒有分配payload緩沖區,那么當程序執行到memcpy()時,就會越界讀取其他一些內存數據。
如上圖所示,程序會拷貝從0x36E4D96到0x378A0D0之間0x500個字節長度的數據。然而,我們自己的數據在0x36E4DB7處的0x4C那就已經結束了,0x36E4DB7之后的數據會導致越界讀取漏洞。
3.2 越界寫入
如果RPC消息中包含多個報文,那么sub_1406215F0就會被調用。
為了在這個函數中實現越界寫入,我們需要在一個會話內發送多個RPC報文,然后vmware-vmx會創建一個新的緩沖區,將所有報文的載荷結合在一起。經過全面的逆向分析實驗后,我們最終發現,我們可以從客戶機往宿主機發送包含如下特征的RPC報文,實現越界寫入目標。
首先,我們需要發送帶有如下特征的一個拖放RPC報文:
1、packet->binarySize為0x10000。
2、packet->payloadOffset為0x0。
3、packet->payloadSize為0x500。
通過這些選項,我們就能通過前面所有的檢查條件,這些條件包括:
1、packetSize大于DND_CP_MSG_HEADERSIZE_V4。
2、packet->payloadSize小于0xFF64。
3、packet->binarySize小于0x400000。
4、packet->payloadOffset + packet->payloadSize < packet->binarySize。
程序將會創建一個新的緩沖區,將我們所有的報文載荷復制到緩沖區中。
接下來,我們需要發送另一個報文,該報文使用相同的會話ID,具體特征為:
1、packet->binarySize為0x10100。
2、packet->payloadOffset為0x500。
3、packet->payloadSize為0xFC00。
這些選項依然滿足過濾條件,這些條件包括:
1、packetSize大于DND_CP_MSG_HEADERSIZE_V4。
2、packet->payloadSize小于0xFF64。
3、packet->binarySize小于0x400000。
4、packet->payloadOffset + packet->payloadSize < packet->binarySize。
由于這個報文與第一個報文的會話ID相同,并且程序已經分配了一個新的緩沖區,因此程序會繼續將載荷數據復制到當前緩沖區中(因為0x500 + 0xFC00的值等于0x10100,不等于0x10000)。這樣就會導致程序越界寫入0x100字節大小的數據。
上圖顯示了vmware-vmx.exe進程在越界寫入之前的內存狀態。
上圖顯示了vmware-vmx.exe進程在越界寫入之后的內存狀態,其中0x40E3070處的內存為新的緩沖區尾部(0x10000)之后的內存。我們發送完第二個報文后,成功實現將0x100字節大小的數據覆蓋了位于0x40E3070處的內存數據。
四、總結
本文簡要介紹了VMware Workstation中的RPC機制,也分析了如何利用RPC中的漏洞實現從客戶機系統到宿主機系統的虛擬機逃逸。在之后的一系列文章中,我們將詳細分析漏洞利用的每個步驟,并向大家演示如何組合這些漏洞,在VMware中實現完整的虛擬機逃逸。
根據 Marvel Team 掌門人唐青昊對雷鋒網的介紹,這個漏洞的危害非常巨大,可以使得黑客從虛擬機中“逃逸”到宿主機,從而利用宿主機的權限,查看、修改所有運行其上的虛擬機信息。
而就在今天,VMware 為旗下所有受此漏洞影響的軟件都推出了最新的版本更新,并且公布了這個漏洞的編號:CVE-2016-7461,還專門鳴謝了來自 360 Marval Team 的唐青昊和應鑫磊以及韓國神童 Lokihardt。
【VMware 官方網站漏洞詳情中的致謝聲明】
說到這個漏洞,還有個有趣的故事。
在 PwnFest 比賽現場,VMware 正是主辦方的破解目標之一。主辦方為能破解 Workstation 的黑客提供了高達 15 萬美元的獎金。而規則規定如果多位選手參加破解,則抽簽決定順序。如果兩組選手恰好使用同樣的漏洞,俗稱“撞洞”,則獎金歸屬第一組破解選手。
而在這次比賽上,恰好出現了這種情況。
【唐青昊(圖右)和應鑫磊(圖左)在 PwnFest 現場成功破解 VMware Workstation】
來自 360 的 Marvel Team 抽簽首先出場,成功破解;而來自韓國的顏值逆天的黑客神童 Lokihardt 同樣破解成功。然而,VMware 工程師經過確認,兩組黑客恰恰使用的同樣的漏洞。根據規則,獎金應該由 Marvel Team 獲得。
然而根據雷鋒網了解到的消息,韓國神童從 VMware 工程師口中得知自己和剛剛完成比賽的 360“撞洞”,表示了些許遺憾,然后在鍵盤上輕輕敲了一會兒,詢問工程師:“我更換了一種漏洞利用的方式,你們看如何?”
工程師們驚愕地發現,僅僅幾十秒時間,神童就更改出了一種完全不同的對于漏洞的利用方法。這樣的利用方法同樣給 VMware 在產品安全方面有很大的啟示。于是現場決定兩組黑客都可以得到15萬美金的獎勵。
撞洞在所難免,而現場改代碼力挽狂瀾,卻讓人驚嘆。(撞洞之后現場改代碼還長得這么帥,可能才是最讓人驚嘆的地方。)
對于神童的逆天表現,Marvel Team 掌門人唐青昊也表達了欽佩之意。這其中的難度,也許只有黑客才能更深地理解。
【韓國神童 Lokihardt(圖左一)在現場破解 VMware Workstation】
韓國神童的表現可圈可點,但 VMware 對于漏洞的響應速度同樣可圈可點。
在比賽之前,唐青昊曾經預測:VMware 這樣的傳統軟件廠商修復這個漏洞可能需要兩個月。而實際上,從漏洞被黑客提交,到 VMware 推出全線產品補丁,只用了五天時間。
唐青昊對雷鋒網說:
在 PwnFest 上被破解的軟件廠商中,VMware 修復漏洞的效率是最好的。修復漏洞的速度,甚至超過了谷歌和蘋果。
從這一點上來看,VMware對于自身軟件安全的重視,值得點贊。
不過,唐青昊告訴雷鋒網,他和 Marvel Team 還在繼續尋找 VMware 各個產品的漏洞,在云計算越來越普及的今天,虛擬化軟件的安全關乎銀行、政府、大型企業的信息安全,重要性難以想象。
不知道 VMware 的童鞋們是否準備好,修復自己的下一個漏洞了呢?
最后,應迷妹要求,再欣賞一下 Lokihardt 的帥照。