記一次VMware的崩潰調試分析過程

發布時間 2020-08-11

1.研究背景


VMware Workstation是一款主流的虛擬機軟件,近期啟明星辰ADLab安全研究員在使用VMware虛擬機的過程中遇到虛擬機異常崩潰的問題,當從7zip中直接將文件拖拽到VMware虛擬機中,會造成虛擬機異常關閉。目前已測試過VMware 15.5.0、15.5.2、15.5.5 以及7zip 19.0、20.02等版本。本文將通過對VMware和7zip程序進行跟蹤分析,最終定位虛擬機異常關閉原因。

2.VMware端調試分析

使用WinDbg-I指令將WinDbg設置為即時調試器,VMware-vmx.exe程序崩潰后自動彈出WinDbg。堆棧信息如下:



調試信息顯示stack buffer overrun異常,最初推斷可能是緩沖區溢出漏洞。



通過查詢資料后發現,從Windows 8開始,Windows設計了一個新的中斷INT 29H,用以快速拋出失敗,在sdk中被聲明為__fastfail, __fastfail內部函數不會返回。


體系結構
指令
代碼參數的位置
x86
int 0x29
ecx
x64
int 0x29
rcx
ARM
操作碼 0xDEFB
r0


在上圖中,程序終止于int 29h,而它的參數為0xa,對應FAST_FAIL_GUARD_ICALL_CHECK_FAILURE,由此推斷問題可能出現在CFG的檢查過程中。



從函數調用棧中vmware_vmx+0x58b21地址向上追溯,動態調試程序,比較程序正常運行與異常崩潰的函數調用區別,定位到與程序崩潰相關的函數sub_1400965A0。


使用Windbg Attach vmware-vmx.exe程序,在sub_1400965A0函數設置斷點,開始動態調試。從7z打開的壓縮文件中拖拽cdp.pcapng的文件,程序在斷點處停下。通過動態調試可知該函數中calloc分配了三個堆空間,分別用于存放:主機臨時文件路徑temp_path、目標文件名file_name以及VMware中的緩存目錄名vm_cache_dir_name。



但是打開主機Temp目錄下卻沒有發現該文件,于是初步斷定這是程序崩潰原因。繼續往下看,3個文件相關參數全都傳入了sub_140579b30函數。



進入函數sub_140579b30,定位temp_path參數的處理。其中,sub_14057FF90函數對傳入的temp_path進行了逐一遍歷,sub_1405B2080函數對傳入的temp_path進行了非法性檢查。下面重點分析sub_140576460函數。



sub_140576460函數將路徑參數temp_path傳入了sub_14049DA50。



首先,函數sub_14049DA50通過sub_140477C70對字符串進行了處理。然后,調用wstat64獲取相應路徑的文件狀態,如果成功獲取則保存到一個結構體中,否則返回0xffffffff。由于Temp目錄下并未發現備份文件,導致獲取狀態失敗,從而返回0xffffffff。



返回0xffffffff后,重新回到sub_140579b30函數中,程序跳出while循環到達如下位置,輸出錯誤信息并跳轉至sub_140572A70。



從sub_140572A70最終執行到sub_1400960C0,到達如下位置將vmware_vmx+0xb1ed90處的值賦給了rsi,即為0。



繼續往下執行,將rsi中0值賦值到rax中,然后調用0x7ff8fab0c510處,即ntdll!LdrpDispatchUserCallTarget。



此處與靜態下的過程有一點不同,靜態下該處調用如下:



如果按照靜態過程執行,應當到達sub_1407C7650,即如下位置:


在ntdll.dll被加載之前,該處數據依舊為上圖所示地址:



后來在ntdll.dll中實施CFG(ControlFlowGuard)保護機制,將vmware_vmx+0x7c9668地址處數據進行了改寫,從而執行到ntdll!LdrpDispatchUserCallTarget中。



在ntdll!LdrpDispatchUserCallTarget函數中,取r11+r10*8處的值賦值給r11時出現了問題,該地址為空,就造成了空指針引用,從而執行了int 29h,造成異常。然而,即使沒有CFG機制,程序也會在執行“jmp rax”處崩潰,通過下圖可以看出,CFG機制僅僅是在原本程序跳轉指令前添加了一些檢查。



至此,VMware崩潰的原因基本分析清楚了。另一個疑問是,為什么7zip已經在系統Temp下生成了文件,并且VMware也已經獲取到了路徑參數,卻在移動前自動刪除了文件呢。這就需要從7zip中尋找答案。


3.7zip端調試分析

由上一節分析可知,Vmware crash原因是Temp目錄下文件被刪除。閱讀7zip源碼,鎖定了CPP/Windows/FileDir.cpp中的文件刪除函數。



使用WinDbg加載7zip,然后在Remove函數位置進行下斷,程序運行后進行拖拽操作,在Remove函數中斷后對應的調用堆棧如下所示。



堆棧中7zFM+0x5b212地址位于函數CPanel::OnDrag中,該函數為鼠標拖拽操作函數。當檢測到對7zip打開的目錄進行操作時,便會在Temp目錄下生成一個以7zE開頭的隨機命名文件夾。



然后,將該文件夾設置為目標目錄,并且設置了一些數據及IpDropSourse結構體。



繼續往下可以看到一個DoDragDrop函數,該函數功能是進行OLE拖放相關操作,通過檢測光標的行為分別調用一些方法并返回對應的數值。



然后,根據DoDragDrop函數的返回值來判斷光標的拖拽是否有效,從而執行對應的操作。



從7zip中拖拽文件到虛擬機,由于無法獲知文件拖拽的目標路徑,因此DoDragDrop會返回DRAGDROP_S_CANCEL(0x40101),不會執行拷貝操作的分支,而是直接將Temp目錄下生成的臨時目錄刪除。



4.小 結


7zip壓縮包中文件拖拽操作會觸發DoDragDrop函數調用,該函數會獲取文件數據及光標停止的位置。但是將文件拖拽到VMware窗口時,DoDragDrop函數不能獲取準確的目標路徑,因此無法將文件拷貝到目標位置,從而直接刪除臨時文件,最終導致VMware無法獲取文件狀態造成崩潰。


參考鏈接:

[1]https://0cch.com/2016/12/13/int29h/

[2]https://docs.microsoft.com/en-us/windows/win32/api/ole2/nf-ole2-dodragdrop

[3]https://github.com/kornelski/7z/tree/20e38032e62bd6bb3a176d51bce0558b16dd51e2



啟明星辰積極防御實驗室(ADLab)


ADLab成立于1999年,是中國安全行業最早成立的攻防技術研究實驗室之一,微軟MAPP計劃核心成員,“黑雀攻擊”概念首推者。截止目前,ADLab已通過CVE累計發布安全漏洞近1100個,通過 CNVD/CNNVD累計發布安全漏洞900余個,持續保持國際網絡安全領域一流水準。實驗室研究方向涵蓋操作系統與應用系統安全研究、移動智能終端安全研究、物聯網智能設備安全研究、Web安全研究、工控系統安全研究、云安全研究。研究成果應用于產品核心技術研究、國家重點科技項目攻關、專業安全服務等。


lab.jpg