喬向東,郭戎瀟,趙勇
?
代碼復用對抗技術研究進展
喬向東1,郭戎瀟1,趙勇2,3
(1. 空軍工程大學信息與導航學院,陜西 西安 710077;2. 清華大學計算機科學技術系,北京 100871;3. 江南計算技術研究所,江蘇 無錫 214083)
代碼復用攻擊利用被攻擊目標的固有程序代碼實施攻擊,打破了惡意行為總是源自外部的傳統假設,是先進內存攻擊技術的典型代表,也是近期軟件安全領域的研究熱點。首先,闡述了該技術的產生背景和實現機理;其次,從改進與變體、不同架構平臺下的實現方法、自動化以及包括盲代碼復用攻擊和基于代碼復用的非控制數據攻擊在內的代碼復用攻擊技術的重要拓展等方面系統闡述了近年來國內外相關研究進展;再次,對代碼復用攻擊的防御機制和對抗防御機制的方法進行了討論;最后,對代碼復用對抗技術的發展趨勢和研究方向進行了展望。
軟件安全;代碼復用;返回導向式編程;研究進展

早在20世紀末,盡管當時軟硬件廠商還未提出完整的數據執行保護機制,研究人員已經開始設想復用被攻擊目標中的已有代碼來幫助攻擊者完成特定操作[3],并于1997年首先提出了復用libc函數庫(一種最為常見的基礎函數庫)中的函數二進制代碼來實施攻擊的方法,即Return-into-libc攻擊[4~6]。利用該方法實施攻擊時,攻擊者無需注入惡意代碼(盡管此類情況極少),只需在攻擊載荷中提供必要的libc庫函數的地址,在劫持目標程序控制流后即可使被攻擊目標程序按照攻擊者的意圖執行特定操作,從而繞開數據執行保護機制。然而,由于復用的是函數二進制代碼,Return-into-libc攻擊也存在一些缺陷:1) 只能順序調用函數實施線性攻擊,無法實現跳轉及循環,不具備圖靈完備的計算能力,攻擊能力有限;2) 完全依賴于系統的庫函數,移除或修改庫中的函數將嚴重限制攻擊能力[7]。
返回導向編程技術(ROP, return-oriented programming)是2007年由Shacham[8,9]提出的代碼復用攻擊技術,其核心思想是利用目標設備程序中可實現特定操作的、以ret指令結束的指令序列片段(Gadget),而非完整函數二進制代碼,幫助實現目標設備的執行惡意操作。一般而言,單個Gadget并不具有惡意語義,但通過ret指令將多個Gadget串聯起來是可以完成某種惡意操作的,因此一次攻擊往往需要跳轉執行若干個Gadget。通常情況下,ROP攻擊中需將攻擊所需各個Gadget的地址以及相關數據按照精心設計的格式發送至目標程序存在安全漏洞的函數棧空間中,以確保漏洞觸發后程序控制流發生跳轉并轉而執行Gadget,最終實現惡意操作。圖1給出了基于棧空間控制流劫持的ROP攻擊原理示意,攻擊指令序列是由5個指令序列所含ret指令串聯而成。

圖1 ROP攻擊指令序列示意

圖2 指令序列提取示意(14個字節X86平臺程序片段)
Shacham證明了只要短Gadget足夠多,ROP攻擊即可具備圖靈完全的計算能力。特別地,目標設備處理器指令集中的指令越密集,越有利于代碼復用,這是因為通過對已有指令字節序列的偏移解碼,有極大概率得到具有新語義的有效指令序列。通過改變指令執行的起點,圖2和圖3分別給出了對應X86平臺指令字節序列和Z80單板機BIOS指令字節序列的Gadget提取示意。從圖2可看出,從僅有14個字節的指令字節序列中可得到3個Gadget,其中Gadget 1是原有的指令序列,即有意代碼段;而Gadget 2和Gadget 3則是具有新語義的指令序列,即無意代碼片段。圖3顯示僅從4 byte BIOS指令字節序列中提取到1個無意指令序列。在代碼復用攻擊中,許多Gadget都是由無意代碼片段組成的。通常可從規模較大的程序或函數庫(如libc、glibc)提取到具有各種語義的Gadget,由這些Gadget可組裝出具有內存讀取/存儲、算術和邏輯運算、流程控制、系統調用、函數調用5大功能的Gadget集合,從而實現圖靈完全的計算能力。

圖3 指令序列提取示意(4 byte Z80單板機BIOS程序片段)
與Return-into-libc相比,ROP攻擊的代碼復用粒度更細、針對性更強、應用更為靈活,減小了攻擊載荷的長度,提高了攻擊載荷的利用效率,并已成為主流的代碼復用攻擊技術。以ROP為代表的代碼復用攻擊技術,在建立新的攻擊作用機制的同時,也使因數據保護機制而一度處于困境的代碼注入攻擊重新煥發了生機。
由于ROP攻擊復用了單獨的、以ret結尾的指令片段,使代碼中的call和ret指令不匹配(正常程序中兩者存在一一對應關系),加之通常會將多個ret結尾的指令片段鏈接為ROP攻擊Gadget鏈,這些明顯的特征使其容易被檢測到。為此,研究人員對ROP攻擊進行各種改進,提出了ROP攻擊技術的各種變體。這些ROP變體的一個共同特征是,其Gadget調度和復用機制更加靈活多樣且特征不再凸顯,攻擊更加隱蔽,從而提高了抗攻擊檢測的能力。

圖4 JOP攻擊的原理
2010年,Checkoway[10,11]提出采用具有相同功能的pop-jmp指令序列來替代ret指令,但由于pop-jmp指令序列同樣具有很鮮明的特征,并未從本質上解決ROP的缺陷,通過對指令序列特征的分析,如語義、頻率等,還是很容易檢測到攻擊行為,改進的意義不大。早在2003年,專注于Linux內核安全研究的PaX項目組就提出采用jmp間接跳轉指令構建代碼復用攻擊的想法[12]。2011年,Bletsch[13]提出跳轉導向編程攻擊方法(JOP, jump-oriented programming),以jmp或call間接跳轉指令結尾的指令片段構造功能Gadget,并使用調度Gadget分發控制流,使具體的功能Gadget得以執行,每次功能Gadget執行完畢后都會跳回調度Gadget,繼而執行下一個功能Gadget。圖4給出了JOP的攻擊原理模型。與ret指令相比,jmp指令具有使用位置靈活、形式多樣(間接跳轉和直接跳轉均可)及不依賴棧空間的特點,不僅可以擺脫棧的限制,且由于沒有特定的使用形式和跳轉的目標地址,使對攻擊行為的辨識較為困難。
JOP雖然消除了對ret指令的依賴,但存在其他缺陷。首先,指令序列所包含的call指令,并無相應ret指令與其匹配,使用棧保護技術可以識別;其次,JOP具有寄存器依賴性,在某個Gadget中使用寄存器會影響到后續其他Gadget對該寄存器的使用,從而使其攻擊能力受到限制,因而JOP的實用性并不高。陳平[14]提出了JOP Gadget搜索方法及圖靈完備的JOP Gadget(包括調度和功能Gadget),并實現了自動構建JOP Shellcode的工具,解決了Gadget和內存布局等問題。邢曉[15,16]提出了一種分支指令導向攻擊技術(BIOP, branch instruction-oriented programming),使用間接轉移指令(如jmp指令或call指令)結尾的短指令序列傳遞控制流,由包含一個call指令的Gadget和一個含ret指令的Gadget組成的聯合指令序列負責調用復用的Gadget。由于并未引入新的指令序列特征,BIOP可有效避免現有的防護技術,特別是解決了攻擊構造時的內存沖突,避免了寄存器副作用對攻擊的影響,實現了自動化的攻擊構造。圖5比較了ROP與BIOP的控制流跳轉過程。
傳統上,要在ROP的功能代碼中實現條件轉移邏輯是一件較為復雜的事情。針對X86架構下的ROP攻擊,Shacham給出了間接實現條件跳轉的一種思路,需要串接多達11個不同的Gadget,構造過程中若缺少某些類型的Gadget或不能消除Gadget之間的副作用,都會使構造失敗。為此,袁平海等[17]研究指出,盡管大部分條件判斷指令無助于條件轉移邏輯的實現,但仍有少部分條件判斷指令每個分支的開始部分是可復用的經典指令序列且從不同的內存單元中取得下一個指令序列的地址,從而可以幫助ROP實現條件轉移邏輯,并將這種以條件判斷指令開始的代碼片段稱為if-Gadget(包括I、II、III型),從而大大簡化ROP中條件轉移邏輯的實現,且在Linux 和Windows 上的實驗結果表明,if-Gadget在軟件模塊中普遍存在,從而進一步證實了攻擊者可在可執行程序中構造純ROP 代碼攻擊,ROP 攻擊對現實系統的威脅比原來認為的嚴重得多。

圖5 ROP與BIOP控制流跳轉的比較
盡管初始提出ROP攻擊時主要針對的是X86平臺,但近年來研究人員相繼在SPARC、PowerPC、Z80、ARM、Atmel AVR等不同處理器平臺下實現了ROP攻擊,大大拓展了ROP攻擊的適用范圍。
相較Intel X86平臺的CISC架構,ARM平臺的RISC架構在指令集及實現方式上存在很大的差異。不同于Intel X86的不定長指令,ARM指令是32/16 bit定長指令,且是4/2 byte對齊的。ARM沒有ret指令,但它提供對程序寄存器PC的直接操作,任何一條寫PC寄存器指令都可以當作跳轉指令來執行。2009年,Kornau[18]首先提出了針對ARM平臺的ROP攻擊方法,證明了通過復用應用程序中可執行代碼和鏈接庫代碼能夠實現圖靈完全計算;2010年,Davi[19]采用間接跳轉指令(BLX reg)和跳板塊實現了針對ARM平臺的JOP攻擊,圖6給出了攻擊流程及步驟。錢逸[20,21]在借鑒Kornau所提平臺無關的(基于REIL語言(reverse engineering intermediate language))自動搜索算法和Shacham所提搜索算法的基礎上,提出了針對ARM架構平臺的攻擊指令序列的自動搜索算法。
與馮·諾依曼架構處理器不同,哈佛(Harvard)架構處理器的指令和數據各自享有獨立的存儲器和訪問總線,不允許指令和數據并存。由于程序和數據內存空間相互隔離,也使被當作數據接收的、存儲于數據內存空間的指令很難得到執行的機會。由于哈佛架構處理器的特殊內存布局,傳統上認為對其實施內存注入攻擊是不可能的。針對采用哈佛架構Atmel AVR Atmega 128處理器的無線傳感器網絡節點, Francillon成功實現了針對傳感器節點內存的永久代碼注入攻擊,其核心研究思路是兩階段注入,即首先基于ROP技術將惡意數據注入數據內存空間,其次借助ROP技術將包含在惡意數據中的惡意代碼從數據內存空間注入指令內存空間并執行,這其中會利用到該處理器指令集中的個別特殊指令[22]。由于無線傳感器網絡節點所采用的IEEE 802.15.4協議數據分組大小有限且注入的代碼量較大(如蠕蟲攻擊需增加自傳播模塊),兩階段注入過程均需綜合利用程序控制流恢復及大偽棧技術,以便循環利用漏洞完成大量數據的注入,圖7給出了相關示意。該項研究對于針對嵌入式設備的代碼注入攻擊開辟了新的路徑。

圖6 針對ARM平臺的基于BLX間接跳轉指令的JOP攻擊流程
Checkoway等[23]利用ROP攻擊對采用Z80單板機的美國大選投票機實施了攻擊,整個攻擊過程并未替換安裝有選舉程序的系統只讀存儲器,卻成功改變了投票機存儲的投票結果。需要指出的是,該投票機的所有程序均存儲在3塊64 kB的EPROM只讀存儲器中,這一研究成果打破了有關嵌入式設備固件程序鎖定后即無法對其實施攻擊的傳統認識。此外,Buchanan[24]提出了針對SPARC架構(RISC微處理器架構之一)的微處理器的ROP攻擊實現方法;Lidner[25]則針對采用PowerPC微處理器的嵌入式設備,提出了ROP攻擊的實現方法。
ROP攻擊的核心在于分析目標程序代碼、獲取所需的Gadget,利用所得指令序列構建攻擊Gadget鏈,以完成特定操作。一般而言,實現上述過程既復雜又繁瑣,傳統手工分析設計效率低也容易出錯,因此,近年來ROP攻擊研究的一個重要方向就是自動化,主要圍繞Gadget的自動化搜索和自動化組裝,目的是為了快速、高效地找到實現特定功能邏輯的Gadget。

圖7 針對哈佛架構無線傳感器節點的代碼注入攻擊
針對Gadget的自動獲取,Shacham[8]提出了被稱為Galileo算法的Gadget搜索算法,其核心思想是通過反匯編二進制程序映像,以遞歸反向遍歷的方式,在目標程序中搜索以ret指令結束的指令序列,直至找到所有以ret指令結束的指令序列。公開的Gadget搜索工具,如ROPGadget和ropshell均是基于Galileo算法實現的,但該算法僅適用于X86平臺下以ret 指令作為控制流轉移指令的Gadget搜索。然而,即便是在X86平臺下,用于Gadget間控制流轉移的指令也不只有ret指令,還包括call指令,更何況其他架構平臺還有其特有的指令,如ARM平臺下的bx REG指令序列控制流轉移指令。彭國軍等[26]指出一種更加通用的搜索方式應根據代碼復用的具體方式,構建關于可能的控制流轉移指令的集合,以集合中的每一個指令作為匹配對象來搜索全部潛在的Gadget。
關于Gadget的自動化組裝(編譯)是從搜索到的Gadget集合中選取適當的Gadget,并按照適當的方式將其拼接組織起來形成鏈條,以實現所需的功能邏輯,其實現原理是在使用中間語言描述Gadget的基礎上利用程序最弱前置條件方法對Gadget指令序列進行分類,然后基于編譯器中的指令匹配原理從不同功能類別的Gadget集合中選擇能夠匹配用中間語言描述的功能邏輯需求的Gadget。Buchanan、Komau、Hund、Lez[18,24,27,28]在上述領域開展了深入的研究,相關的研究成果包括基于REIL的Gadget自動化搜索框架和基于QooL的Gadget鏈自動化生成框架,但距離完全意義下自動化代碼復用攻擊仍有很大的差距,難點就在于如何優化地選擇指令序列以實現特定功能邏輯。
針對JOP攻擊的自動化構造,邢曉首先給出了一種針對JOP的Gadget快速搜索算法,并提出了自動構造JOP攻擊shellcode的一般方法和充分條件;為解決Gadget寄存器使用沖突的問題,邢曉還提出了JOP Gadget的排列算法。其所設計的JOP攻擊自動化構造工具由指令序列采集器、指令序列排列器和內存優化器3部分組成,可構建實現各種語義的shellcode[15]。常規ROP攻擊會頻繁調用ret指令結尾的短指令序列,這也成為ROP攻擊防御檢測的一個重要判據,有的檢測方法會將連續3次長度小于5的指令片段調用視為發生了ROP攻擊,采用長度更長的Gadget將使攻擊更為隱蔽和不易被檢測。為此,楊超[29]對基于長指令序列的ROP攻擊自動化進行了研究,在確保圖靈完備的前提下降低了長指令集合的寄存器依賴度,并通過實驗驗證了基于長指令序列自動化填充和鏈接的ROP自動化攻擊的有效性。研究人員還就ROP攻擊的簡化實現開展了深入研究,Long[30]提出先利用一小段ROP攻擊代碼關閉ASLR及DEP保護,并將惡意代碼復制到指定的內存空間,繼而篡改控制流執行以實現惡意代碼的注入。Payer[31]的做法則是首先利用格式串漏洞關閉ASLR及DEP的保護,繼而實施ROP攻擊。簡化的ROP攻擊方式避免了繁瑣的構造攻擊的步驟和時間,大大提高了ROP的攻擊能力。
利用ROP攻擊方法需事先獲得目標設備固件映像(至少是被攻擊程序的二進制代碼),這一條件并非容易滿足。2014年,Bittau等[32]提出了無需事先掌握目標程序的二進制代碼的情況下對其實施ROP攻擊的盲ROP攻擊方法(BROP, blind ROP)。該方法利用服務軟件(如nginx、MySQL、Apache、OpenSSH、Samba等)進程崩潰后會自動重啟的特性,向該服務發送精心設計的探測請求數據分組,通過服務軟件的返回響應所泄露的信息,逐步探測確定所需Gadget的地址(包括擴展的棧空間讀取Gadget、可使目標程序暫停的stop Gadget、潛在可利用的Gadget以及BROP Gadget等),最終實現被攻擊目標設備程序映像的遠程dump操作,繼而對目標實施常規ROP攻擊。在滿足一定條件的前提下,BROP攻擊能夠突破ASLR、程序裝載地址隨機化(PIE, position independent executables)及堆棧檢測等多種保護機制,對32/64 bit Linux系統中的服務應用實施ROP攻擊。表1給出了BROP針對開啟ASLR、NX及canaries棧保護的64 bit Linux系統中3種不同服務的攻擊所需發送請求數目和時間,表2給出了BROP攻擊各階段累積發送的請求數目,從中可見針對源代碼和二進制代碼均閉源的輕量級私有服務,BROP僅發送了1 950個探測請求后就成功對其實施了攻擊,歷時也僅5 min。有關BROP的研究工作得到了DARPA的資助。目前,BROP僅能針對Linux系統開展盲攻擊,還不能適用于Windows系統;此外,BROP假設被攻擊目標和進程能夠容忍多次的惡意連接嘗試,這在現實中也還是較難滿足的。

表1 BROP的攻擊請求總數和耗時

表2 BROP各攻擊階段的累積請求數目
鑒于針對控制流劫持的防御機制日漸豐富和完善,早在2003年就有學者提出了針對非控制數據的攻擊(non-control data attack ),非控制數據主要是指控制流轉移指令不直接使用的內存變量。傳統上一般認為非控制數據攻擊的攻擊載荷僅能實現有限的語義。例如,僅能破壞和泄露少量字節的安全敏感數據。2016年,新加坡國立大學的Hu等[33]提出了一種基于代碼復用的非控制數據攻擊技術,也稱DOP(data-oriented programming),該技術通過利用與內存錯誤相關的漏洞,攻擊非控制數據(如函數局部變量、全局變量、函數參數等),繼而復用搜索到目標程序中的Gadget和Gadget調度器,完成對目標程序的攻擊。DOP Gadget與ROP Gadget的差異主要有兩點:一是DOP Gadget采用某一地址的內存空間作為虛擬寄存器,由虛擬寄存器保存并傳遞Gadget的計算結果,ROP Gadget則可以采用內存或硬件寄存器存儲計算結果;二是由于數據攻擊并不破壞程序控制流程,DOP Gadget的執行必須依據合法的程序控制流程執行,并且不必一個Gadget接著一個Gadget相繼執行,而ROP Gadget的調用不必依據程序控制流程執行,可以在任何需要的時候執行。因此,通常DOP Gadget較ROP Gadget要求更嚴苛。DOP Gadget調度器負責完成DOP Gadget的調度執行,通常由目標程序中的循環體以及對應的選擇器(一般由內存錯誤所控制)構成,并以前次循環迭代中所執行特定DOP Gadget的輸出作為輸入,每次循環迭代會依據選擇器的值選擇執行特定的Gadget,直至無法滿足選擇器的要求而循環終止,圖8給出了DOP攻擊模型的示意。Hu證明了DOP具備圖靈完備的計算能力,大量實驗結果也表明DOP Gadget和調度器的泛在性以及DOP攻擊突破ASLR和DEP防御機制的能力。DOP的最大優勢為在不破壞目標程序控制流的前提下對其實施攻擊,而其主要挑戰在于DOP Gadget和調度器的辨識以及DOP指令序列的拼接組裝,Hu雖然給出了相關算法但其執行效率還需要評估;此外,目前DOP的攻擊對象僅限于X86程序,并不能適用于其他指令架構程序的攻擊。關于針對DOP攻擊的防御,Hu等認為全覆蓋的內存安全措施、全覆蓋的數據流完整性保護(DFI, data-flow integrity)、非控制數據存儲空間的細粒度隨機化等措施有助于緩解甚至消除DOP攻擊,但顯然這些措施也會帶來極大的計算負荷,影響系統運行性能。
隨著代碼復用攻擊技術的發展,其攻擊能力越來越強,威脅也日趨嚴重,研究人員開始考慮針對代碼復用攻擊的防御機制,并提出了不少研究成果。另外,為對抗這些防御機制,如何讓代碼復用攻擊更為隱蔽和難以檢測也成為重要的研究方向。圍繞代碼復用攻擊,一場攻防博弈也就此展開。
總體上講,迄今提出的代碼復用攻擊防御機制可以劃分為三大類:一是通過重編譯從目標程序中移除可被利用的Gadget或者強化目標程序的控制流完整性(CFI, control flow integrity);二是采用運行時保護技術為目標二進制程序提供透明保護[14];三是基于隨機化的防護方法。
就基于重編譯的防護機制而言,其目的是通過定制的編譯器重新編譯目標程序,以使編譯輸出的二進制文件中沒有可被ROP攻擊利用的指令片段。例如,Li等[34]設計實現了一個完全不包含ret返回指令的系統內核,內核中所有指令中的C3字節(ret指令的操作碼)全部被移除,需要通過查表才能找到有效的返回指令,Onarlioglu等[35]學者研發的G-Free編譯器可完全移除目標程序的無意返回指令并加密返回地址。基于重編譯的防護機制的缺點是需要獲得目標程序的源代碼。

圖8 DOP原理示意
基于控制流完整性的防護機制主要通過控制流圖來保護關鍵的控制流對象或者代碼不被篡改,包括跳轉、調用及返回指令必須遵從事先通過源碼分析、靜態分析或運行時profiling獲得的程序控制流圖。已有的控制流完整性保護工具包括Program Shepher、StackGuard、XFI、SFI、Hypersentry等[15]。由于較難獲得細粒度的程序控制流圖,多數情況下該防御機制被簡化為返回指令必須是Call-preceded的,以及間接跳轉指令只能跳轉至函數起始處的約束。2014年,Goktas和Carlini[36,37]經過獨立研究后得出了相同的結論,即基于控制流完整性的防護機制并沒有想象得強。2015年,Otgonbaatar[38]指出,即便獲得了細粒度的控制流完整性,也并不能有效對抗攻擊。王明華等[39]學者提出一種新的面向二進制的細粒度CFI保護方案BinCC,通過代碼復制和靜態分析,該方案將二進制代碼分成幾個互斥代碼塊,繼而將代碼中的各個間接轉移歸類為塊間轉移或塊內轉移,并分別應用嚴格的CFI策略來限制這些轉移,通過減少合法轉移目標,從而增加了攻擊者繞過CFI 限制實施ROP 攻擊的難度。當前有關代碼復用攻擊檢測的研究主要關注的是針對應用層的攻擊檢測,針對內核的攻擊檢測方法較少。為此,陳志鋒等[40]提出了一種基于細(函數)粒度CFI的Linux內核代碼復用攻擊檢測方法,其核心思路是針對與控制流相關的call、ret 和indirect jump指令,提出對應的CFI約束規則,基于編譯器插樁技術和vmcall指令生成并引入CFI標簽指令,在Hypervisor中執行的CFI標簽指令會根據標簽編號和狀態屬性驗證3種指令使用的合法性,實驗結果表明,該方法能夠有效檢測內核級代碼復用攻擊,但對于IO密集作業時的性能開銷較大。另外,使用代碼插樁技術將檢查代碼插入二進制程序中檢測代碼復用攻擊不僅會破壞二進制文件的完整性,通常也會帶來較大的性能損失。
運行時保護是根據代碼復用攻擊Gadget的可能特征阻止針對正在運行的、被保護程序的攻擊。例如,ROPecker發現目標程序存在連續的(10個以上)、以ret指令結尾的Gadget調用且每個Gadget的長度均小于固定門限時,就會關閉該程序[37]。改進版的ROPecker的檢測規則是通過過去次檢測過程中疑似攻擊指令序列的執行次數來判斷是否發生了ROP攻擊[41]。希臘學者Papps等[42]開發的kBouncer則會在程序執行系統調用時停止程序執行,并基于Intel處理器提供的最近指令執行分支記錄(LBR, last branch record)的歷史數據,檢測程序最近16次間接分支執行歷史,依據檢測結果要么允許程序運行,要么關閉程序。Davi[43]通過構建影子棧開發了ROP防御工具ROPdefender,通過驗證所有返回地址是否位于影子棧中判斷是否發生了ROP攻擊。
惡意代碼攻擊過程中通常利用程序中的假設不變量(如地址、代碼、數據、系統調用等)進行攻擊,為此研究人員提出了程序隨機化防御機制,具體表現為4類隨機化方法,包括地址隨機化、代碼隨機化、數據隨機化和操作系統接口隨機化[15]。ROP攻擊的一個重要前提是假設程序中Gadget的地址是不變的,因而通過改變程序內存空間的地址以防止ROP利用硬編碼地址實施攻擊成為ROP攻擊的主要方法之一,包括ASLR、地址空間布局置換排列(ASLP, address space layout permutation)等。地址隨機化現已被常用操作系統采用,但由于并非對程序內存空間的全部地址進行隨機化(有的僅對堆棧和動態鏈接庫地址進行隨機化處理),利用內存信息泄露漏洞或暴力破解方式可以獲得隨機化之后的指令序列地址,因而近年來繞過地址隨機化保護的ROP攻擊也不斷出現,包括前述BROP中提出的、擴展的棧讀取技術。為此,Davi、Wartell及Pappas等[44~46]提出通過函數順序重排列、指令順序重排列、等價指令替換和寄存器重賦值等細粒度的代碼隨機化技術來阻止ROP攻擊。
為了對抗針對代碼復用攻擊的各種防御機制,研究人員也不斷對以ROP攻擊為主的代碼復用攻擊技術進行改進,通過弱化攻擊特征、消除歷史痕跡等方法,使攻擊更加隱蔽和不易檢測。2014年,Carlini和Wagner[37]提出了3種突破ROP攻擊防御的基本方法,即Call-preceded ROP攻擊、規避攻擊、歷史刷新,并闡述了如何綜合利用上述方法構造可突破ROPecker和kBouncer這2種常見防御工具的ROP攻擊。
對于一個正常的構造良好的程序,ret指令和call指令總是成對出現,且每個ret指令總是返回到一個緊跟在call指令之后的指令處(Call-preceded的具體含義),而ROP攻擊則背離了這一模式,因而也成為ROP攻擊檢測和防御的重要判決規則。然而,Carlini的研究表明,即便所有ret指令服從該模式,只要允許攻擊指令序列足夠復雜(長且包含直接或間接跳轉指令),仍然可以實施ROP攻擊,即Call-preceded ROP攻擊。實驗中,Carlini復用70 kbyte二進制文件中的代碼實現了Call-preceded ROP攻擊[37]。
基于運行時檢查的ROP攻擊防御機制常會將程序指令片段辨識為Gadget或非Gadget指令序列,而最常用的辨別依據就是指令片段的長度,較短的指令片段往往被識別為Gadget,較長的指令片段則被識別為非Gadget指令序列。如果防御機制在一定時間內檢測出多個Gadget,就會判定發生了ROP攻擊。一種繞過基于指令片段長度防護機制的方法就是采用長指令片段完成特定功能,楊超[27]對基于長指令序列的ROP攻擊進行了深入研究,通過實驗驗證了基于長指令序列的自動化ROP攻擊方案的有效性。Carlini[37]的研究進一步表明,混合使用長、短指令序列的方式也可以實施ROP攻擊,并能繞過多種公開的防御機制,這也就是Carlini所提的規避攻擊。
除指令片段長度外,基于運行時檢查的防御機制也常常會在程序執行時通過檢查程序指令執行的歷史數據(如Intel處理器支持的LBR數據)判斷是否發生了ROP攻擊。出于性能考慮,這種檢查也只是在特定時刻進行(如發生系統調用時)。由此,Carlini提出在防御機制對應的檢查進程未啟動時執行Gadget,并在檢查進程啟動前周期性地執行無意義的指令序列以清除ROP攻擊的痕跡,而在檢查進程執行時不執行任何Gadget并繼續執行無意義操作,在檢查進程檢測完畢后繼續推進ROP攻擊,這樣檢查進程就看不到任何ROP攻擊的歷史痕跡[37],圖9給出了相關原理說明。

圖9 歷史刷新(隱藏)ROP攻擊
代碼復用對抗是近期軟件安全領域的研究熱點,且已取得了一大批有影響力的研究成果。隨著研究的進一步深入,相信代碼復用攻擊技術依然會保持旺盛的生命力,有關攻防技術的博弈依然會是軟件安全理論研究的熱點。特別地,攻防技術兩端長期呈現的螺旋式發展態勢,有關防御機制的研究依然將推動代碼復用攻擊技術自身的發展,并在提升自身能力、拓展應用領域的同時,不斷提高技術實現的自動化和智能化程度。在今后研究中,有以下幾個方向值得關注。
首先,在已提出的各種代碼復用技術中,BROP突破了傳統ROP攻擊需事先獲得被攻擊目標的程序映像的限制,實現了盲代碼注入攻擊,在極大提升代碼復用攻擊能力的同時,也為今后針對源代碼和二進制代碼均未知的私有服務程序的攻擊技術研究提供了新思路,值得持續開展深入研究,其研究成果有可能為今后具備初步平臺自適應能力的代碼復用攻擊技術提供方法基礎。
其次,基于非控制數據攻擊的代碼復用攻擊由于未改變程序即有的控制流程,包括CFI在內的代碼復用攻擊防護機制對于該類型攻擊并不有效。已證明該類型攻擊具備圖靈完全計算能力,但該類型攻擊較為復雜、實現難度較大。如何降低基于非控制數據攻擊的代碼復用攻擊的實現復雜度以及將基于控制數據攻擊和非控制數據攻擊的代碼復用攻擊相結合是可供探索的方向。
從已發表的文獻看,代碼復用攻擊中所涉及的代碼復用源種類十分廣泛,從傳統的Intel X86、ARM平臺下的代碼,到Z80單板機的代碼,再到無線傳感器節點中的代碼,涉及現有絕大多數通用微處理器,但尚未看到有針對數字信號處理器(DSP, digital signal processor)代碼的驗證性代碼復用攻擊,這或許和DSP主要運行數字信號處理算法代碼而非控制程序代碼有關。從理論上講,復用DSP代碼并非不可行,但由于控制代碼復用和運行復用的代碼涉及不同的指令集合的處理器(前者一般為通用處理器,后者為專用處理器),實現難度會很大,但基于新的代碼復用源的代碼復用攻擊技術仍然十分令人期待。
最后,以ROP為代表的代碼復用攻擊技術的提出,使關于“好代碼”和“壞代碼”的界定變得模糊,因為那些看起來即便是“好的”代碼也可被用來干壞事。通過前述的梳理分析可以看出,無論是基于重編譯還是基于運行時保護的防護機制還不能完全阻止代碼復用攻擊的發生,攻擊方總是想方設法突破各種防護機制,盡管這樣會大大增加攻擊實現的難度和代價。由此,借鑒深度學習和人工智能的最新研究成果,探索將其用于代碼復用攻擊檢測及防護領域的可能,也將是具有較高理論和實踐價值的研究方向。
[1] MICROSOFT. A detailed description of the data execution prevention (dep) feature in windows xp service pack 2[EB/OL]. http://Vsupportjnicrosoft.com/kb./875352.
[2] THE PaX TEAM. PaX project[EB/OL]. http: //pax.grsean-ity.net docs/randexec.txt.
[3] DESIGNER S. Bugtraq: getting around non-executable stack (and fix)[EB/OL]. http://seclists.org/bugtraq/1997/Aug/63..
[4] Bypassing non-executable-stack during exploitation using return-to-libc.c0ntex[EB/OL].http://www.infosecwriters.com/textresources/pdf/return-to-libc.pdf.
[5] MCDONALD J. Defeating solaris/sparc non-executable stack protection[EB/OL]. https://www.thc.org/root/docs/exploit_writing/ sol-ne-stack.html.
[6] TIM N. non-exec stack[J]. Bugtraq, 2000.
[7] KRAHMER S. x86-64 buffer overflow exploits and the borrowed code chunks exploitation techniques[EB/OL]. http://www.suse.de/ krahmer/ no-nx.pdf.
[8] SHACHAM H. The geometry of innocent flesh on the bone: retum-into-libc without function calls (on the x86)[C]//ACM conference on Computer and communications security. 2007: 552-561.
[9] ROEMER R, BUCHANAN E, SHACHAM H, et al. Return-oriented programming: Systems, languages, and applications[EB/OL]. http://cseweb.ucsd.edu/liovav/papers/rbss11.html.
[10] CHECKOWAY S,DAVI L,DMITRIENKO A. Return-oritend programming without returns[C]//ACM Conference on Computer and Communications Security. 2010:559-572.
[11] CHECKOWAY S, SHACHAM H. Escape from return-oriented programming: return-oriented programming without returns (on the x86)[R]. CS2010-0954, 2010.
[12] PaX TEAM. What the future holds for pax[EB/OL]. http://pax. grsecurity. net/docs/pax-future.txt.
[13] BLETSCH T, JIANG X, FREEH V. Jump-oriented programming: a new class of code reuse attack[EB/OL]. ftp://ftp.ncsu.edu/pub/tech/ 2010/TR-2010-8.pdf.
[14] 陳平. 代碼復用攻擊與防御技術研究[D]. 南京: 南京大學, 2012.
CHEN P. Research on the attack and defense techniques of code reuse[D]. Nanjing: Nanjing University, 2012.
[15] 邢曉.自動化構造Jump-Oriented Programming[D]. 南京: 南京大學, 2012
XIAO X. Automatic construction of jump-oriented programming attack[D]. Nanjing: Nanjing University, 2012.
[16] 邢曉,陳平,丁文彪,茅兵,謝立. BIOP: 自動構造增強型ROP攻擊[J].計算機學報, 2014, 37(5):1111-1123.
XIAO X, CHEN P, DING W B, et.al. BIOP:automatic construction of enhanced ROP attack[J]. Chinese Journal of Computers, 2014, 37(5):1111-1123.
[17] 袁平海, 曾慶凱. ROP 圖靈完備的普遍可實現性.軟件學報, 2017, 28(10): 2583-2598.
YUAN P H, ZENG Q K. Universal availability of ROP-based turing-complete computation[J]. Chinese Journal of Software, 2017, 28(10): 2583-2598.
[18] KORMAU T. Return oriented programming for the ARM architecture[D]. Bochum: Ruhr University, 2010.
[19] DAVI L. Return-oriented programming without returns on ARM[R]. Technical Report HGI-TR-2010-002, 2010.
[20] 錢逸, 王軼駿, 薛質. 基于ARM平臺的ROP攻擊及防御技術.信息安全與保密, 2012,10:75-77.
QIAN Y, WANG Y J, XUE Z. ROP attack and defense technology based on ARM[J]. Chinese Information Security and Communication Privacy, 2012,10:75-77.
[21] 錢逸. 基于ARM架構的ROP攻擊與防御技術研究[D]. 上海: 上海交通大學, 2012.
QIAN Y. ROP attack and defense technology based on ARM[D]. Shanghai: Shanghai JiaoTong University, 2012.
[22] FRANCILLON, C.CASTELLUCCIA. Code injection attacks on harvard-architecture devices[C]//ACM Conference on Computer and Communications Security. 2008: 15-26.
[23] CHECKOWAY S, FELDMAN A J, KANTOR B, et al. Can DREs provide long-lasting security? The case of return-oriented programming and the AVC Advantage[C]//EVT/WOTE 2009. USENIX/ACCURATE/IAVoSS. 2009.
[24] BUCHANAN E, ROEMER R, SHACHAM H, et al. When good instructions go bad: generalizing return-oriented programming to RISC[C]//ACM Conference on Computer and Communications Security. 2008: 27-38.
[25] LIDNER F. Developments in Cisco IOS forensics Confidence 2.0[EB/OL].http://www.recurity-labs.com/content/pub/FX_Router_Exploitation.pdf.
[26] 彭國軍, 梁玉, 張煥國, 等. 軟件二進制代重用技術綜述[J]. 軟件學報, 2017,28(8): 2026-2045.
PENG G J, LIANG Y, ZHANG H G, et al. Survey on software binary code reuse technologies[J]. Chinese Journal of Software, 2017, 28(8): 2026-2045.
[27] HUND R, HOLZ T, FREILING F C. Return oriented rootkits: bypassing kernel code integrity protection mechanisms[C]//Usenix Security Symposium. 2009: 383-398.
[28] LEZ R. ARM exploitation ROPMap[C]//BlackHat, 2011.
[29] 楊超. 基于長指令序列的ROP攻擊的自動化工具的研究與實現[D].南京: 南京大學, , 2015
YANG C. Research and implement on an automatic ROP exploit based on long instruction sequence[D]. Naijing: Nanjing University, 2015.
[30] LONG L D, NGUYEN T. Payload already inside: data re-use for rop exploits[C]//Black Hack in the Box. 2010.
[31] PAYER M. String oriented programming circumventing aslr, dep, and other guard[C]//Chaos Communication Congress. 2011:1-5.
[32] BITTAU A, BELAY A. MASHTIZADEH and et al. Hacking blind[C]//IEEE Symposium on Security and Privacy. 2014: 227-242.
[33] HU H, SHINDE S, ADRIAN S, et al. Data-oriented programming:on the expressiveness of non-control data attacks[C]//The 37th IEEE Symposium Security and Privacy. 2016: 969-986.
[34] LI J K, WANG Z, JIANG X X, et al. Defeating return-oriented rootkits with return-less kernels[C]//European conference on Computer systems. 2010:195-208.
[35] ONARLIOGLU K, BILGE L, LANZI A et al. G-free: defeating return-oriented programming through gadget-less binaries[C]// Computer Security Applications Conference. 2010: 49-58.
[36] GOKTAS E, ATHANASOPOULOS E, BOS H, et al. Out of control: overcoming control-flow integrity[C]//IEEE Symposium on Security and Privacy. 2014:575-589.
[37] CARLINI N, WAGNER D. ROP is still dangerous: breaking modern defenses[C]//Usenix Security Symposium, 2014:385-399.
[38] OTGONBAATAR U. Evaluating modern defenses against control flow hijacking[D]. Massachusetts Institute of Technology, 2015.
[39] 王明華,尹恒, BHASKAR AV, 等. 代碼塊:面向二進制程序的細粒度控制流完整性校驗方法.信息安全學報, 2016,1(2):61-72.
WANG M H, YIN H, BHASKAR A V, et al. Binary code continent: finer-grained control flow integrity for stripped Binaries[J]. Chinese Journal of Cyber Security,2016,1(2):61-72.
[40] 陳志鋒, 李清寶, 張平, 等. 面向Linux的內核級代碼復用攻擊檢測技術[J]. 軟件學報, 2017,28(7):1732-1745.
CHEN Z F, LI Q B, ZHANG P, et al. Kernel code reuse attack detection technique for Linux[J]. Chinese Journal of Software, 2017, 28(7): 1732-1745.
[41] CHENG Y Q, ZHOU Z W, YU M, et al. ROPecker: a generic and practical approach for defending against rop attacks[C]//ISOC Network and Distributed System Security Symposium. 2014: 1-14.
[42] PAPPAS V, POLYCHRONAKIS M,. KEROMUTIS A D. Transparent ROP exploit mitigation using indirect branch tracing[C]// USENIX Conference on Security. 2013: 447-462.
[43] DAVI L, SADEGHI A, WINANDY M. ROPdefender: a detection tool to defend against return-oriented programming attacks[C]// ACM Symposium on Information, Computer and Communications Security. 2011: 40-51.
[44] HISER J, NGUYEN-TUNONG A, CO M, et al. ILR: where’d my gadgets go?[C]//The 2012 IEEE Symp. On Security and Privacy (SP). 2012:571-85.
[45] WARTELL R, MOHAN V, HAMLEN K W, et al. Binary stirring: self-randomizing instruction addresses of legacy x86 binary code[C]//The 2012 ACM Conf. on Computer and Communications Security (CCS 2012). 2012. 157-168.
[46] PAPPAS V, POLYCHRONAKIS M, KEROMYTIS A D. Smashing the gadgets: Hindering return-oriented programming using in-place code randomization[C]//The 2012 IEEE Symp. on Security and Privacy (SP). 2012. 601-615.
Research progress in code reuse attacking and defending
QIAO Xiangdong1, GUO Rongxiao1, ZHAO Yong2,3
1. Information and Navigation College, Air Force Engineering University, Xi’an 710077, China 2. Department of Computer Science and Technology, Peking University, Beijing 100871, China 3. Jiangnan Institute of Computing Technology, Wuxi 214083, China
Code reuse attacks make use of binary code existed in the attacked target to perform attack action, such technique breaks out the traditional assumption that malicious behavior always be introduced from the outside,it is representative sample of the advanced memory corruption techniques and also the focus of attention in the software security research field. The generation background and implementation principle were described firstly, and then the recent progresses of the technique, including improvement and variants, implementation methods under the different architecture platforms, automatic construction and important extension including blind ROP and non-control data attacks based on code reuse attacks, were introduced respectively. Various defense mechanisms and possible counter-defense methods for code reuse attacks were also discussed. Finally a perspective of the future work in this research area was discussed.
software security, code reuse, return-oriented programming (ROP), research progress
TP309.2
A
10.11959/j.issn.2096-109x.2018017
2017-12-23;
2018-01-26
喬向東,qxdcm@sina.com
國家自然科學基金資助項目(No.61672061)
The National Natural Science Foundation of China (No.61672061)
喬向東(1970-),男,陜西佳縣人,博士,空軍工程大學副教授,主要研究方向為網絡空間安全、信息對抗及多傳感器信息融合。

郭戎瀟(1982-),女,甘肅蘭州人,博士,空軍工程大學講師,主要研究方向為網絡空間安全。
趙勇(1978-),男,黑龍江方正人,清華大學博士生,主要研究方向為網絡信息安全。
