翻譯:myswsun
預估稿費:170RMB
投稿方式:發送郵件至linwei#360.cn,或登陸網頁版在線投稿
0x00 前言
本文是2016年7月一些研究的結果,但是直到現在才能發布。在6月,Theori發布了一篇博文關于IE的漏洞MS16-063,他們寫的利用是針對Windows7上IE 11版本,并且他們認為因為Windows 10 的CFG機制無法在Windows 10利用。本文描述了我如何在Windows 10利用,并繞過CFG,事實我還發現了另一種方法,會在將來發布。
0x01 理解CFG
控制流保護(CFG)是微軟在Windows 8.1 update 3和Windows 10中實現的緩解措施,用來保護匯編級別的非直接調用。趨勢已經公布了Windows 10上面關于CFG的很好的分析文章。已經有集中公布的繞過CFG的方法,但是這些方法主要的目標是CFG實現算法,但是我想從這個功能的弱點入手。因為Theori在他們博文中寫的Windows 7上面的利用因為CFG的存在無法有效工作,讓我們看下為什么并試圖繞過它。
來自Theori的利用代碼在Windows 10的IE中直接覆蓋了虛函數表。因此問題是我們如何利用任意讀寫來繞過CFG。根據趨勢的研究,CFG被函數LdrValidateUserCallTarget調用來驗證一個函數的調用是否用了非直接調用:
加載到EDX中的指針是驗證位圖的基本指針,在這種情況下是:
然后,被驗證的函數將其地址加載到ECX中,如果kernel32!VirtualProtectStub作為示例,則在這種情況下的地址是:
然后地址右移8位,用于裝入保存該地址有效位的DWORD值,在這種情況下:
然后函數地址右移3位,并執行位測試,這本質上對位移地址進行模數0x20操作,然后是驗證位圖的DWORD中檢查的位,因此在這種情況下:
因此相關位在偏移0x14處:
這意味著它是可靠的。因此VirtualProtect的調用地址是可靠的,然而這沒有真的解決問題,它的參數也必須由攻擊者提供。正常情況應該是用ROP鏈,但是任何不是從函數開始的字節都是無效的。因此解決方案是找到一個函數在被調用的地方的參數是可以控制的,并且函數的功能可以給攻擊者利用。這需要在利用中非常仔細。
0x02 在Windows 10中利用
在Theori提供的利用,代碼是通過stack pivot小配件覆蓋TypedArray的虛函數表,因此這個沒有其他可能了,研究TypedArray提供的函數是值得的,發現下面兩個函數比較有用:
他們的偏移是0x7c和0x188,他們能從javascript代碼中直接調用,并且HasItem有個可以控制的參數,同時Subarray有兩個用戶可控制的參數。然而問題是它們都不返回除布爾值之外的任何數據。此外,所選擇的函數必須采用相同數量的參數,否則堆棧不平衡將會引發異常。我搜索的API應該暴露一個指針能用來覆蓋返回地址,以便可以繞過CFG。
我定位的可用的API是RtlCaptureContext,由kernel32.dll、kernelbase.dll和ntdll.dll導出,這個API有一個指向CONTEXT結構的參數:
CONTEXT結構儲存了轉儲的所有的寄存器(包括ESP),而且輸入值僅僅是一個緩沖區的指針。看一下TypedArray對象的內存布局:
第一個DWORD值是虛函數表指針,能夠被覆蓋創建一個假的虛函數表,在偏移0x7c處存儲API RtlCaptureContext的地址,同時偏移0x20是TypedArray指向的真實數據的指針:
因為泄漏這個緩沖區的地址也是可能的,它能提供RtlCaptureContext的參數。為了完成夾的虛函數表,不得不創建一個指針指向偏移0x7c處的ntdll!RtlCaptureContext,這意味著泄露了RtlCaptureContext的地址,繼而意味這泄露了ntdll.dll的地址。執行此操作的默認路徑是使用vtable的地址,它是一個指向jscript9.dll的指針:
從這個指針往回0x1000個字節,搜索MZ頭,繼而查找到指向kernelbase.dll的導入表。做同樣的操作能偶獲得kernelbase.dll的基址,然后再獲得ntdll.dll的導入表指針并再次獲得其基址,然后從導出函數中找到RtlCaptureContext。盡管這個方法是可靠的但是有個缺陷,如果在系統中裝了EMET,將觸發來自jscript9.dll的代碼的崩潰,因為從PE頭或導出表讀取數據不被允許,為了繞過EMET我使用了一個不同的技術。記住每一個非直接調用都被CFG保護,因為jscript9.dll的函數被CFG保護了,所以不能調用直接指向ntdll的函數。一個在虛表中偏移0x10的函數如下:
用原始讀操作,指向ntdll.dll的指針能通過以下函數找到:
通過ntdll.dll的指針得到RtlCaptureContext的地址,不通過讀取導出表而是使用搜索特征和哈希找到并讀取。RtlCaptureContext看起來如下:
前0x30字節總是相同的并且很特殊,因此可以用哈希碰撞找到函數地址:
函數可以使用指向ntdll.dll的指針作為參數。
把上面的都整合到一起:
從這偏移0x200包含了RtlCaptureContext的結果,看起來如下:
從上面可以清楚地看出堆棧指針已經泄漏,現在找到一個能控制執行的地址是個問題。看下棧頂顯示:
那就是當前函數的返回地址,這個地址位于與RtlCaptureContext信息中的偏移0x9C處的泄漏指針相距0x40字節的偏移處。運氣好,這個偏移對于其他簡單函數將是相同的,所以應該可以寫入并使其覆蓋其自己的返回地址,從而繞過CFG。
利用補充如下:
運行時顯示EIP控制:
而且,在偏移0x40和0x44的寫入現在位于棧頂,允許創建一個stack pivot和ROP鏈,一種方法是用POP EAX接著XCHG EAX,ESP。
0x03 微軟緩解措施
Microsoft已經聲明,堆棧上的損壞返回地來繞過CFG是一個已知的設計限制,因此無法修復或領取任何種類的賞金,如下所示:
正如那個所說,微軟做了兩個事情來緩解這個技術,首先在未來的Windows 10版本中,RFG將被實現,阻止堆棧損壞以給予執行控制的方式。另一個是在Windows 10的周年版發布中引入敏感的API的介紹,它僅保護微軟Edge,但是上述情況無法保護,但是他能阻止微軟Edge中的RtlCaptureContext。Poc代碼可以在這找到:https://github.com/MortenSchenk/RtlCaptureContext-CFG-Bypass。
Win10企業版和LTSC分支Win10企業版的區別;
1、Win10企業版LTSB分支不會有Edge瀏覽器
2、在系統更新方面,用戶能完全手動控制更新,選擇和決定自己要的更新和驅動,更新內容和更新時間可以隨意控制,但不能無限期推遲。
3、無Cortana
4、無任何系統自帶磁貼程序
5、無應用商店
如果要此鏡像,可以去MSDN我告訴你網站下載,怎么下載前幾篇教程有介紹。
在此處可能會停留幾分鐘
桌面空白處右鍵
選擇左邊主題,打開桌面圖標設置
依次打開計算機、用戶文件、控制面板的快捷方式