王 燁 李清寶 曾光裕 陳志鋒
(解放軍信息工程大學 鄭州 450001) (數學工程與先進計算國家重點實驗室(解放軍信息工程大學) 鄭州 450001) (daguoli415@163.com)
?
基于代碼防泄漏的代碼復用攻擊防御技術
王 燁 李清寶 曾光裕 陳志鋒
(解放軍信息工程大學 鄭州 450001) (數學工程與先進計算國家重點實驗室(解放軍信息工程大學) 鄭州 450001) (daguoli415@163.com)
隨著地址空間布局隨機化被廣泛部署于操作系統上,傳統的代碼復用攻擊受到了較好的抑制.但新型的代碼復用攻擊能通過信息泄露分析程序的內存布局而繞過地址空間布局隨機化(address space layout randomization, ASLR),對程序安全造成了嚴重威脅.通過分析傳統代碼復用攻擊和新型代碼復用攻擊的攻擊本質,提出一種基于代碼防泄漏的代碼復用攻擊防御方法VXnR,并在Bitvisor虛擬化平臺上實現了VXnR,該方法通過將目標進程的代碼頁設置可執行不可讀(Execute-no-Read, XnR),使代碼可以被處理器正常執行,但在讀操作時根據被讀物理頁面的存儲內容對讀操作進行訪問控制,從而阻止攻擊者利用信息泄露漏洞惡意讀進程代碼頁的方法搜索gadgets,實驗結果表明:該方法既能防御傳統的代碼復用攻擊,還能夠防御新型的代碼復用攻擊,且性能開銷在52.1%以內.
地址空間布局隨機化;代碼復用攻擊;程序安全;信息泄露;虛擬化
近年來,計算機軟件經歷著一場漏洞利用攻擊與防御惡意攻擊行為之間的對抗.越來越多的攻擊方法被發現,其中代碼復用攻擊(code reuse attack,CRA)正成為安全領域研究的熱點,如return-into-libc[1],ROP(return-oriented programming)[2-5],JOP(jump-oriented programming)[6-8]和SROP(sigreturn-oriented programming)[9]等.代碼復用攻擊是一種新型的攻擊技術,與傳統的惡意代碼攻擊不同,代碼復用攻擊不需要引入額外的惡意代碼,僅使用程序已有的代碼便能實施惡意攻擊,使得數據執行保護(data execution protection, DEP)[4]和棧溢出保護(stack smashing protection, SSP)[10]等防御機制失效.
為了有效檢測和防御代碼復用攻擊,研究人員提出了多種檢測方法和防御技術,其中應用最廣泛的方法是ASLR[11].傳統的ASLR機制通過隨機化代碼段的基地址使得攻擊者無法預知代碼在內存中的具體位置,從而阻止代碼復用攻擊.由于這種傳統的ASLR只是改變了整個代碼段的基地址,一旦泄漏一個指針值就可以通過它們的相對偏移發現所有gadget的地址.為了阻止攻擊者獲取所需gadgets的有效地址,一些更復雜的隨機化技術被研究提出,主要分為細粒度隨機化和加載時隨機化2類.細粒度隨機化通過將隨機化的基本塊粒度細化到函數級和指令級,Pappas等人[12]就提出了一種in-place代碼隨機化技術,通過指令重排列、等價指令替換和寄存器重賦值等方法阻止ROP攻擊;加載時隨機化技術主要是通過在程序加載時進行地址隨機化處理,文獻[13]分析了Vista中的ASLR機制,如果可執行文件被打上了ASLR標記,進程的代碼段基地址、棧基地址、堆基地址和PEB(process environment block)的位置等都在進程加載時被隨機化.這類ASLR機制對系統的性能消耗較小,且能有效阻止攻擊者使用預先計算的gadget鏈完成事先設計的攻擊.
為了繞過上述ASLR機制,Snow等人[14]提出just-in-time代碼復用攻擊技術(下面簡稱JIT-ROP,即時代碼復用攻擊),該攻擊技術是在腳本環境下通過一個內存泄漏漏洞在線獲取程序的內存布局,在收集到的內存頁中動態搜索API函數和gadgets,完成payload構造,利用payload即時編譯攻擊代碼,完成代碼復用攻擊.JIT-ROP攻擊是一種動態計算構造gadgets鏈的攻擊方法,可以繞過現有的防御機制,是當前最復雜的攻擊技術之一.
由于JIT-ROP攻擊需要利用一個信息泄漏后門讀取任意內存位置內容搜索gadgets,通過強制可執行代碼不可被讀或者被反匯編,可以避免內存中可執行代碼信息泄漏的風險,阻止攻擊者在線構造gadgets鏈.根據上述思想,Backes等人[15]設計完成了XnR系統.XnR只允許代碼可以被處理器取指令操作訪問和執行,但不能以讀數據方式被訪問,由此可知XnR能阻止針對可執行代碼的內存泄漏攻擊和JIT-ROP攻擊.但該方法只能阻止未映射到內存的代碼頁被非法訪問,攻擊者可以通過在內存中的代碼頁進行漏洞利用搜索gadgets,從而繞過保護機制發動JIT-ROP攻擊.
為了有效防御代碼復用攻擊,本文借鑒W⊕X和XnR的設計思路,提出了一種基于代碼防泄漏的代碼復用攻擊防御方法VXnR.該方法利用內存虛擬化技術,在虛擬層實現對可疑漏洞程序的內存代碼頁添加Execute-no-Read保護屬性,使得進程的代碼頁可以被CPU取指執行但不能被讀操作訪問,攻擊者無法通過內存泄漏獲取到漏洞進程的代碼頁信息,這種保護機制大大降低了攻擊者繞過防御機制的可能性.實現VXnR需要解決的挑戰性技術問題:
1) 無法直接區分對內存的合法的數據訪問和對代碼的讀行為.雖然HideM[16]通過分立式TLB結構ITLB和DTLB區分對數據和指令代碼的訪問操作,而目前的處理器已經升級為統一式TLB結構,HideM方法需要依賴硬件結構,不具有普適性.
2) 具有不可讀但可執行訪問權限的內存并不存在.可執行權限意味著必須可讀,無法直接對可執行代碼頁設置“可執行不可讀”權限.XnR通過修改頁錯誤處理函數和請求頁面處理函數,限制內存中進程虛擬頁面頁數,在觸發缺頁異常時對訪問操作進行判斷,根據判斷結果來限制對代碼頁的讀行為,該方法只能對不在內存的虛擬頁訪問控制,攻擊者可以利用在內存的虛擬頁繞過缺頁異常處理函數,進行代碼復用攻擊.
針對代碼復用攻擊的防御需求及面臨的技術挑戰,本文主要貢獻如下:
1) 提出了一種基于代碼防泄漏的代碼復用攻擊防御方法VXnR.該方法通過阻止對進程代碼非法讀訪問,使攻擊者無法搜索構造gadget,實現了對新型代碼復用攻擊的防御.相比現有的防御方法的優勢體現在:①無需修改客戶操作系統;②避免客戶操作系統旁路甚至破壞代碼復用防御系統,解決了VXnR的安全性問題;③性能開銷較小,可靠性高.
2) 針對主要技術挑戰,提出了2項解決方法:基于缺頁異常的內存訪問操作識別、基于硬件輔助頁面映射機制的XnR權限修改.2項技術均在虛擬機監控層實現,對上層操作系統透明,同時具有更高的安全性,即使客戶操作系統內核被攻破也不影響底層安全機制.
3) 在一種虛擬化平臺Bitvisor上實現了VXnR原型系統,并使用代碼復用攻擊測試程序評估了VXnR的有效性和性能.實驗表明VXnR在保護客戶操作系統中的目標進程,防御代碼復用攻擊的同時,僅帶來了不超過52.1%的運行時開銷.
傳統的代碼復用攻擊利用逆向工程工具靜態分析目標可執行程序,通過搜索算法尋找以ret,jmp和call等轉移指令結尾的短指令序列gadgets,鏈接這些指令序列構造payload,并將其地址以及指令序列需要的數據布置在堆棧中,當目標程序執行時通過一個程序漏洞將控制流導向堆棧中的payload,進行代碼復用攻擊.
隨著ASLR思想的提出,程序執行的指令和代碼在內存中的位置都被改變,靜態分析搜索到的gadgets地址并不可用,限制了傳統的代碼復用攻擊.為了繞過該防御機制,新型的代碼復用攻擊利用內存泄漏漏洞使攻擊者在程序運行時可以動態獲取內存布局,讀取被隨機化后的gadget的真實地址,成功利用程序已有代碼完成攻擊.
綜上,隨著有效防御機制的發展,傳統的代碼復用攻擊受到了一定的抑制,但新型的代碼復用攻擊仍然不斷涌現.一種新型的代碼復用攻擊一般分為2個階段:1)需要針對具有某個漏洞的目標程序進行信息泄露以獲取到該程序的內存分布;2)進行實際的漏洞利用并發動代碼復用攻擊.結合細粒度的地址空間布局隨機化機制,本文提出的防御方法旨在第1步阻止代碼復用攻擊,保護目標程序的內存布局,使攻擊者無法搜索讀取目標程序的可執行代碼,防御攻擊者利用目標程序已有代碼進行代碼復用攻擊.
1.1 總體架構
若將代碼復用攻擊防御程序設置于內核中,那么一旦內核遭到破壞,防御程序就有可能被攻擊者禁用,從而被繞過.因此,我們引入虛擬機架構,并將防御程序放置于Hypervisor中,這種機制大大降低了攻擊者繞過防御系統的可能性.防御架構如圖1所示:

Fig. 1 System architecture of VXnR.圖1 VXnR系統架構
從圖1中可知,系統架構由進程檢測模塊process detector和在線保護代碼頁模塊runtime protect兩部分組成,分別對應檢測漏洞進程加載階段和在線保護階段.檢測漏洞進程加載階段通過Hypervisor中的進程檢測模塊檢測目標進程的加載運行.當目標進程processT在用戶層加載時,進程檢測模塊會檢測到目標進程的運行,并通知在線保護代碼頁模塊對進程processT執行在線保護.在線保護代碼頁模塊接收到進程檢測模塊的消息后,系統進入在線保護階段,目標進程對物理內存的訪問操作都需要經過在線保護代碼頁模塊,而未被保護進程對內存的訪問不需要通過在線保護代碼頁模塊.利用虛擬化內存管理技術,對目標進程processT的內存頁執行Execute-no-Read保護.當處理器訪問目標進程代碼頁進行取指令執行代碼(fetch)時,該操作通過在線保護驗證;當處理器執行讀(read)操作訪問目標進程代碼頁時,在線保護代碼頁模塊認為該操作為非法操作并拒絕服務.本系統實現需要的關鍵技術主要有2個:1)需要定位到目標進程代碼段在內存中的位置,并設置目標進程代碼頁的訪問權限為只可執行不可讀;2)在線保護代碼頁模塊需要區分2個內存訪問操作,即合法的數據訪問和對代碼的讀行為.
1.2 基于缺頁異常的內存訪問操作識別
本文將內存訪問操作分為3種:取指令(instr-uction fetch)、讀數據(read data)和讀代碼(read code).取指令操作表示處理器從內存取一個字節,譯碼執行指令,這是代碼執行時發生的合法操作;讀數據操作表示指令執行訪問內存數據的行為,這里的數據不包含代碼,這是程序運行時發生的合法操作;讀代碼操作表示指令執行訪問內存數據的行為,這里的數據僅指代碼,這是信息泄露的可疑行為,所以認為是非法的操作.

Fig. 3 Memory access operations identification method based on page fault violation.圖3 基于缺頁異常的內存訪問操作識別方法
為了發現非法的讀代碼行為,首先需要攔截對內存的訪問操作,然后判斷該訪問操作類型.在虛擬層,攔截對內存的訪問操作可以通過監控與內存訪問操作行為相關的指令,包括read,load和store等,修改編譯器對相關指令靜態插樁或者利用動態插樁工具在程序運行過程中動態插樁,當程序執行與內存訪問操作相關的指令時觸發異常,陷入虛擬機監控器.但是靜態插樁需要程序的源碼,動態插樁對系統的性能開銷較大,而且與內存訪問操作行為相關的指令種類較多,因此,該方法有一定局限性且可行性較差.
利用操作系統虛擬內存管理機制,本文提出基于缺頁異常的內存訪問操作識別方法.新建進程的虛擬地址空間是按寫時復制方式從創建者進程中復制,屬于共享的虛擬地址空間,在進程剛加載完新程序之后,它的虛擬地址空間幾乎是空的.而加載操作僅在虛擬地址空間與可執行文件之間建立了映射關系,并未真正將文件的內容讀入內存.在虛擬機監控器架構下,客戶機的訪存操作需要利用硬件輔助頁面映射(hardware assisted paging, HAP)頁表項進行地址轉換,HAP是基于硬件虛擬化實現虛擬機物理地址空間隔離的頁表映射機制,不同的硬件廠商提供特定平臺的HAP機制,如Intel處理器的EPT機制和AMD處理器的NPT機制.圖2為EPT機制下客戶操作系統訪存過程,其實現原理和x86架構下的分頁機制是一致的,通過客戶機虛擬地址到客戶機物理地址(guest-physical address, GPA)和客戶機物理地址到宿主機物理地址(host-physical address, HPA)兩次地址映射轉換來支持地址空間的虛擬化.由于新加載的進程并未建立HAP映射將可執行文件的內容讀入內存,進程對虛擬地址空間的讀、寫、執行操作都會觸發HAP異常.HAP異常事件相關信息會存儲在exit qualifica-tion字段中,這些信息包括觸發異常的操作類型(例如取指令操作、讀數據和寫數據操作),該物理頁的HAP權限和引起異常的客戶物理地址.因此,新加載目標進程初始運行時由于請求頁面引起缺頁異常事件,通過分析觸發異常事件的相關信息可以判斷該訪存操作類型.

Fig. 2 Access process in guest OS with EPT mechanism.圖2 EPT機制下guest OS 訪存過程
圖3以x86下Linux操作系統為例,Linux內核采用Copy on Write機制,在請求頁面時觸發EPT violation,進入do ept violation異常處理函數對異常事件進行分析,在exit qualification字段尋找引起VM-exit的明細信息.其中bits0,bit1,bit2指示產生EPT violation時對GPA進行哪些訪問:當bit0=1時,表示正在對GPA進行讀訪問;當bit1=1時,表示正在對GPA進行寫訪問;當bit2=1時,表示正在嘗試執行GPA地址上的指令(fetch指令).通過分析exit qualification字段的bits0,bit1,bit2位的值,可以得到觸發EPT violation的訪問操作類型.當bit2=1時,CPU執行instruction fetch指令訪問該物理頁面,由于進程初始運行階段并未建立EPT映射,虛擬頁面不在內存中從而觸發EPT異常,因此,認為該GPA通過EPT映射的物理頁存儲的是進程的可執行代碼段信息,所以記錄該GPA并標記為代碼頁,然后建立EPT映射項將虛擬頁映射到物理內存.當bit0=1或bit1=1時,CPU執行readwrite指令訪問物理頁面,由于進程初始運行階段未建立EPT映射,虛擬頁面不在內存中從而觸發EPT異常,因此,認為該GPA通過EPT映射后的物理頁存儲的是進程的數據信息,所以標記該物理頁面為數據頁,然后建立EPT映射項將虛擬頁映射到物理內存.

Fig. 5 Set XnR permission on the process code page.圖5 對進程代碼頁設置XnR權限
1.3 基于硬件輔助頁面映射機制的XnR權限修改
在進程初始運行時,利用基于缺頁異常的內存訪問操作識別的方法可以實現對進程代碼頁的定位收集,為了阻止非法的讀代碼行為,還需要將目標進程的代碼頁保護起來.
一種方法是通過在內核層修改缺頁處理函數實現對進程代碼頁設置XnR權限,該方法通過只保留N個代碼頁存在內存中,程序運行時對其它代碼頁的訪問操作都將觸發缺頁異常,在缺頁異常處理函數中處理該異常事件,被修改的缺頁異常處理函數會判斷觸發異常的訪問操作類型,當取指令操作觸發異常時,缺頁異常處理函數建立相應映射項允許訪問并將內存中已有的一個代碼頁移除,從而保證內存中只保留程序的N個代碼頁;當讀寫操作觸發異常時,缺頁處理函數判斷該物理頁面是否為代碼頁,若是代碼頁則拒絕服務,若是數據頁則建立相應映射項允許訪問.該方法可限制映射到內存的程序代碼頁數量為N,程序運行到未映射的代碼頁即會觸發缺頁異常,當程序運行連續跳轉到未映射代碼頁時會頻繁觸發缺頁異常,嚴重影響程序的運行效率,而且攻擊者也可以利用已映射到內存的N個代碼頁搜索gadgets從而繞過該保護機制.
為解決上述問題,利用內存虛擬化技術,本文提出基于硬件輔助頁面映射機制的XnR權限修改的解決辦法.和傳統內存管理類似,HAP使用頁表入口設置權限管理物理內存.但HAP支持讀權限和present(虛擬頁在內存)狀態的分立.如圖4所示,傳統的x86頁表第0位控制present狀態和讀權限,當頁面為non-present且不可讀時,第0位bit-0(P)被清零,因此,present的頁面總是可讀的.但HAP是通過將第0位bit-0(R)、第1位bit-1(W)和第2位bit-2(E)全清零代表頁面non-present(虛擬頁不在內存).所以,只要將HAP入口第2位設置為1并將第0位和第1位清零,就可以實現對該頁面設置 “可執行不可讀”權限.

Fig. 4 Page-table entry permission bits for x86PAE and HAP.圖4 x86PAE和HAP的頁表入口權限位
4K頁面下EPT頁表結構由PML4T(page map level 4 table),PDPT(page-directory-pointer table),PD(page-directory)和PT(page table)共4級頁表構成,如圖5所示,GPA被分割為5個部分,頂層頁表PML4T的物理地址由擴展頁表指針(extended page table pointer, EPTP)字段提供,一級一級地往下查找,直到找到PTE,最后加上偏移值offset即可獲得真實的HPA,根據已定位的程序物理頁信息,查看該HPA所在物理頁面的標記.若為代碼頁,則設置該HAP頁表入口權限為可執行不可讀;若為數據頁,則默認該HAP頁表入口權限的初始值,不對其修改.因此,程序在訪問該HPA上的內容前,VXnR會檢查該物理頁面的訪問權限,在檢查通過后允許訪問.當程序執行讀操作訪問可執行不可讀頁時觸發異常,VXnR對異常事件進行分析處理,當發生讀寫操作異常時繼續分析該頁面內容,若該頁面被標記為可執行不可讀頁則拒絕該非法操作訪問,若該頁面為可讀可寫頁則允許訪問.
本文實現的VXnR采用x86架構的CPU,而且CPU需要支持虛擬化技術,目前大多數處理器都能滿足該要求,主機操作系統采用Ubuntu 12.04,且配置ASLR機制,使用gcc編譯器進行開發,虛擬機監視器使用Bitvisor.VXnR的實現主要分為對進程檢測模塊和在線保護代碼頁模塊2個模塊的實現.
2.1 進程檢測模塊
采用Ether[17]中提出的系統調用截獲技術,當截獲到execve系統調用,進程檢測模塊在VMM中監控CR3控制寄存器的更新來識別客戶機操作系統的當前進程,由于新進程創建可能會重用之前撤銷的進程頁目錄基地址,同時考慮頂層頁表中第1有效項從而創建唯一的標識符.當發現新進程為目標進程時,立即向在線保護代碼頁模塊發送消息,使系統進入在線保護代碼頁階段.
2.2 在線保護代碼頁模塊
實現在線保護代碼頁模塊的關鍵技術難點主要有2個:1)在目標進程加載完初始運行時定位該進程代碼頁;2)對目標進程代碼頁設置XnR訪問權限.通過基于缺頁異常的內存訪問操作識別的方法,在目標進程初始運行中實現對其代碼頁定位收集,并將該GPA與已記錄的代碼頁GPA進行匹配.若沒有匹配項,認為該代碼頁為第1次請求頁面映射到物理內存,則將該GPA添加到記錄中并標記為代碼頁;若存在匹配項,說明該代碼頁已經收集到記錄中.然后利用基于硬件輔助頁面映射機制的XnR權限修改的方法,針對定位到的代碼頁建立EPT映射將虛擬頁映射到物理內存,并修改該EPT頁表入口權限位,根據圖6所示的PTE頁表項結構圖,對PTE頁表項的后3位修改為100來設置對應頁面的可執行不可讀權限.當存在讀(read)該代碼頁操作時,由于訪問權限不夠觸發EPT violation,此時系統認為存在非法的讀取代碼行為,報警存在利用目標進程進行內存泄漏,阻止代碼復用攻擊.

Fig. 6 The structure of PTE.圖6 PTE結構圖
本節從有效性和性能2個方面對VXnR進行測試.有效性測試用于驗證VXnR能否實現代碼復用攻擊防御;性能測試用于驗證VXnR的效率和開銷.實驗環境如下:主機CPU為Intel?CoreTMi7-4790 @ 3.60 GHz,內存為16 GB;Hypervisor采用Bitvisor,其版本為1.4.0,Guest OS采用的是3.2.0-x86_32內核的Ubuntu 12.04.
3.1 有效性測試
為了測試VXnR的有效性,我們構造了一個具有棧溢出漏洞和內存泄漏漏洞的目標程序,選擇了文獻[2,5-7,14,18-22]實現的ROP 作為測試用例,并對其進行修改使其能夠運行在32位3.2.0-x86內核的Ubuntu 12.04.
文獻[14]實現了just-in-time ROP,該攻擊重復利用內存泄漏漏洞,映射出目標程序的內存布局,進而搜索gadegts并即時編譯攻擊代碼.但由于其需要利用信息泄露后門讀取程序內存可執行代碼,所以攻擊會被VXnR阻止.文獻[6]實現了以非ret結尾轉移指令的ROP攻擊,但由于其復用的代碼中包含loadstore,在執行loadstore指令對內存代碼的操作時會被VXnR阻止.文獻[2]實現了return-into-libc攻擊,由于該攻擊在尋找所需動態庫函數地址時違背了VXnR代碼不可讀原則,所以攻擊失效.文獻[18]實現了一種利用call-preceded gadget構造call-preceded ROP攻擊.文獻[19]提出了一種新型的代碼復用攻擊LOP.文獻[20]實現了在不破壞ROP payload的語義的前提下構建Long-NOP gadget.文獻[21]定義了2種類型的gadget:call-site(CS) gadgets和entry-point(EP) gadgets.其中CS gadgets與call-preceded gadget概念相同,而EP gadgets是從函數入口點指令開始,到間接跳轉或間接調用指令結束的指令序列,基于這2種gadget只能繞過控制流完整性保護從而實現ROP攻擊.文獻[7]提出了一種ROP攻擊的變種JOP攻擊,文獻[5]提出了一種增強型的代碼復用攻擊BIOP,文獻[22]利用內存泄漏分析程序內存布局實現ROP攻擊.但本系統配置了地址空間布局隨機化保護機制,文獻[5,7,18-22]都需要獲取程序內存布局的前提去搜索gadget,所以違背了VXnR代碼頁不可讀的原則而攻擊失效.測試結果如表1所示,表1的列1為測試用例名稱,列2是測試用例的實現原理,列3表示VXnR能夠檢測到并防御列1所列的測試用例,列4表示VXnR認為測試用例的非法行為.

Table 1 The Defense Results for ROP
Note:“√”means successful defense.
從表1可知,VXnR成功防御了這10類攻擊,表明本文提出的方法是有效的.
為了進一步驗證本方法的有效性,我們與目前主流的代碼復用攻擊防御工具kBoucer[23]和Isomeron[24]對比測試,測試結果如表2所示:

Table 2 Comparison of Different Defense Methods
Note:“√”means successful defense, “×”means failed defense.
根據表2,VXnR能夠防御所有的代碼復用攻擊,而kBoucer無法防御文獻[18]提出的攻擊方法,這是因為kBoucer通過LBR (last branch recording)寄存器檢查與返回地址指向的指令位置相鄰的上一條指令是否為call指令,通過防止返回地址被修改的方法來防御ROP攻擊,而文獻[18]提出了call-preceded ROP并采用歷史記錄沖洗的方法在系統調用前使用一些無關的指令片段將LBR中存儲的真正的gadget信息給替換掉,從而使得kBouncer無法防御攻擊行為,kBoucer也無法防御文獻[19]提出的攻擊方法.因為文獻[19]是通過以整個函數為粒度搜索gadget,實現了call和ret指令是成對出現的LOP(loop-oriented programming)攻擊,能夠繞過控制流完整性(control-flow integrity, CFI)策略.Isomeron無法防御文獻[7,19]提出的攻擊方法,因為Isomeron通過結合執行路徑隨機化和代碼隨機化防御傳統的ROP和JIT-ROP攻擊,所以無法防御文獻[7,19]實現的ROP攻擊的變種JOP和LOP攻擊.文獻[20]實現了在不破壞ROP payload語義的前提下構建Long-NOP gadget,使kBouncer對于gadget長度的檢測防御失效.文獻[21]基于CS gadgets和EP gadgets這2種gadget成功繞過kBouncer控制流完整性保護實現ROP攻擊.文獻[22]能夠利用內存泄漏分析程序內存布局繞過隨機化機制,所以Isomeron無法防御文獻[22]提出的攻擊方法.
為了檢驗本文方法的誤報率,我們使用了一些常用應用程序進行對比檢測.通過運行500次表3列舉的應用程序,觀察每次運行過程中是否會產生誤報,記錄產生誤報的次數,測試結果如表3所示:

Table 3 Results of False Positive Test
由表3可知,沒有誤報產生,這也進一步驗證了本文方法的有效性.
3.2 性能測試
3.2.1 微基準測試
由于本文對系統調用、內存訪問等進行監控,選擇了lmbench中的與系統調用、文件處理、缺頁異常、信號處理以及進程創建等相關事件作為測試項.通過分別測試裸機、Bitvisor,VXnR三者下的性能開銷,并通過對比來分析VXnR所引入的性能開銷,測試結果如表4所示.
其中,在VXnR系統中,受保護程序用戶態和內核態之間的切換會觸發陷入以及相應EPT頁表的切換,因此上下文切換的處理時間會有所增加.由于在VXnR中對所有系統調用進行截獲,系統調用的每次執行都會陷入陷出Hypervisor,因此與系統調用相關的測試項都會受到VXnR的影響.pagefault以及fork proc,fork exec,sh proc執行過程中會更新受保護程序頁表,訪問新的物理頁面時會觸發EPT violation異常陷入VMM,因此它們會引入較大的時間開銷.如圖7所示.

Table 4 LMBench Results: Time in Microseconds

Fig. 7 Microbenchmark results of VXnR.圖7 VXnR微基準測試結果
3.2.2 微基準測試
為了進一步評估VXnR的性能,本文采用4種常用的應用程序對其性能開銷進行測試,每項測試進行500次取平均值,測試結果如表5所示.
壓縮(compression)和解壓縮(decompress)程序均為計算密集型應用,VXnR所引入的性能開銷較小,分別為3.55%和7.89%.內核編譯(kernel build)屬于綜合型應用,既需要CPU時間,也會進行大量的IO操作,VXnR引入了34%的性能開銷.Postmark是IO密集型應用,用于測試系統的后端存儲性能,需要頻繁地存取小文件.我們配置postmark為并發的文件數500個,文件大小的上下限分別是500 B和9.77 KB,讀寫塊大小均為512 B,讀追加發生的概率相等,創建刪除發生的概率相等,文件操作將使用標準的緩沖區IO,隨機數產生的種子是42,事務處理的數目為500000,由于VXnR對讀寫系統調用函數被調用時陷入Hypervisor,因此導致了一定的性能開銷(52.1%).如圖8所示.
Table 5 Application Benchmark Performance Test Results Time in Seconds

表5 應用程序基準測試時間結果 s

Fig. 8 Application benchmark performance test results.圖8 應用基準程序性能測試結果
為了有效防御代碼復用攻擊,研究人員提出了若干方法,主要分為2類:1)通過移除二進制文件中gadget或者隨機化關鍵內存區域來被動阻止ROP攻擊;2)通過基于預定策略執行檢查來有效防御ROP攻擊.
其中,第1類方法應用最廣泛典型的是ASLR機制.然而,ASLR機制通過將程序代碼段加載到一個隨機的基地址使代碼段中每一條指令的地址都發生了變化,但容易被內存泄漏攻擊繞過,為了提升ASLR機制,研究人員通過細粒度隨機化增加隨機化熵,將隨機化對象縮小到函數級和指令級,Marlin[25]是一種函數粒度隨機化方法,該方法通過符號分析、函數重排和跳轉修復3個階段實現改變每一個gadget絕對地址,從而防御代碼復用攻擊.ILR(instruction location randomization)[26]將程序中每一條指令的地址進行隨機化,并利用一個映射表引導指令的執行,從而實現指令級隨機化.Pappas等人[12]提出了IPR(in-place randomization)的方法,通過用語義相同的指令替換gadget中的指令,減少可構造的gadget,因為該方法并未改變函數的位置,所以不能防御return-into-libc攻擊.Davi等人提出了一種基于隨機化有效防御JIT-ROP的防御方法Isomeron[24],通過結合執行路徑隨機化和代碼隨機化來防御傳統的ROP和JIT-ROP攻擊,但該方法無法防御ROP攻擊的變種JOP和LOP攻擊.由于隨機化方法通常只是在程序加載前或加載時進行一次隨機化處理,攻擊者可以利用信息泄露或暴力破解的方式在程序運行時獲取gadget的有效地址.為了防止隨機化保護被繞過,Bigelow等人[27]提出了運行時代碼隨機化的方法,該方法能夠在存在可疑內存泄漏的時間點對程序進行運行時隨機化,從而阻止攻擊者獲取gadget的真實地址.但由于運行時隨機化需要暫停當前程序、保存現場、然后隨機化等操作,所以會帶來較大性能損耗.
第2類方法應用最廣泛典型是CFI.該方法通過構造程序的控制流圖(control-flow graph, CFG),在程序運行時對比檢查程序執行流是否遵循CFG中的有效路徑,從而確保程序運行時的控制流完整性.KBouncer[23]通過在Windows API插入檢查點,利用LBR寄存器檢查與返回地址指向的指令位置相鄰的上一條指令是否為call指令來防御ROP攻擊,由于LBR記錄在上下文切換時會產生記錄溢出或者污染記錄,所以其漏報率較高.為了克服KBouncer的漏報問題,ROPecker[28]將當前LBR中的記錄和后續的記錄結合起來進行檢查,但由于該方法是粗粒度的控制流完整性保護,仍然存在被繞過的風險.Kuznetsov等人[29]提出了一種細粒度的控制流完整性方法代碼指針完整性(code-pointer integrity, CPI),該方法通過使用靜態分析程序所有指向代碼的指針變量,在運行時將存儲變量的內存分為安全區和正常區2個區域,分別存儲代碼指針變量和其它變量.限制所有對安全區的訪問操作必須通過安全檢查來阻止控制流劫持.由于CPI需要靜態分析目標程序源碼,無法確保動態生成代碼的代碼指針完整性.相比于基于隨機化的方法,CFI通過執行檢查主動防御ROP攻擊,但帶來的開銷明顯更高.結合粗粒度CFI和隨機化方法,Opaque CFI[30]通過在控制流轉移前插入CFI檢查限制跳轉目標地址的范圍,由于該閾值因隨機化而改變且隔離在安全區域,可以防御信息泄露攻擊,但是該方法仍然需要靜態分析程序源碼重構跳轉地址,沒有考慮到動態生成的代碼.XnR通過保護目標程序部分代碼頁的隱私安全防御代碼復用攻擊,但攻擊者可以利用未受保護的代碼頁發動攻擊.HideM彌補了XnR的缺陷,能夠對目標進程的全部代碼頁進行保護,但HideM 需要依賴硬件結構,所以不具有普適性.
綜上,隨機化的方法只能在某種程度上減輕代碼復用攻擊,但攻擊者可以通過暴力破解和信息泄露的方式分析獲取可用gadget的地址,并完成代碼復用攻擊,而控制流完整性保護的性能開銷較大,且攻擊者可以通過程序運行時動態生成的代碼繞過完整性保護并構造代碼復用攻擊.本文結合細粒度的隨機化機制,利用內存虛擬化技術,保護程序的內存布局,阻止攻擊者讀取可執行代碼的地址,避免代碼被攻擊者濫用進行惡意攻擊,能夠更加有效地防御代碼復用攻擊.
本文提出了一種基于代碼防泄漏的代碼復用攻擊防御方法VXnR,并給出了VXnR的設計和具體實現.VXnR通過對目標進程的可執行代碼內存區域進行保護,防止信息泄露,從而阻止攻擊者利用目標進程進行代碼復用攻擊.VXnR在虛擬層實現,無需修改客戶操作系統內核,具有良好的兼容性和安全性.我們在Bitvisor虛擬化平臺上實現了VXnR的原型系統,并對VXnR的有效性和性能進行了評測.結果表明VXnR在有效防御代碼復用攻擊的同時,引入的性能開銷不超過52.1%.我們的后續工作將側重于從運行時代碼隨機化的角度研究防御代碼復用攻擊的方法.
[1]Tran M, Etheridge M, Bletsch T, et al. On the expressiveness of return-into-libc attacks[G] //LNCS 6961: Proc of the 14th Int Conf on Recent Advances in Intrusion Detection. Berlin: Springer, 2011: 121-141
[2]Shacham H. The geometry of innocent flesh on the bone: Return-into-libc without function calls (on the x86)[C] //Proc of the 14th ACM Conf on Computer and Communications Security. New York: ACM, 2007: 552-561
[3]Buchanan E, Roemer R, Shacham H, et al. When good instructions go bad: Generalizing return-oriented programming to RISC[C] //Proc of the 15th ACM Conf on Computer and Communications Security. New York: ACM, 2008: 27-38
[4]Hund R, Holz T, Freiling F C. Return-oriented rootkits: Bypassing kernel code integrity protection mechanisms[C] //Proc of the 18th Conf on USENIX Security Symp. Berkeley: USENIX Association, 2009: 383-398
[5]Xing Xiao, Chen Ping, Ding Wenbiao, et al. BIOP: Automatic construction of enhanced ROP attack[J]. Chinese Journal of Computers, 2014, 37(5): 1111-1123 (in Chinese)(邢驍, 陳平, 丁文彪, 等. BIOP:自動構造增強型ROP攻擊[J]. 計算機學報, 2014, 37(5): 1111-1123)
[6]Checkoway S, Davi L, Dmitrienko A, et al. Return-oriented programming without returns[C] //Proc of the 17th ACM Conf on Computer and Communications Security. New York: ACM, 2010: 559-572
[7]Bletsch T, Jiang X, Freeh V W, et al. Jump-oriented programming: A new class of code-reuse attack[C] //Proc of the 6th ACM Symp on Information, Computer and Communications Security. New York: ACM, 2011: 303-307
[8]Sadeghi A A, Aminmansour F, Shahriari H R. Tiny jump-oriented programming attack (A class of code reuse attacks)[C] //Proc of the 12th Int Iranian Society of Cryptology Conf on Information Security and Cryptology. Piscataway, NJ: IEEE, 2015: 52-57
[9]Bosman E, Bos H. Framing signals—A return to portable shellcode[C] //Proc of the 35th IEEE Symp on Security and Privacy. Los Alamitos, CA: IEEE Computer Society, 2014: 243-258
[10]Cowan C, Pu C, Maier D, et al. StackGuard: Automatic adaptive detection and prevention of buffer-overflow attacks[C] //Proc of the 7th USENIX Security Symp. Berkeley, CA: USENIX Association, 1998: 63-78
[11]PaX Team. Address Space Layout Randomization (ASLR)[EB/OL].[2016-08-06]. http://pax.grsecurity.net/docs/aslr.txt
[12]Pappas V, Polychronakis M, Keromytis A D. Smashing the Gadgets: Hindering return-oriented programming using in-place code randomization[C] //Proc of the 33rd IEEE Symp on Security and Privacy. Piscataway, NJ: IEEE, 2012: 601-615
[13]Sotirov A, Dowd M. Bypassing browser memory protections in windows vista[EB/OL].[2016-08-06]. http://www.phreedom.org/research/bypassi-ng-browser-memory-protections
[14]Snow K Z, Monrose F, Davi L, et al. Just-in-time code reuse: On the effectiveness of fine-grained address space layout randomization[C] //Proc of the 34th Symp on Security and Privacy. Piscataway, NJ: IEEE, 2013: 574-588
[15]Backes M, Holz T, Kollenda B, et al. You can run but you can’t read: Preventing disclosure exploits in executable code[C] //Proc of the 2014 ACM SIGSAC Conf on Computer and Communications Security. New York: ACM, 2014: 1342-1353
[16]Gionta J, Enck W, Ning P. HideM: Protecting the contents of userspace memory in the face of disclosure vulnerabilities[C] //Proc of the 5th ACM Conf on Data and Application Security and Privacy. New York: ACM, 2015: 325-336
[17]Dinaburg A, Royal P, Sharif M, et al. Ether: Malware analysis via hardware virtualization extensions[C] //Proc of the 15th ACM Conf on Computer and Communications Security. New York: ACM, 2008: 51-62
[18]Carlini N, Wagner D. ROP is still dangerous: Breaking modern defenses[C] //Proc of the 23rd USENIX Security Symp. Berkeley, CA: USENIX Association, 2014: 385-399
[19]Lan B, Li Y, Sun H, et al. Loop-oriented programming: A new code reuse attack to bypass modern defenses[C] //Proc of the 2015 IEEE Trustcom/BigDataSE/ISPA. Piscataway, NJ: IEEE, 2015: 190-197
[20]Davi L, Sadeghi A R, Lehmann D, et al. Stitching the gadgets: On the ineffectiveness of coarse-grained control-flow integrity protection[C] //Proc of the 23rd USENIX Security Symp. Berkeley, CA: USENIX Association, 2014: 401-416
[21]Goktas E, Athanasopoulos E, Bos H, et al. Out of control: Overcoming control-flow integrity[C] //Proc of the 35th IEEE Symp on Security and Privacy. Piscataway, NJ: IEEE, 2014: 575-589
[22]Strackx R, Younan Y, Philippaerts P, et al. Breaking the memory secrecy assumption[C] //Proc of the 2nd European Workshop on System Security. New York: ACM, 2009: 1-8
[23]Pappas V, Polychronakis M, Keromytis A D. Transparent ROP exploit mitigation using indirect branch tracing[C] //Proc of the 22nd USENIX Conf on Security. Berkeley: USENIX Association, 2013: 447-462
[24]Davi L, Liebchen C, Sadeghi A-R, et al. Isomeron: Code randomization resilient to (just-in-time) return-oriented programming[C] //Proc of the 22nd Network and Distributed System Security Symp. Washington, DC: Internet Society: 2015
[25]Gupta A, Kerr S, Kirkpatrick M S, et al. Marlin: A fine grained randomization approach to defend against ROP attacks[G] //LNCS 7873: Proc of Network and System Security. Berlin: Springer, 2013: 293-306
[26]Davidson J W, Hall M, Co M, et al. ILR: Where’d my gadgets go?[C] //Proc of the 33rd IEEE Symp on Security and Privacy. Piscataway, NJ: IEEE, 2012: 571-585
[27]Bigelow D, Hobson T, Rudd R, et al. Timely rerandomization for mitigating memory disclosures[C] //Proc of the 22nd ACM SIGSAC Conf on Computer and Communications Security. New York: ACM, 2015: 268-279
[28]Cheng Y, Zhou Z, Yu M, et al. ROPecker: A generic and practical approach for defending against ROP attacks[C] //Proc of the 21st Network and Distributed System Security Symp. Washington, DC: Internet Society: 2014
[29]Kuznetsov V, Szekeres L, Payer M, et al. Code-pointer integrity[C] //Proc of the 11th USENIX Conf on Operating Systems Design and Implementation. Berkeley, CA: USENIX Association, 2014: 147-163
[30]Mohan V, Larsen P, Brunthaler S, et al. Opaque control-flow integrity[C] //Proc of the 22nd Network and Distributed System Security Symp. Washington, DC: Internet Society: 2015

Wang Ye, born in 1993. Master candidate. His main research interests include information security and trust computing.

Li Qingbao, born in 1967, Professor and PhD supervisor. Senior member of China Computer Federation. His main research interests include information security and trust computing.

Zeng Guangyu, born in 1966. Associate professor and master supervisor. Senior member of China Computer Federation. Her main research interests include information security and trust computing.
A Code Reuse Attack Protection Technique Based on Code Anti-Leakage
Wang Ye, Li Qingbao, Zeng Guangyu, and Chen Zhifeng
(PLAInformationEngineeringUniversity,Zhengzhou450001) (StateKeyLaboratoryofMathematicalEngineeringandAdvancedComputing(PLAInformationEngineeringUniversity),Zhengzhou450001)
As the address space layout randomization (ASLR) is widely deployed on operating systems, traditional code reuse attacks are suppressed. New code reuse attacks analyze program memory layout through information leak to bypass ASLR, which causes a serious threat to the safety of programs. By analyzing the nature of traditional code reuse attacks and new code reuse attacks, we propose a code reuse attack protection technique VXnR based on code anti-leakage. In this method, we set Execute-no-Read (XnR) permission for the code pages of the target process so that code can be properly executed by the processor, but a read operation is controlled according to the content in the physical page to be accessed, which can prevent attackers from maliciously reading code pages of process to search gadgets by using the information disclosure vulnerability, and defense both traditional code reuse attacks and new code reuse attacks. We have developed a prototype of VXnR and implemented it in a virtual machine monitor Bitvisor. We also evaluate the effectiveness and performance overhead of our approach by comprehensive experiments. The experimental results show that VXnR can effectively prevent attackers from exploiting executable code of the target process to launch code reuse attacks with less than 52.1% overhead.
address space layout randomization (ASLR); code reuse attack; program security; information leaks; virtualization

2016-06-15;
2016-08-10
國家社會科學基金項目(15AGJ012);“核高基”國家科技重大專項基金項目(2013JH00103)
TP303; TP309
This work was supported by the National Social Science Foundation of China (15AGJ012) and the National Science and Technology Major Projects of Hegaoji (2013JH00103).