柳 童 史 崗 孟 丹
?
代碼重用攻擊與防御機(jī)制綜述
柳 童1,2史 崗1孟 丹1
1中國(guó)科學(xué)院信息工程研究所 北京 中國(guó) 1000932中國(guó)科學(xué)院大學(xué) 北京 中國(guó) 100049
由于C與C++等計(jì)算機(jī)程序中廣泛存在的漏洞, 攻擊者可以通過(guò)這些漏洞讀取或篡改內(nèi)存中的數(shù)據(jù), 改變計(jì)算機(jī)程序原有的執(zhí)行狀態(tài)達(dá)到破壞的目的。為此研究者進(jìn)行了不懈地努力并采取了一些卓有成效的保護(hù)機(jī)制, 例如數(shù)據(jù)不可執(zhí)行與內(nèi)存布局隨機(jī)化, 這些防御機(jī)制對(duì)于早期的代碼注入攻擊起到了極好的防御效果, 然而計(jì)算機(jī)系統(tǒng)的安全性依然不容樂(lè)觀。攻擊者在無(wú)法通過(guò)向內(nèi)存中注入自己的代碼并執(zhí)行的方式完成攻擊后, 開(kāi)始利用內(nèi)存中原有的代碼, 通過(guò)控制它們執(zhí)行的順序來(lái)達(dá)到自己的目的, 這種攻擊方式稱為代碼重用攻擊, 它具有極大的威脅性, 能夠繞過(guò)多種現(xiàn)行的安全措施, 并成為攻擊者的主流攻擊方式。為此, 研究界針對(duì)代碼重用攻擊的研究也逐漸增多。本文簡(jiǎn)述了代碼重用攻擊的起源, 攻擊實(shí)現(xiàn)的方式, 系統(tǒng)化地總結(jié)了現(xiàn)有的防御機(jī)制并對(duì)這些防御機(jī)制進(jìn)行了評(píng)價(jià)。對(duì)代碼重用攻擊的根本原因進(jìn)行了簡(jiǎn)要的分析, 并提出了一種新的防御機(jī)制設(shè)計(jì)思路。
計(jì)算機(jī)系統(tǒng)安全; 內(nèi)存攻擊; 代碼重用攻擊
計(jì)算機(jī)的使用在當(dāng)代社會(huì)已經(jīng)普及到工業(yè)、教育、醫(yī)療、金融、軍事等各個(gè)行業(yè)。然而, 針對(duì)計(jì)算機(jī)系統(tǒng)的攻擊也數(shù)不勝數(shù), 造成的損失數(shù)以億計(jì)。這是由于在C與C++等計(jì)算機(jī)程序中普遍存在漏洞, 例如能夠?qū)?nèi)存的直接存取; 對(duì)用戶的輸入沒(méi)有自動(dòng)的邊界檢查機(jī)制, 以及對(duì)已經(jīng)釋放的指針再利用等[1]。使攻擊者能夠利用這些漏洞通過(guò)溢出沒(méi)有邊界檢查機(jī)制的緩沖區(qū)來(lái)注入惡意代碼并篡改內(nèi)存的函數(shù)返回地址, 改變程序控制流使注入的代碼得到執(zhí)行[2], 這就是最早的代碼注入攻擊。在此之上又發(fā)展出了整數(shù)溢出、格式化字符串溢出等攻擊方式, 實(shí)現(xiàn)原理基本相同。計(jì)算機(jī)系統(tǒng)安全機(jī)制的設(shè)計(jì)者針對(duì)這種攻擊方式采用了許多卓有成效的防御機(jī)制, 例如數(shù)據(jù)不可執(zhí)行(Data Execution Prevention , DEP)[3-5], 它將原有在內(nèi)存中無(wú)差別存儲(chǔ)的內(nèi)容分為數(shù)據(jù)段與代碼段, 并劃分了不同的權(quán)限: 數(shù)據(jù)不可執(zhí)行, 代碼不可修改。這使攻擊者以溢出緩沖區(qū)等形式注入的惡意代碼不會(huì)再被允許執(zhí)行, 從而抑制了代碼注入攻擊。
然而這些漏洞仍然在被利用。近年來(lái), 另一種攻擊方式開(kāi)始興起。一些攻擊者開(kāi)始利用程序在內(nèi)存中原有的代碼, 通過(guò)利用漏洞改變它們的執(zhí)行順序來(lái)達(dá)到攻擊的目的, 這就是所謂的代碼重用攻擊(Code-reuse Attack)。從最早的Return-to-Libc攻擊[6,7]逐漸發(fā)展出了ROP(Return Oriented Programming)[8,9]、JOP(Jump Oriented Programming)[10]等攻擊方式。這些攻擊方式依然能夠達(dá)到與傳統(tǒng)的代碼注入攻擊相同的攻擊效果, 能夠使攻擊者執(zhí)行任意代碼。因此目前對(duì)于計(jì)算機(jī)系統(tǒng)安全性的保護(hù)依然不容樂(lè)觀, 研究界對(duì)于代碼重用攻擊的防御提出了各種各樣的安全機(jī)制, 然而都存在安全性或性能、兼容性缺陷, 無(wú)法達(dá)到令人滿意的效果。本文對(duì)代碼重用攻擊的實(shí)現(xiàn)機(jī)制與主要方法進(jìn)行了概述, 并對(duì)針對(duì)代碼重用攻擊的防御機(jī)制的實(shí)現(xiàn)與存在的問(wèn)題進(jìn)行了詳細(xì)的介紹。在分析了代碼重用攻擊的根本原因基礎(chǔ)上提出了一種新的針對(duì)代碼重用攻擊的防御機(jī)制設(shè)計(jì)思想。
本文結(jié)構(gòu)如下: 第二部分對(duì)代碼重用攻擊的實(shí)現(xiàn)機(jī)制與國(guó)內(nèi)外研究界當(dāng)前對(duì)于代碼重用攻擊的研究現(xiàn)狀進(jìn)行了概述; 第三部分和第四部分分別對(duì)當(dāng)前主流的防御機(jī)制兩大設(shè)計(jì)思想進(jìn)行了綜述; 第五部分對(duì)這些防御機(jī)制進(jìn)行了總結(jié)并提出了一種全新的能夠提高計(jì)算機(jī)系統(tǒng)安全性的安全機(jī)制設(shè)計(jì)思想; 第六部分對(duì)全文進(jìn)行總結(jié)。
代碼注入與代碼重用都屬于對(duì)計(jì)算機(jī)系統(tǒng)漏洞進(jìn)行利用的攻擊方式。他們的區(qū)別在于攻擊者執(zhí)行惡意代碼的方式, 前者通過(guò)直接向內(nèi)存中注入惡意代碼并執(zhí)行; 后者利用內(nèi)存中原有的代碼, 通過(guò)篡改控制指令執(zhí)行的數(shù)據(jù), 改變了指令原有的執(zhí)行順序, 使其按照攻擊者的意志執(zhí)行, 達(dá)成攻擊目標(biāo)。現(xiàn)有的安全機(jī)制, 例如數(shù)據(jù)不可執(zhí)行(DEP), 對(duì)代碼注入攻擊起到了極大的抑制作用。因此, 代碼重用攻擊得到了攻擊者的青睞, 成為目前攻擊方式的主流, 它能夠繞過(guò)現(xiàn)行計(jì)算機(jī)系統(tǒng)的大部分安全機(jī)制。目前代碼重用攻擊有Return-to-Libc、ROP、JOP等具體形式。
2.1 Return-to-Libc攻擊
若攻擊者能夠獲悉程序所使用的庫(kù)函數(shù)的地址, 便可以用其地址來(lái)覆蓋程序中某個(gè)函數(shù)的返回值, 并將調(diào)用庫(kù)函數(shù)所需要的參數(shù)以正確的順序添加至覆蓋區(qū)內(nèi), 這樣程序在該函數(shù)返回后就會(huì)執(zhí)行相應(yīng)的庫(kù)函數(shù), 例如調(diào)出一個(gè)shell。這種攻擊方式能使攻擊者可以使用任意的參數(shù)調(diào)用內(nèi)存中任意的庫(kù)函數(shù)[11,12]。
雖然Return-to-Libc攻擊能夠達(dá)成上述的效果, 但在使用上還是有局限性, 不屬于圖靈完備的攻擊方式[9], 原因有兩點(diǎn): 一是在Return-to-Libc攻擊中, 攻擊者能夠一個(gè)接一個(gè)調(diào)用任意的庫(kù)函數(shù), 然而這仍然只能允許他執(zhí)行原有的線性代碼, 無(wú)法滿足進(jìn)行任意行為的需求; 二是攻擊者只能夠調(diào)用已經(jīng)加載到內(nèi)存中的庫(kù)函數(shù), 它們功能有限, 因此限制了攻擊者的能力。
然而也有證明Return-to-Libc攻擊的圖靈完備性的成果[13], 通過(guò)傳統(tǒng)Return-to-Libc中利用的函數(shù)產(chǎn)生的副作用完成特定的操作。找出那些副作用可用的函數(shù)來(lái)作為執(zhí)行某項(xiàng)功能的函數(shù)配件。再利用與下文講述的ROP攻擊相同的原理將這些函數(shù)串聯(lián)起來(lái), 完成圖靈完備的攻擊。
2.2 ROP(Return-Oriented Programming)攻擊
OP是在Return-to-Libc攻擊的基礎(chǔ)上逐步發(fā)展起來(lái)的, 能夠?qū)崿F(xiàn)任意程序行為(圖靈完備)的攻擊方式[9]。ROP攻擊與函數(shù)調(diào)用和返回機(jī)制有極大的聯(lián)系。以x86架構(gòu)程序?yàn)槔? call與ret指令在程序的執(zhí)行過(guò)程中總是一一對(duì)應(yīng)的。在執(zhí)行call指令時(shí), CPU會(huì)將call指令的下一條指令地址壓棧作為返回地址, 然后跳轉(zhuǎn)到call所指示的位置。在ret指令執(zhí)行時(shí), CPU會(huì)自動(dòng)將預(yù)先保存在棧中的返回地址彈給eip寄存器, 繼續(xù)執(zhí)行原有call指令之后的指令。這個(gè)操作不會(huì)對(duì)call的下一條指令的正確性進(jìn)行檢查或保障。ROP攻擊就是利用了這種缺陷。如圖一所示, 首先在原有代碼中搜索一些短小的指令序列, 這些序列都能完成一定的功能, 例如運(yùn)算或賦值, 然后以ret指令為結(jié)尾, 稱為配件(gadget)。攻擊者依據(jù)要執(zhí)行的配件的順序與所需的參數(shù), 將這些配件的地址與參數(shù)進(jìn)行拼接, 構(gòu)建一條配件鏈(gadget chain)。并通過(guò)棧溢出漏洞將這條配件鏈注入到棧中覆蓋當(dāng)前或其他某個(gè)函數(shù)的返回地址。一旦返回地址被覆蓋的函數(shù)返回, 那么CPU就會(huì)按照棧中攻擊者存放的配件地址鏈進(jìn)行跳轉(zhuǎn), 不斷的從一個(gè)配件返回并跳轉(zhuǎn)到下一個(gè)配件執(zhí)行[14]。ROP攻擊極為靈活, 在發(fā)展演變的過(guò)程中出現(xiàn)了許多變種與新的實(shí)現(xiàn)方式, 并配合內(nèi)存泄露攻擊, 能夠繞過(guò)多種專門(mén)針對(duì)它的防御機(jī)制[15-17]。
圖1 ROP攻擊模型
2.3 JOP(Jump-Oriented Programming)攻擊
JOP攻擊采用與ROP類似的配件鏈來(lái)實(shí)現(xiàn)攻擊, 但不依賴棧完成對(duì)程序流的控制[10]。如圖二所示, JOP采用以jmp指令為結(jié)尾的配件。將配件地址鏈保存在另外一塊任意數(shù)據(jù)區(qū)中, 稱為調(diào)度表(dispatch table), 采用了一個(gè)專門(mén)的配件作為一個(gè)指向調(diào)度表的指針, 稱為調(diào)度配件(dispatcher), 類似于普通程序的eip指針, 它對(duì)某個(gè)寄存器進(jìn)行已知操作, 例如自增, 然后跳轉(zhuǎn)到這個(gè)寄存器指示的地址。其他所有的能夠完成特定功能的配件在最后都跳轉(zhuǎn)到調(diào)度配件。而在ROP攻擊中, 配件執(zhí)行的控制序列是以配件地址鏈的形式存儲(chǔ)在棧上的, 利用棧指針來(lái)指向配件。與ROP相同, JOP攻擊的實(shí)現(xiàn)也是需要指令序列的, 這些序列就是配件的地址, 但由于采用了調(diào)度配件, 配件地址序列可以存放在內(nèi)存的任何可讀寫(xiě)區(qū)域, 而不是必須在棧上。這就給了攻擊者更大的靈活性和空間。他們可以將配件鏈放置于內(nèi)存中任意一塊可寫(xiě)的數(shù)據(jù)區(qū)。
2.4 其他類型代碼重用攻擊
除了上述三種常見(jiàn)的代碼重用攻擊之外, 有研究者和黑客也相繼提出了其他類型的代碼重用攻擊。
SROP[18]利用類UNIX操作系統(tǒng)用進(jìn)程棧保存信號(hào)幀的機(jī)制, 通過(guò)偽造信號(hào)幀來(lái)引導(dǎo)進(jìn)程進(jìn)入到攻擊者設(shè)定的代碼區(qū)域中執(zhí)行實(shí)現(xiàn)攻擊目的。
COOP[19]利用了C++面向?qū)ο缶幊痰奶匦? 利用篡改類中的虛函數(shù)表來(lái)使一系列虛函數(shù)按照攻擊者設(shè)定的順序執(zhí)行完成攻擊目標(biāo)。
2.5 國(guó)內(nèi)外研究現(xiàn)狀
由于代碼重用攻擊具有極強(qiáng)的破壞性, 極高的靈活性, 能夠繞過(guò)現(xiàn)行的絕大多數(shù)防御機(jī)制。已經(jīng)漸漸成為黑客進(jìn)行攻擊的主要手段。研究界對(duì)于代碼重用攻擊防御機(jī)制的研究也得到極大的重視。
在2011-2015年間S&P (IEEE Symposium on Security and Privacy)、CCS(ACM Conference on Computer and Communications Security)以及Usenix (Usenix Security Symposium)安全方面世界三大頂級(jí)會(huì)議對(duì)于代碼重用攻擊的相關(guān)論文發(fā)表數(shù)量如圖三所示, 可以看出, 對(duì)于這類攻擊的研究與防范逐漸成為研究界的重點(diǎn)。
代碼重用攻擊的實(shí)現(xiàn)需要兩大重要環(huán)節(jié), 一個(gè)是控制流的劫持, 另外一個(gè)是對(duì)內(nèi)存中的代碼位置的獲悉。首先得到內(nèi)存中的代碼位置, 構(gòu)建控制程序執(zhí)行的配件地址鏈, 而后通過(guò)對(duì)溢出漏洞將配件鏈注入到內(nèi)存的數(shù)據(jù)區(qū)中, 最后劫持控制流使得程序按照攻擊者注入的配件順序執(zhí)行。因此防御措施也就分別針對(duì)這兩個(gè)重要環(huán)節(jié), 監(jiān)測(cè)程序的異常行為與增加程序的不可知性。
攻擊者在實(shí)行代碼重用攻擊時(shí), 要實(shí)現(xiàn)惡意的功能, 勢(shì)必改變?cè)谐绦虻膱?zhí)行路線, 因此研究者通過(guò)添加一些監(jiān)控機(jī)制對(duì)這種改變做出偵測(cè)用以判斷代碼重用攻擊的發(fā)生。
實(shí)現(xiàn)代碼重用攻擊的另外一個(gè)要素是對(duì)內(nèi)存中程序指令位置的精確知曉, 由于攻擊者已經(jīng)無(wú)法注入自己的代碼, 因此只能使用內(nèi)存中原有的代碼, 他們通過(guò)選擇配件, 并精心構(gòu)造配件地址鏈用來(lái)控制這些配件的執(zhí)行實(shí)現(xiàn)自己的惡意目的。因此研究者通過(guò)增加內(nèi)存的不可知性來(lái)阻止攻擊者得知內(nèi)存中代碼的布局, 使其無(wú)法構(gòu)造配件鏈。
目前的針對(duì)程序異常行為的監(jiān)測(cè)防御機(jī)制中, 大致分為兩種方法, 一種是對(duì)ROP/JOP攻擊中配件出現(xiàn)頻率的監(jiān)測(cè); 另一種是對(duì)程序控制流正確性的保障與監(jiān)測(cè)。
3.1 對(duì)于配件出現(xiàn)頻率的檢測(cè)
研究者在觀察代碼重用攻擊(這里以ROP攻擊為例)發(fā)生時(shí)的程序行為時(shí)發(fā)現(xiàn), 發(fā)生ROP攻擊的程序行為與正常程序行為有著明顯不同。在ROP攻擊的過(guò)程中, 攻擊者通過(guò)將許多以ret指令為結(jié)尾的配件連接起來(lái)完成攻擊, 這些配件大都較短, 在一定長(zhǎng)度以內(nèi), 當(dāng)ROP攻擊發(fā)生時(shí)程序指令流中會(huì)出現(xiàn)大量ret指令。因此監(jiān)測(cè)一段指令當(dāng)中ret指令出現(xiàn)的頻率, 就成為了一種監(jiān)測(cè)ROP攻擊的方式。然而這種方式只能對(duì)ROP攻擊產(chǎn)生效果, 無(wú)法防御Return-to-Libc攻擊。
Pappas等人[20]利用Intel處理器中自帶的LBR (Last Branch Recording)機(jī)制來(lái)對(duì)程序中的間接跳轉(zhuǎn)進(jìn)行檢測(cè), 保證所有的ret指令返回目標(biāo)指令都位于一條call指令之后, 這種方式可以防御簡(jiǎn)單的Return-to-Libc與ROP攻擊; 利用對(duì)LBR中存儲(chǔ)的跳轉(zhuǎn)指令的地址進(jìn)行分析, 分析這些地址之間的緊密程度來(lái)判斷是否出現(xiàn)了一串以ret為結(jié)尾的配件鏈, 從而判斷是否出現(xiàn)了ROP攻擊。Cheng[21]等人采用了相同的對(duì)配件鏈的檢查思路, 并采取了對(duì)于間接跳轉(zhuǎn)更為頻繁和嚴(yán)格的檢查。Pappas[20]等人與Cheng[21]等人都采用了對(duì)配件的出現(xiàn)頻率進(jìn)行監(jiān)控的方法, 通過(guò)比對(duì)遭到攻擊的程序與正常程序之間的差別來(lái)監(jiān)測(cè)攻擊的發(fā)生。具體涉及到兩個(gè)變量: 被認(rèn)作是配件的指令序列長(zhǎng)度Lg和被認(rèn)作ROP攻擊發(fā)生的配件連續(xù)出現(xiàn)的次數(shù)Lc。通過(guò)改變這兩個(gè)變量可以提高或降低ROP攻擊檢測(cè)的敏感程度。
這種方式存在的問(wèn)題是無(wú)法確定檢查的敏感度。假如提高敏感度, 那么有可能正常的程序也會(huì)被判定發(fā)生ROP攻擊, 使假警報(bào)劇增; 假如降低敏感度, 則ROP攻擊就有可能逃過(guò)監(jiān)測(cè)。如何選擇Lg和Lc對(duì)是需要解決的問(wèn)題。更嚴(yán)重的是, 目前有些攻擊者已經(jīng)能夠找到一些長(zhǎng)配件, 這些長(zhǎng)配件的長(zhǎng)度大于被系統(tǒng)認(rèn)作ROP配件的長(zhǎng)度, 并把這些配件加入到實(shí)施ROP攻擊的配件鏈中, 就可以完全逃過(guò)這種防御機(jī)制的監(jiān)測(cè)[15,16,22]。
總體來(lái)說(shuō), 這種監(jiān)測(cè)思想存在較大的繞過(guò)可能性, 無(wú)法有效滿足目前的安全需求。
3.2 基于保障控制流完整性思想的防御機(jī)制
類比與對(duì)配件出現(xiàn)頻率進(jìn)行監(jiān)測(cè)的方法, 保障間接轉(zhuǎn)移指令目標(biāo)地址的正確性是目前更為有效的方法, 這里需要指出的是, 轉(zhuǎn)移指令分為直接轉(zhuǎn)移和間接轉(zhuǎn)移兩大類, 直接轉(zhuǎn)移指令的目的地址是在編譯鏈接階段就已經(jīng)確定并寫(xiě)入二進(jìn)制代碼中的, 在程序運(yùn)行時(shí)無(wú)法更改; 間接轉(zhuǎn)移指令在運(yùn)行時(shí)對(duì)具體的寄存器或內(nèi)存進(jìn)行間接尋址, 這些間接轉(zhuǎn)移指令的目標(biāo)可能是動(dòng)態(tài)變化的, 因此存在被攻擊者篡改并劫持的可能性, 故所有保障控制流完整性的機(jī)制都是針對(duì)間接轉(zhuǎn)移指令的。
3.2.1 細(xì)粒度CFI的最早提出與探討
文獻(xiàn)[23]是最早提出保障控制流完整性(Control- Flow Integrity,CFI)思想的文章, 首先將要執(zhí)行的代碼進(jìn)行靜態(tài)分析, 畫(huà)出控制流圖, 預(yù)先計(jì)算出所有的間接轉(zhuǎn)移指令的可能的目標(biāo)地址, 并為之配唯一的ID。改寫(xiě)程序的二進(jìn)制代碼, 在每一條間接跳轉(zhuǎn)指令執(zhí)行之前增加檢查邏輯, 一旦出現(xiàn)違反控制流圖的間接跳轉(zhuǎn)就會(huì)報(bào)錯(cuò)并終止程序。這種為每一個(gè)轉(zhuǎn)移目標(biāo)地址分配唯一ID的實(shí)現(xiàn)思想我們稱之為細(xì)粒度CFI。它在被提出時(shí)被認(rèn)為具有極佳的安全性, 能夠檢測(cè)出任何代碼重用攻擊并使用純軟件方式實(shí)現(xiàn), 得到了研究界廣泛的重視與探討, 并出現(xiàn)了不少具體的實(shí)現(xiàn)方案。
XFI[24]利用CFI思想保證控制流的正確性, 并結(jié)合了其他例如內(nèi)存訪問(wèn)控制, 影子棧等機(jī)制, 將傳統(tǒng)的應(yīng)用程序包裝成XFI模塊, 在運(yùn)行時(shí)提供保護(hù)與監(jiān)控, 并通過(guò)設(shè)置外部接口與操作系統(tǒng)交互。然而所有的應(yīng)用程序都被封裝成塊, 則被設(shè)計(jì)用于共享的動(dòng)態(tài)鏈接庫(kù)就無(wú)法使用, 導(dǎo)致運(yùn)行時(shí)內(nèi)存有一定的空間損耗。
Hypersafe[25]是最早提出的對(duì)虛擬機(jī)監(jiān)控器進(jìn)行CFI保護(hù)的安全機(jī)制。其對(duì)監(jiān)控器代碼進(jìn)行分析, 對(duì)所有代碼指針的可能調(diào)用位置進(jìn)行計(jì)算, 并維持指針?biāo)饕? 在每次指針解引用時(shí)查表, 若出現(xiàn)非法目標(biāo)地址就會(huì)報(bào)錯(cuò)。對(duì)返回地址采用類似的方法。但是只能對(duì)直接運(yùn)行在硬件上的1類監(jiān)控器進(jìn)行保護(hù), 在運(yùn)行與宿主操作系統(tǒng)之上的2類監(jiān)控器上無(wú)法實(shí)現(xiàn)。
文獻(xiàn)[26]是最早提出的基于智能手機(jī)平臺(tái)上的CFI實(shí)現(xiàn)方案, 針對(duì)蘋(píng)果公司的面向?qū)ο驝語(yǔ)言并且應(yīng)用程序加密存儲(chǔ)。對(duì)程序的二進(jìn)制代碼進(jìn)行解密, 反匯編, 繪制控制流圖再對(duì)二進(jìn)制代碼進(jìn)行改寫(xiě)。而文獻(xiàn)[27]是屬于對(duì)其的改進(jìn), 在編譯器階段進(jìn)行CFI設(shè)置, 提高了應(yīng)用程序的靈活性。
上述文章都屬于對(duì)傳統(tǒng)CFI思想在不同平臺(tái)上的實(shí)現(xiàn)與應(yīng)用, 沒(méi)有本質(zhì)上的改進(jìn)與創(chuàng)新。
在提出了近10年以后, CFI思想才在商業(yè)領(lǐng)域得到了初步的應(yīng)用, 微軟公司提出了CFG (Control- Flow Guard)技術(shù), 通過(guò)編譯器在編譯階段對(duì)代碼的分析。在程序運(yùn)行時(shí)的每一個(gè)間接調(diào)用進(jìn)行檢查, 看目標(biāo)地址是否是一個(gè)函數(shù)的開(kāi)頭[28]。這種方式不屬于傳統(tǒng)細(xì)粒度CFI思想并且對(duì)間接跳轉(zhuǎn)與返回指令沒(méi)有保護(hù), 存在被繞過(guò)的可能。
細(xì)粒度CFI在提出之后之所以一直沒(méi)有得到廣泛的應(yīng)用, 是由于其本身還存在不少問(wèn)題, 比如:
1. 針對(duì)諸如內(nèi)核程序上百萬(wàn)行的代碼, 以及其他的大規(guī)模的程序, 如何精確的畫(huà)出其控制流圖, 仍然是一個(gè)亟待解決的問(wèn)題。
2. 傳統(tǒng)的細(xì)粒度CFI要求在程序載入內(nèi)存之前需要對(duì)所有的程序模塊進(jìn)行分析并重寫(xiě)二進(jìn)制代碼加入檢查指令, 包括動(dòng)態(tài)鏈接庫(kù), 那么每個(gè)程序就只能在載入時(shí)帶著它們自己重寫(xiě)好后的庫(kù)了, 無(wú)法與其他的程序共享, 這與動(dòng)態(tài)鏈接庫(kù)的設(shè)計(jì)初衷相悖[29]。
3. 純軟件的CFI實(shí)現(xiàn)方式性能損耗較高。在20%至50%左右[23]。
針對(duì)細(xì)粒度CFI存在的這些性能與實(shí)現(xiàn)上缺陷, 研究界也進(jìn)行了許多探討與改進(jìn)。
文獻(xiàn)[29]針對(duì)經(jīng)典CFI[23]對(duì)動(dòng)態(tài)鏈接庫(kù)無(wú)法支持的缺陷, 將ID與地址綁定存在另外一塊內(nèi)存區(qū)中。建立兩個(gè)表, 一個(gè)映射間接轉(zhuǎn)移指令地址與其ID, 稱為分支表; 另一個(gè)表映射各個(gè)ID的轉(zhuǎn)移指令的合法目標(biāo)地址, 稱為目標(biāo)表。對(duì)每一個(gè)間接轉(zhuǎn)移指令, 分別查兩個(gè)表, 根據(jù)指令自身地址在分支表中查其ID, 再在目標(biāo)表中根據(jù)轉(zhuǎn)移指令的目標(biāo)地址查ID, 若匹配, 說(shuō)明通過(guò)。若不匹配則報(bào)錯(cuò)。經(jīng)典CFI要求一次性畫(huà)出全部程序的CFG, 但是該方法將程序分為多個(gè)模塊, 分別為每個(gè)模塊畫(huà)出CFG, 在加載多個(gè)模塊運(yùn)行時(shí), 就會(huì)將各個(gè)模塊的CFG合并。這種運(yùn)用ID表的方式方便動(dòng)態(tài)的添加與維護(hù)。能夠較好的解決傳統(tǒng)二進(jìn)制代碼改寫(xiě)的無(wú)法兼容共享庫(kù)的缺陷。
文獻(xiàn)[30,31]針對(duì)傳統(tǒng)CFI使用純軟件實(shí)現(xiàn)導(dǎo)致?lián)p耗高的缺點(diǎn), 使硬件層次對(duì)上層的CFI機(jī)制進(jìn)行支持, 添加了關(guān)于CFI檢查的指令以替代傳統(tǒng)的軟件實(shí)現(xiàn), 能夠大大縮減代碼指令長(zhǎng)度并減小了性能損耗。但這種方式會(huì)使兼容性降低, 沒(méi)有進(jìn)行硬件修改的硬件無(wú)法對(duì)上層代碼進(jìn)行CFI支持。
文獻(xiàn)[32]將沙箱處理的相關(guān)技術(shù)與CFI進(jìn)行組合, 對(duì)CFI繁瑣的檢查機(jī)制進(jìn)行整合簡(jiǎn)化, 提高了CFI檢索的速度, 降低了性能損耗。
文獻(xiàn)[33]將CFI在編譯器層次上實(shí)現(xiàn), 對(duì)C++中的虛函數(shù)表進(jìn)行保護(hù), 采用靜態(tài)分析, 對(duì)虛函數(shù)表進(jìn)行分析, 對(duì)目標(biāo)碼進(jìn)行修改, 在調(diào)用虛函數(shù)之前加入一個(gè)驗(yàn)證函數(shù)進(jìn)行確認(rèn)。該方法在一定程度上提高了CFI的兼容性并減少了性能損耗。但是僅僅能夠?qū)νㄟ^(guò)函數(shù)指針進(jìn)行的函數(shù)調(diào)用進(jìn)行保護(hù), 無(wú)法對(duì)運(yùn)行時(shí)的棧、堆等數(shù)據(jù)結(jié)構(gòu)進(jìn)行保護(hù)。
3.2.2 粗粒度CFI的提出與否定
針對(duì)經(jīng)典的細(xì)粒度CFI實(shí)現(xiàn)較困難, 損耗較高的缺陷。學(xué)界提出了一類簡(jiǎn)化版的CFI實(shí)現(xiàn)方案。它們通過(guò)犧牲一定安全性來(lái)達(dá)到可以接受的性能損耗與實(shí)現(xiàn)難度。與先前的細(xì)粒度CFI相比, 這些實(shí)現(xiàn)方案都不需要畫(huà)出程序的控制流圖, 可以稱之為粗粒度CFI。
CCFIR[34]重寫(xiě)目標(biāo)碼, 收集所有合法的跳轉(zhuǎn)指令目標(biāo)地址并將其以隨機(jī)序存儲(chǔ)于一塊獨(dú)立的安全內(nèi)存中, 強(qiáng)制所有的間接跳轉(zhuǎn)指令只能通過(guò)這個(gè)內(nèi)存區(qū)域完成控制流的轉(zhuǎn)移。CFIMon[35]通過(guò)靜態(tài)分析得出合法的跳轉(zhuǎn)地址, 并利用處理器中的分支追蹤存儲(chǔ)機(jī)制(LBR等)來(lái)實(shí)時(shí)分析控制流的完整性。文獻(xiàn)[36]將間接轉(zhuǎn)移指令替換為到一個(gè)外部處理程序的直接跳轉(zhuǎn), 并維持一個(gè)合法跳轉(zhuǎn)表, 每次間接跳轉(zhuǎn), 處理程序會(huì)查這個(gè)表, 只有在表中的目標(biāo)地址才能作為這個(gè)間接跳轉(zhuǎn)的目的地。文獻(xiàn)[37]首次將CFI思想在操作系統(tǒng)內(nèi)核上實(shí)現(xiàn)。改寫(xiě)操作系統(tǒng)代碼, 加入檢查邏輯。文獻(xiàn)[38]采用靜態(tài)分析與動(dòng)態(tài)監(jiān)測(cè)相結(jié)合的方式檢查間接跳轉(zhuǎn)指令的目標(biāo)是否位于合法函數(shù)區(qū)間。
上述幾種方法雖然實(shí)現(xiàn)方法各異, 但是他們都有一個(gè)共同的特點(diǎn), 就是不需要畫(huà)出程序詳細(xì)的控制流圖并且對(duì)于間接跳轉(zhuǎn)目的地址不需要分配唯一ID。僅僅是對(duì)程序進(jìn)行靜態(tài)分析, 根據(jù)一定的規(guī)則找到合法的跳轉(zhuǎn)地址, 例如, 所有的ret指令的合法目標(biāo)都是一條call指令下一條指令; 所有的間接調(diào)用目標(biāo)地址都必須是一個(gè)函數(shù)的開(kāi)頭。這就導(dǎo)致任意間接轉(zhuǎn)移指令與他們可能的目標(biāo)地址之間不再遵從邏輯上的一對(duì)一關(guān)系, 而是一對(duì)多。一條ret指令可以返回到任意一個(gè)call指令的下一條指令, 而不必是原本的調(diào)用者; 一條call指令可以進(jìn)入任意一個(gè)函數(shù)的開(kāi)頭, 而不用根據(jù)邏輯進(jìn)行判定究竟應(yīng)當(dāng)跳轉(zhuǎn)到哪一個(gè)函數(shù)的開(kāi)頭。
粗粒度CFI這種對(duì)間接跳轉(zhuǎn)目標(biāo)地址不加以再區(qū)分的管理方式, 導(dǎo)致了攻擊者能夠通過(guò)精心設(shè)計(jì)的配件, 組合配件鏈, 能夠做到繼續(xù)實(shí)施代碼重用攻擊[16,39]。具體使用的配件特點(diǎn)如下: 一種配件以一條call指令的下一條指令為起始, 以ret指令為結(jié)尾, 這種配件可以繞過(guò)粗理度CFI對(duì)ret指令必須調(diào)到調(diào)用點(diǎn)的檢查機(jī)制; 另一種配件是以一個(gè)函數(shù)開(kāi)頭為起始, 以一個(gè)間接跳轉(zhuǎn)指令為結(jié)束的配件, 這種配件可以繞過(guò)粗粒度CFI對(duì)間接調(diào)用指令必須調(diào)到函數(shù)開(kāi)頭的檢查機(jī)制。攻擊者將這兩種配件搭配使用, 就可以完全繞開(kāi)粗粒度CFI的檢查完成攻擊。因此, 粗粒度CFI也被證明無(wú)法滿足安全需求而被研究界淘汰。
3.2.3 細(xì)粒度CFI安全性弱點(diǎn)的提出與改進(jìn)
隨著研究界將研究的重點(diǎn)重新轉(zhuǎn)回細(xì)粒度CFI, 研究者又發(fā)現(xiàn)了細(xì)粒度CFI中存在的安全漏洞。
“控制流彎曲”[40]利用細(xì)粒度CFI僅僅保障所有跳轉(zhuǎn)都按照事先通過(guò)靜態(tài)分析確定的控制流圖進(jìn)行, 不會(huì)對(duì)進(jìn)程的上下文語(yǔ)義進(jìn)行分析的缺陷。挑選了一些經(jīng)常使用的并且會(huì)對(duì)內(nèi)存中的數(shù)據(jù)產(chǎn)生修改的函數(shù)(例如printf()、memcpy()等)通過(guò)控制這些函數(shù)的參數(shù)對(duì)內(nèi)存中的數(shù)據(jù)進(jìn)行修改, 完成了不逾越控制流圖的控制流劫持, 完成攻擊者所需要的功能。
傳統(tǒng)細(xì)粒度CFI的另一個(gè)缺陷是無(wú)法對(duì)系統(tǒng)產(chǎn)生的信號(hào)或中斷的返回進(jìn)行保護(hù), 在類UNIX操作系統(tǒng)中, 這些信號(hào)或中斷發(fā)生時(shí), 進(jìn)程原狀態(tài)大多數(shù)是保存在棧上的。SROP[36]利用這種機(jī)制, 通過(guò)偽造信號(hào)幀來(lái)并篡改棧上保存的現(xiàn)場(chǎng)狀態(tài)引導(dǎo)進(jìn)程進(jìn)入到攻擊者設(shè)定的代碼區(qū)域中執(zhí)行實(shí)現(xiàn)攻擊的目的。文獻(xiàn)[41]與[42]也針對(duì)細(xì)粒度CFI在實(shí)現(xiàn)上的漏洞提出了繞過(guò)的方法。
針對(duì)細(xì)粒度CFI存在的安全缺陷, 研究者也對(duì)其進(jìn)行了相關(guān)的改進(jìn)。
文獻(xiàn)[43]對(duì)所有能夠改變程序控制流的對(duì)象進(jìn)行認(rèn)證(包括函數(shù)返回地址, 函數(shù)指針等), 在每次這些對(duì)象從內(nèi)存中存儲(chǔ)的時(shí)候計(jì)算一個(gè)驗(yàn)證值, 將其存于一個(gè)寄存器中, 每次這些對(duì)象被讀取時(shí)檢查這個(gè)值是否與先前相同。
文獻(xiàn)[44]提出了上下文相關(guān)的CFI, 利用intel CPU中的LBR(Last Branch Record)機(jī)制, 每當(dāng)程序要執(zhí)行重要的系統(tǒng)調(diào)用時(shí)(例如exec()等), 則對(duì)LBR中保存的先前的跳轉(zhuǎn)指令進(jìn)行CFI判斷, 若全部符合, 則繼續(xù)執(zhí)行, 若有不符合CFG的跳轉(zhuǎn)則會(huì)報(bào)錯(cuò)停止執(zhí)行。這種方法能夠解決傳統(tǒng)細(xì)粒度CFI無(wú)法對(duì)上下文的跳轉(zhuǎn)合法性進(jìn)行判斷的缺陷。
總體來(lái)說(shuō), 粗粒度CFI安全性不足不能滿足實(shí)際需求。細(xì)粒度CFI機(jī)制尚未完全成熟, 仍然存在安全與性能問(wèn)題需要克服, 若能達(dá)到低耗, 高兼容性實(shí)現(xiàn), 將會(huì)產(chǎn)生較好的保護(hù)效果。
由于代碼重用攻擊的實(shí)現(xiàn)要依賴對(duì)內(nèi)存中已有指令的使用。攻擊者需要知道這些指令的確切位置。因此通過(guò)增加程序不可知性的方法也可以達(dá)到阻止攻擊的發(fā)生, 使用隨機(jī)化是一個(gè)典型并有效的方法。
4.1 隨機(jī)化安全機(jī)制
ASLR(Address Space Layout Randomization)[45]是一個(gè)典型且已經(jīng)得到廣泛應(yīng)用的基于隨機(jī)化的防御機(jī)制。其主要思想是通過(guò)對(duì)進(jìn)程中的代碼段、數(shù)據(jù)段、堆、棧所占的頁(yè)面進(jìn)行隨機(jī)化排布來(lái)使攻擊者無(wú)法得知這些段的具體位置從而無(wú)法實(shí)施攻擊。這種方式與數(shù)據(jù)段不可執(zhí)行機(jī)制(DEP)相結(jié)合, 起到了很好的防御效果, 不僅能夠?qū)鹘y(tǒng)的注入攻擊產(chǎn)生防御效果, 也能提高代碼重用攻擊實(shí)施的難度。
但是ASLR仍然存在不足與缺陷, 具體有三點(diǎn):
1. 隨機(jī)化的粒度僅僅到頁(yè)一級(jí), 頁(yè)內(nèi)的數(shù)據(jù)仍然是順序存儲(chǔ)的, 且參與隨機(jī)化的內(nèi)存地址位數(shù)不足, 能夠被暴力攻破[46,47];
2. 由于動(dòng)態(tài)鏈接庫(kù)的共享機(jī)制, 其位置對(duì)所有的程序都是可知的, 這就導(dǎo)致了這些代碼無(wú)法參與細(xì)粒度隨機(jī)化處理。防御機(jī)制設(shè)計(jì)者只能選擇放棄動(dòng)態(tài)庫(kù)的共享或放棄對(duì)這部分代碼的隨機(jī)化處理[48];
3. ASLR面臨內(nèi)存泄露攻擊的威脅, 由于程序代碼段一般都會(huì)占用多個(gè)頁(yè)面, 頁(yè)面之間都有跳轉(zhuǎn)指令維持其之間的聯(lián)系。攻擊者若能夠通過(guò)懸空指針等漏洞對(duì)任意內(nèi)存地址數(shù)據(jù)進(jìn)行讀取, 可以找到頁(yè)面之間的相互聯(lián)系, 就可以達(dá)到知曉代碼段頁(yè)面的分布位置, 實(shí)現(xiàn)去隨機(jī)化[49]。
由于ASLR極為廣泛的使用和極為突出的弱點(diǎn)與缺陷, 目前大多數(shù)的研究都是著眼于對(duì)ASLR的改進(jìn)或以ASLR為標(biāo)尺。在ASLR的基礎(chǔ)上又產(chǎn)生了許多新穎的內(nèi)存隨機(jī)化實(shí)現(xiàn)機(jī)制。
文獻(xiàn)[50]針對(duì)ASLR粒度較粗的缺點(diǎn), 對(duì)代碼的放置順序進(jìn)行隨機(jī)排布, 粒度達(dá)到了單個(gè)指令級(jí)。建立一個(gè)記錄代碼順序的表, 對(duì)每一條指令, 記錄其后繼指令。
文獻(xiàn)[51]在不影響程序運(yùn)行正確性的情況下, 對(duì)指令進(jìn)行小范圍的隨機(jī)化處理, 能夠做到消除無(wú)意識(shí)配件, 重排函數(shù)調(diào)用與返回的寄存器保存和彈出指令。能夠在一定程度上減少攻擊者可以使用的配件數(shù)量。但是這種方法的覆蓋不夠廣泛, 無(wú)法完全消除配件。
文獻(xiàn)[52]對(duì)二進(jìn)制代碼中的代碼段復(fù)制為兩份, 將原有的代碼段當(dāng)做純數(shù)據(jù), 不可執(zhí)行, 對(duì)復(fù)制的部分進(jìn)行分塊, 并在此程序裝載時(shí)隨機(jī)化, 并運(yùn)行, 使用相關(guān)的算法保證代碼段中的轉(zhuǎn)移指令的正確性。以此實(shí)現(xiàn)內(nèi)存布局的細(xì)粒度隨機(jī)化。
文獻(xiàn)[53]將進(jìn)程的所有代碼數(shù)據(jù)段分割成任意大小的塊, 然后將這些塊隨機(jī)排布的整個(gè)進(jìn)程地址空間。利用二進(jìn)制代碼重寫(xiě)技術(shù)進(jìn)行重新匯編, 保持控制流指令正確。
文獻(xiàn)[48]對(duì)于ASLR的兼容性問(wèn)題, 使共享代碼實(shí)現(xiàn)隨機(jī)化。首先重寫(xiě)目標(biāo)代碼, 利用一個(gè)間接查找表使控制流轉(zhuǎn)移重定向, 使得所有跳轉(zhuǎn)目標(biāo)都會(huì)通過(guò)這個(gè)表來(lái)查找。利用x86的分段機(jī)制保護(hù)間接查找表, 使用特定的段選擇寄存器FS, 只有修改過(guò)的合法跳轉(zhuǎn)指令才能找到間接查找表。但這種方式僅僅能夠在x86-32架構(gòu)上實(shí)現(xiàn), 并且無(wú)法防御內(nèi)存泄露的攻擊[54]。
文獻(xiàn)[55]與[56]分別在函數(shù)段與程序塊的粒度對(duì)內(nèi)存中代碼進(jìn)行隨機(jī)化分布, 增加了參與隨機(jī)化的內(nèi)存地址位數(shù), 提高了隨機(jī)化粒度。
不論實(shí)現(xiàn)方式如何, 上述通過(guò)隨機(jī)化增加程序不可知性的安全機(jī)制, 都面臨一個(gè)共同的威脅, 那就是內(nèi)存泄露。內(nèi)存泄露能夠幫助攻擊者獲得配件的地址, 對(duì)代碼重用攻擊的實(shí)現(xiàn)起到了極大的幫助作用。代碼重用加內(nèi)存泄露是目前最具威脅性的攻擊方式。
4.2 內(nèi)存泄露的威脅與應(yīng)對(duì)
傳統(tǒng)的DEP等權(quán)限劃分的安全機(jī)制僅僅是將內(nèi)存頁(yè)面的寫(xiě)操作與執(zhí)行操作分離開(kāi)來(lái)。無(wú)論代碼段還是數(shù)據(jù)段都是默認(rèn)可讀的, 這就導(dǎo)致了攻擊者通過(guò)懸空指針等程序錯(cuò)誤對(duì)內(nèi)存頁(yè)面進(jìn)行讀取、掃描。在代碼段或數(shù)據(jù)段中得到程序隨機(jī)化的分布布局, 從而繞過(guò)ASLR等隨機(jī)化安全機(jī)制, 進(jìn)行攻擊。
文獻(xiàn)[49]能夠使用內(nèi)存泄露漏洞, 實(shí)時(shí)對(duì)隨機(jī)化布局之后的程序代碼段進(jìn)行掃描, 獲悉每個(gè)代碼頁(yè)確切的起始地址, 計(jì)算出可以用作配件的代碼段的地址, 動(dòng)態(tài)搭建配件鏈實(shí)施攻擊。
內(nèi)存泄露大致分為兩種方式: 一是直接泄漏: 讀取代碼段, 找到直接跳轉(zhuǎn)和直接調(diào)用的目標(biāo)地址, 收集這些地址進(jìn)行分析, 就可以得出代碼頁(yè)面的分布位置; 二是間接泄漏: 讀取數(shù)據(jù)段中的函數(shù)指針(例如虛函數(shù)表), 返回地址可以達(dá)到相同的目的[57]。
傳統(tǒng)的寫(xiě)/執(zhí)行權(quán)限分離思想無(wú)法防御內(nèi)存泄露的攻擊, 內(nèi)存泄露又會(huì)導(dǎo)致隨機(jī)化安全機(jī)制的失效。因此防御針對(duì)內(nèi)存泄露也成為了學(xué)界研究的重點(diǎn)。針對(duì)這種威脅, 最初的防御思想是分離讀權(quán)限。但是針對(duì)目前的硬件結(jié)構(gòu)來(lái)說(shuō), CPU無(wú)法對(duì)頁(yè)面的讀權(quán)限進(jìn)行剝離, 需要通過(guò)上層的操作系統(tǒng)進(jìn)行支持, 并且傳統(tǒng)的代碼段中是包含數(shù)據(jù)信息的, 如何對(duì)代碼段中的數(shù)據(jù)進(jìn)行剝離也是實(shí)現(xiàn)的難點(diǎn)之一。
文獻(xiàn)[58]將讀與執(zhí)行權(quán)限分離。通過(guò)改寫(xiě)MMU中的頁(yè)錯(cuò)誤處理機(jī)制實(shí)現(xiàn)。假如進(jìn)程對(duì)內(nèi)存空間中代碼區(qū)中一個(gè)不存在的頁(yè)面進(jìn)行取指操作, 則說(shuō)明屬于正常的缺頁(yè)異常, MMU會(huì)從硬盤(pán)中載入這個(gè)頁(yè)并將頁(yè)存在相關(guān)位置。但如果對(duì)這個(gè)代碼頁(yè)進(jìn)行的不是取指操作, 則說(shuō)明是對(duì)代碼頁(yè)的讀取, 屬非法, 會(huì)導(dǎo)致進(jìn)程停止。能夠?qū)χ苯有孤懂a(chǎn)生防御效果。然而這種防御機(jī)制無(wú)法對(duì)間接泄露產(chǎn)生防御效果, 無(wú)法保護(hù)數(shù)據(jù)段中包含代碼段地址的函數(shù)指針等不會(huì)被泄露。
文獻(xiàn)[57]將代碼段與數(shù)據(jù)段嚴(yán)格區(qū)分, 確保代碼段只可執(zhí)行而不再可讀。將代碼段中的數(shù)據(jù)進(jìn)行修改為只執(zhí)行(例如switch轉(zhuǎn)換表, 之前的是跳轉(zhuǎn)的地址, 文章改成跳轉(zhuǎn)到該地址的指令。)實(shí)現(xiàn)代碼只可執(zhí)行可以防止直接內(nèi)存泄露。再將數(shù)據(jù)段中的函數(shù)指針和返回地址都改為代碼段中的一個(gè)中轉(zhuǎn)站, 這個(gè)中轉(zhuǎn)站通過(guò)指令的形式跳轉(zhuǎn)到對(duì)應(yīng)的目標(biāo)地址, 通過(guò)這種方式防御間接內(nèi)存泄露。這種防御方式在目前來(lái)說(shuō)能夠?qū)?nèi)存泄露起到有效的防御效果。
由于對(duì)內(nèi)存代碼段中的數(shù)據(jù)與代碼強(qiáng)行進(jìn)行分離的方法實(shí)現(xiàn)過(guò)于困難, 有研究者通過(guò)對(duì)代碼段進(jìn)行復(fù)制并添加不同的方式實(shí)現(xiàn)對(duì)內(nèi)存泄露攻擊的防御。
文獻(xiàn)[59]將可執(zhí)行的代碼段復(fù)制作為數(shù)據(jù)段。當(dāng)有對(duì)代碼段中的數(shù)據(jù)進(jìn)行讀取操作時(shí), 就將這段數(shù)據(jù)用隨機(jī)數(shù)代替, 并對(duì)MMU進(jìn)行重定向操作, 使之指向復(fù)制的數(shù)據(jù)段。將對(duì)數(shù)據(jù)和代碼的操作分割在不同的區(qū)域, 在可執(zhí)行區(qū)的數(shù)據(jù)在讀取后將不會(huì)再與原來(lái)相同。
文獻(xiàn)[54]先對(duì)二進(jìn)制代碼進(jìn)行修改, 將其復(fù)制為兩份, 一份是原有狀態(tài), 一份是經(jīng)過(guò)隨機(jī)化排布的, 在每個(gè)函數(shù)的調(diào)用和返回階段, 隨機(jī)選取運(yùn)行哪一份的代碼, 這樣即使攻擊者能夠通過(guò)泄漏得到內(nèi)存布局, 也無(wú)法使構(gòu)造的ROP鏈得到執(zhí)行。
文獻(xiàn)[60]將程序段分為兩個(gè)大段, 代碼段和數(shù)據(jù)段。AG作為中間的轉(zhuǎn)接層。將程序中所有的能夠控制代碼執(zhí)行的位置稱為代碼地址, 例如基地址, GOT、PLT的入口、棧中的返回地址, 跳轉(zhuǎn)表等。每當(dāng)有代碼地址將向數(shù)據(jù)區(qū)泄露時(shí), AG對(duì)其進(jìn)行加密作為一個(gè)標(biāo)識(shí), 每當(dāng)有標(biāo)識(shí)被用于控制流跳轉(zhuǎn)時(shí), AG對(duì)其進(jìn)行解密。對(duì)棧上的數(shù)據(jù)進(jìn)行了保護(hù), 將函數(shù)返回地址等數(shù)據(jù)保存在原有的位置。將棧上的其他數(shù)據(jù)用另一個(gè)寄存器指示。
文獻(xiàn)[61]與文獻(xiàn)[58]類似,利用MMU通過(guò)軟件實(shí)現(xiàn)對(duì)代碼可讀屬性與可執(zhí)行屬性的分離。利用頁(yè)錯(cuò)誤處理程序區(qū)分程序的非法讀操作與正常的指令獲取(Instruction Fetch)。
總結(jié)來(lái)說(shuō), 基于隨機(jī)化的安全機(jī)制在確保內(nèi)存不被泄露并且隨機(jī)熵足夠高的情況下能夠起到較好的防御效果。
本小節(jié)對(duì)現(xiàn)有的對(duì)于代碼重用攻擊的防御方式進(jìn)行系統(tǒng)化的總結(jié), 并提出了一種能夠從根本上提升對(duì)于代碼重用攻擊防御效果的設(shè)計(jì)思路。
對(duì)于計(jì)算機(jī)系統(tǒng)的攻擊與防御是一對(duì)不斷上升與交錯(cuò)的矛盾雙方: 對(duì)于計(jì)算機(jī)系統(tǒng)的攻擊催生著防御方式的改進(jìn); 防御方式的改進(jìn)有促使黑客或研究者開(kāi)發(fā)與使用新的更有效的攻擊方式。
而在對(duì)于計(jì)算機(jī)防御機(jī)制的設(shè)計(jì)與實(shí)現(xiàn)方面。性能與安全又成為了一對(duì)矛盾的兩個(gè)方面。要提高系統(tǒng)的安全性必然伴隨著性能或兼容性的損耗。能夠平衡這一對(duì)矛盾, 在可接受的性能與兼容性損耗限度內(nèi)達(dá)到令人滿意的安全效果的防御機(jī)制才得以廣泛的采用。DEP與ASLR可以成為這種防御機(jī)制的典型, 它們二者組合使用可以做到在較低的損耗的情形大幅度提高攻擊者成功實(shí)施攻擊的難度。
但這兩種防御機(jī)制在代碼重用攻擊與內(nèi)存泄露攻擊的雙重威脅之下其安全效能已經(jīng)不再適用。DEP僅僅能夠防御計(jì)算機(jī)系統(tǒng)不受代碼注入的攻擊, 無(wú)法對(duì)代碼重用攻擊產(chǎn)生防御效果; ASLR本身具有諸多弱點(diǎn)并且面臨內(nèi)存泄露的威脅。研究界對(duì)于這種新興的攻擊方式開(kāi)始了不懈地探索與研究。
5.1 程序行為監(jiān)控
針對(duì)代碼重用攻擊的防御, 思路上最簡(jiǎn)單的方法是對(duì)于程序運(yùn)行時(shí)行為的監(jiān)測(cè), 有效實(shí)施這種防御機(jī)制的難點(diǎn)與關(guān)鍵在于快速區(qū)別正常運(yùn)行的程序與遭到攻擊的程序之間運(yùn)行狀態(tài)的差異。
早期的研究者對(duì)指令流中出現(xiàn)配件的頻率進(jìn)行監(jiān)控。這種方法能夠?qū)ψ钤嫉腞OP攻擊產(chǎn)生較好的防御效果, 但其本身仍然存在問(wèn)題, 嚴(yán)格地監(jiān)控會(huì)導(dǎo)致大量虛假警報(bào), 而降低敏感度會(huì)使攻擊行為被忽視。且攻擊者已經(jīng)開(kāi)始使用超過(guò)被認(rèn)作的配件的長(zhǎng)指令段以此稀釋配件出現(xiàn)的頻率將其繞過(guò)。
對(duì)于配件出現(xiàn)頻率的監(jiān)控?zé)o法進(jìn)行, 研究者開(kāi)始轉(zhuǎn)而控制進(jìn)程跳轉(zhuǎn)行為的合法性, 傳統(tǒng)細(xì)粒度CFI越來(lái)越得到重視。這種機(jī)制安全性較好高, 但存在先天性的性能損耗高, 無(wú)法使用動(dòng)態(tài)鏈接庫(kù)等缺陷。于是研究者開(kāi)始研究能夠?qū)崿F(xiàn)的CFI方案, 出現(xiàn)了粗粒度CFI實(shí)現(xiàn)方案。
粗粒度CFI不需要事先精確分析程序的控制流, 采用了較為寬松的CFI檢查機(jī)制, 得到了性能上的提升, 但是其檢查機(jī)制過(guò)于寬松, 無(wú)法保障函數(shù)在返回時(shí)跳轉(zhuǎn)到的是原先的調(diào)用點(diǎn), 也無(wú)法保障函數(shù)調(diào)用時(shí), 所進(jìn)入的函數(shù)體就是原本應(yīng)當(dāng)調(diào)用的函數(shù), 攻擊者就可以利用精心設(shè)計(jì)的配件加以繞過(guò)。
在粗粒度的CFI實(shí)現(xiàn)方案被否定以后, 研究界繼續(xù)細(xì)粒度CFI的研究。對(duì)于細(xì)粒度CFI安全性的質(zhì)疑被提出, 難點(diǎn)依然無(wú)法解決: 無(wú)法準(zhǔn)確判斷某個(gè)跳轉(zhuǎn)屬于程序正常的操作還是被攻擊者劫持, 有攻擊者能夠?qū)崿F(xiàn)不違反控制流圖的攻擊; 由于目前操作系統(tǒng)自身的代碼沒(méi)有經(jīng)過(guò)CFI強(qiáng)化, 對(duì)于從操作系統(tǒng)到用戶代碼的轉(zhuǎn)移沒(méi)有檢查, 因此攻擊者可以通過(guò)偽造系統(tǒng)調(diào)用或信號(hào)幀來(lái)實(shí)現(xiàn)對(duì)控制流的劫持。
針對(duì)程序行為監(jiān)控這種安全機(jī)制的基本思想是使程序按照一定的規(guī)則運(yùn)行, 一旦檢測(cè)出程序有違反規(guī)則的行為則認(rèn)作攻擊發(fā)生。兩個(gè)關(guān)鍵點(diǎn)分別是監(jiān)控的實(shí)施與規(guī)則的設(shè)定。有些攻擊者通過(guò)安全機(jī)制的監(jiān)控盲區(qū)進(jìn)行攻擊[18]; 有些攻擊者則利用規(guī)則的漏洞進(jìn)行攻擊[40]。因此, 能否全面地對(duì)程序的行為進(jìn)行監(jiān)控與能否設(shè)定安全高效的規(guī)則, 是決定安全機(jī)制有效與否的關(guān)鍵。而由于計(jì)算機(jī)程序的龐雜性、程序運(yùn)行時(shí)的狀態(tài)多樣性, 使得這種監(jiān)控的實(shí)施與規(guī)則的設(shè)定具有很高的挑戰(zhàn)性。
5.2 增加程序的不可知性
代碼重用攻擊的另一個(gè)防御思想是通過(guò)增加程序不可知性使攻擊者無(wú)法得知程序代碼的布置方式從而無(wú)法構(gòu)建配件地址鏈。主要的實(shí)現(xiàn)方式是進(jìn)行隨機(jī)化排布。然而在進(jìn)行隨機(jī)化的同時(shí)還應(yīng)當(dāng)保證程序自身運(yùn)行的正確性。這個(gè)過(guò)程可以成為去隨機(jī)化(Derandomization), 有些安全機(jī)制例如ASLR[45]通過(guò)生成地址無(wú)關(guān)代碼與程序裝載時(shí)的隨機(jī)化分布來(lái)自動(dòng)實(shí)現(xiàn)隨機(jī)化程序的逆隨機(jī)化; 有些需要一定的內(nèi)存占用與時(shí)間開(kāi)銷(xiāo)來(lái)完成隨機(jī)化代碼的去隨機(jī)化例如ILR[50]使用額外的指令流程圖控制每條指令的執(zhí)行。攻擊者可以利用諸如內(nèi)存泄露等方式獲得ASLR隨機(jī)化后的內(nèi)存布局或是ILR的指令流程圖, 進(jìn)而實(shí)現(xiàn)去隨機(jī)化, 找到要用的配件鏈完成代碼重用攻擊。
評(píng)價(jià)一個(gè)隨機(jī)化安全機(jī)制有兩個(gè)關(guān)鍵指標(biāo): 程序正常去隨機(jī)化的難度以及攻擊者掌握去隨機(jī)化方法的難度。一個(gè)好的隨機(jī)化安全機(jī)制必然是程序自身能夠?qū)崿F(xiàn)簡(jiǎn)便的去隨機(jī)化過(guò)程, 而攻擊者很難進(jìn)行去隨機(jī)化。
對(duì)于內(nèi)存泄露的防御也得到了研究者的重視, 主要的防御思想是分離并限制讀權(quán)限, 例如使代碼段不可讀, 僅可執(zhí)行等。但是傳統(tǒng)的程序代碼段是包含數(shù)據(jù)的, 如何將代碼段中的數(shù)據(jù)剝離也是等待解決的問(wèn)題。除此之外也有對(duì)代碼段進(jìn)行冗余化并采取原份與備份不同處理的方式。
總體來(lái)說(shuō), 本文認(rèn)為能夠克服諸多限制的細(xì)粒度CFI, 以及能夠有效防范內(nèi)存泄露的隨機(jī)化機(jī)制可以較好地防御代碼重用攻擊。
5.3 代碼重用攻擊根本原因分析與安全機(jī)制設(shè)計(jì)思路
代碼重用攻擊的一個(gè)重要的原因是控制流被劫持, 許多防御機(jī)制針對(duì)如何保護(hù)控制流的完整性, 致力于發(fā)現(xiàn)并制止控制流的被劫持。但這種防御措施僅僅是被動(dòng)地檢測(cè), 實(shí)際的根本問(wèn)題是控制流為什么會(huì)被劫持。從計(jì)算機(jī)系統(tǒng)結(jié)構(gòu)級(jí)考慮, 發(fā)生傳統(tǒng)緩沖區(qū)溢出攻擊的根本原因是在程序的執(zhí)行過(guò)程中, 對(duì)程序的代碼段和數(shù)據(jù)段采取了相同的權(quán)限管理, 所有的頁(yè)面都是可讀可寫(xiě)并可執(zhí)行的。這就導(dǎo)致了攻擊者利用軟件漏洞將自己要執(zhí)行的惡意代碼以數(shù)據(jù)形式注入到內(nèi)存中, 并通過(guò)修改控制流使得這些惡意代碼以代碼的形式得到了執(zhí)行。對(duì)于數(shù)據(jù)與代碼權(quán)限與處理方式的混淆導(dǎo)致了這種情況的發(fā)生。研究界認(rèn)識(shí)到了這種問(wèn)題, 并提出了數(shù)據(jù)不可知性思想, 即一段內(nèi)存頁(yè)不能既可修改, 又可執(zhí)行。并采取相應(yīng)的實(shí)際防御機(jī)制, 即DEP, 使得這個(gè)問(wèn)題得到了很好的解決。
然而攻擊仍在發(fā)生, 只是攻擊者不再將惡意代碼以數(shù)據(jù)的形式注入到內(nèi)存中去, 而是利用內(nèi)存中原有的代碼, 通過(guò)控制它們執(zhí)行的順序來(lái)達(dá)到自己的目的, 也就是所謂的代碼重用攻擊。數(shù)據(jù)與指令具有極大的關(guān)聯(lián)性, 真正控制指令執(zhí)行的還是數(shù)據(jù)。這些控制指令執(zhí)行的數(shù)據(jù)在內(nèi)存中是以地址或指針的形式存儲(chǔ)的。這些數(shù)據(jù)與傳統(tǒng)的整數(shù)、浮點(diǎn)數(shù)等數(shù)據(jù)類型都被保存在內(nèi)存的數(shù)據(jù)區(qū)中。那么類比針對(duì)傳統(tǒng)注入攻擊的分類并采取權(quán)限分離的防御思想, 我們可以對(duì)內(nèi)存中的內(nèi)容進(jìn)行再次分類。具體可以分為普通數(shù)據(jù), 例如傳統(tǒng)的char、int類型數(shù)據(jù)等; 普通指令, 即原有意義上的指令; 數(shù)據(jù)地址, 例如指向普通數(shù)據(jù)的指針, 數(shù)組等; 指令地址, 例如函數(shù)指針, 函數(shù)的返回地址、基地址、虛函數(shù)表等。那么如此分類之后, 代碼重用攻擊的根本原因也就顯而易見(jiàn)了——指令地址被篡改。然而攻擊者能夠注入自己數(shù)據(jù)的地方僅僅是在內(nèi)存的普通數(shù)據(jù)段與數(shù)據(jù)地址段中, 但是由于這些數(shù)據(jù)段與指令地址在內(nèi)存中都是按照傳統(tǒng)數(shù)據(jù)這種方式進(jìn)行無(wú)差別存儲(chǔ)與管理的, 它們之間沒(méi)有邏輯上或空間上的分隔。這就給了攻擊者篡改指令地址的機(jī)會(huì), 導(dǎo)致了代碼重用攻擊的發(fā)生。
依據(jù)這種宏觀思想, 本文提出了一種初步的設(shè)計(jì)思路。如圖六所示, 對(duì)程序運(yùn)行時(shí)棧的結(jié)構(gòu)進(jìn)行重構(gòu), 將原有的棧一分為二: 一個(gè)用于保存壓入的普通數(shù)據(jù), 稱之為數(shù)據(jù)棧; 一個(gè)用于保存所有的函數(shù)返回地址和基地址, 稱之為地址棧。為兩個(gè)棧分別維護(hù)一套棧頂指針與棧幀指針。將地址棧的權(quán)限設(shè)置為只有函數(shù)的調(diào)用與返回階段才會(huì)進(jìn)行壓棧與彈棧操作。將地址棧的位置置于數(shù)據(jù)棧的地址減小方向, 這樣即使攻擊者利用漏洞對(duì)棧中的緩沖區(qū)進(jìn)行溢出, 也不會(huì)覆蓋到地址棧中函數(shù)的返回地址。
為了初步實(shí)現(xiàn)這種設(shè)計(jì)思路, 本文給出兩種方案: 第一種在硬件上實(shí)現(xiàn), 增加兩條機(jī)器指令分別對(duì)新的數(shù)據(jù)棧進(jìn)行壓棧與彈棧操作, 從原有的寄存器中保留兩個(gè)用于保存數(shù)據(jù)棧的棧頂?shù)刂放c棧幀地址, 將原有的壓棧與彈棧指令改為對(duì)新的數(shù)據(jù)棧進(jìn)行的操作, 原有的棧作為地址棧?;蚴菍?duì)call指令與ret指令進(jìn)行修改, 將壓入原有棧中的返回地址壓入新的地址棧中, 原有的棧作為數(shù)據(jù)棧; 第二種是用軟件實(shí)現(xiàn), 與文獻(xiàn)[60]中的AG-Stack類似, 由編譯器用mov與sub(add)指令組合來(lái)模擬對(duì)新開(kāi)辟的數(shù)據(jù)棧的壓(彈)棧操作, 原有的棧作為地址棧。采用軟件實(shí)現(xiàn)的方式與硬件實(shí)現(xiàn)相比, 能夠產(chǎn)生較少的兼容性損耗和較高的性能損耗。硬件實(shí)現(xiàn)需要對(duì)底層的指令架構(gòu)進(jìn)行修改, 兼容性變差, 但是產(chǎn)生的性能損耗較低。這樣將棧結(jié)構(gòu)分開(kāi)并處以不同的處理方式, 可以有效避免攻擊者利用漏洞對(duì)保存在棧中的函數(shù)返回地址等指向指令的數(shù)據(jù)進(jìn)行篡改, 從而大幅增加了實(shí)現(xiàn)代碼重用攻擊的難度。
本小節(jié)提出的設(shè)計(jì)思路僅僅是一種構(gòu)想, 具體實(shí)現(xiàn)的細(xì)節(jié)仍然有待完善。
導(dǎo)致計(jì)算機(jī)系統(tǒng)不安全的原因是沒(méi)有相應(yīng)權(quán)限的訪問(wèn)與修改: 攻擊者能夠讀取本來(lái)不應(yīng)該被讀取的部分, 導(dǎo)致了內(nèi)存泄露攻擊; 通過(guò)在普通數(shù)據(jù)區(qū)的溢出修改了控制程序運(yùn)行的指令地址段, 導(dǎo)致了代碼重用攻擊。這些都是權(quán)限劃分不清, 處理方法模糊造成的安全隱患。那么針對(duì)這些問(wèn)題就可以通過(guò)權(quán)限與處理方式再細(xì)化的思想予以解決。假如通過(guò)安全機(jī)制的設(shè)計(jì)能夠?qū)崿F(xiàn)普通數(shù)據(jù)與指令地址在邏輯上或空間上隔離, 將有效的阻止代碼重用攻擊的發(fā)生。
本文介紹了代碼重用攻擊的起源與三種主要的實(shí)現(xiàn)方式。系統(tǒng)化的闡述了目前應(yīng)對(duì)這種攻擊的兩類防御思想: 針對(duì)程序行為的監(jiān)控思想以及增加程序的不可知性的思想, 以及它們?cè)谘芯颗c實(shí)現(xiàn)過(guò)程中遇到的困難與解決方式。其中, 對(duì)程序行為監(jiān)控的思想又可以分為針對(duì)配件頻率的監(jiān)控與程序控制流完整性的監(jiān)控; 增加程序不可知性的思想以ASLR為代表, 介紹了實(shí)現(xiàn)過(guò)程中遇到的問(wèn)題以及能夠使這種安全機(jī)制失效的內(nèi)存泄露攻擊, 并介紹了針對(duì)內(nèi)存泄露攻擊的防御機(jī)制。最后, 對(duì)這兩類防御思想進(jìn)行了深入且詳細(xì)的分析, 并提出了一種新的能夠提升對(duì)代碼重用攻擊防御效果的安全機(jī)制設(shè)計(jì)思想。
[1] V. van der Veen , N. dutt-Sharma , L. Cavallaro , and H. Bos. “Memory errors: The past, the present, and the future,” in, pp. 86-106, 2012.
[2] “Smashing the stack for fun and profit.” Aleph One. http://insecure. org/stf/smashstack.html, 2000.
[3] M. Russinovich. “Windows internals.”, 2009.
[4] V. De Ven Arjan. “New security enhancements in red hat enterprise linux v.3, update 3”., 2004.
[5] Microsoft. “Data Execution Prevention (DEP).” http:// windows.microsoft.com/en-us/windows-vista/data-execution-prevention-frequently-asked-questions#, 2001.
[6] C0ntex. “Bypassing non-executable-stack during exploitation using return-to-libc”, http://css.csail.mit.edu/6.858/2014/readings/ return-to-libc.pdf, 2005.
[7] Nergal. “The advanced return-into-lib(c) exploits (pax case study).”, 58(4): 54. http://phrack.org/issues/ 58/4.html Dec.2001.
[8] T. Kornau “Return oriented programming for the ARM architecture.”, 2009.
[9] H. Shacham. “The geometry of innocent flesh on the bone: Returninto-libc without function calls (on the x86).” In Proc., pp. 552-561, 2007.
[10] T. Bletsch, X. Jiang, V.Freh, and Z. Liang. “Jump Oriented Programming:A New Class of Code-Reuse.” in Proc.. pp. 30-40, 2011.
[11] S. El-Sherei, Return-to-libc,https://www.exploit-db.com/docs/ 28553. pdf.
[12] Wikipidia, “Return-to-Libc Attack.” https://en.wikipedia.org/wiki/ Return-to-libc_attack. Aug. 2015.
[13] M. Tran, M. Etheridge,X. Jiang, T. Bletsch, and N. Peng. “On the expressiveness of return-into-libc Attacks” inpp. 121-141, 2011.
[14] R. Roemer ,E. Buchanan ,H. Shacham,. “Return-Oriented Programming System,Languages, and Applications”: Volume 15 Issue 1, March 2012.
[15] N. Carlini ,D. Wagner. “ROP is still dangerous: Breaking modern defenses” inpp. 385-399, 2014.
[16] L. Davi, A. Sadeghi, D. Lehmann. and F. Monrose, “Stitching the Gadgets On the Ineffectiveness of Coarse-Grained Control-Flow Integrity Protection” in, pp. 401-416, 2014.
[17] S. Checkoway, L. Davi, A. Dmitrienko, and H. Shacham. “Return-oriented programming without returns” in, pp. 559-572, 2010.
[18] R. Bosman, H. Bos. “Framing Signals:A Return to Portable Shellcode” inProc.,pp. 243-258, 2014.
[19] F. Schuster, T. Tendyck, C. Liebchen, L. Davi, A. Sadeghi. and T. Holz. “Counterfeit Object-Oriented Programming: On the difficulty of Preventing Code Reuse Attacks in C++ Applications,” in. pp. 745-762, 2015
[20] V. Pappas, M. Polychronakis, and A. D. Keromytis. “Transparent ROP Exploit Mitigation using Indirect Branch Tracing,” in., pp. 447-462, 2013.
[21] Y. Cheng,Z. Zhou, and M. Yu. “ROPecker: A generic and practical for defending against ROP attacks” in Proc.Symposium. 2014
[22] E. Athanasopoulos,M. Polychronakis,H. Bos, “Size Does Matter: Why Using Gadget-Chain Length to Prevent Code-Reuse Attacks is Hard” in, pp. 417-432, 2014
[23] M. Abadi, M. Budiu, J. Ligatti, and U. Erlingsson. “Control-Flow Integrity” inpp.340-353, 2005.
[24] M. Abadi, M. Vrable,M. Budiu, and U. Erlingsson. “XFI Software Guards for System Address Spaces” in,, pp. 75-88, 2006.
[25] Z. Wang, X. Jiang. “HyperSafe A Lightweight Approach to Provide Lifetime Hypervisor Control Flow” in. pp. 380-395 , 2010.
[26] L. Davi, R. Dmitrienko, M. Egele, T. Fischer, T. Holz, R Hund, S. Nurnberger, and A Sadeghi.“: A Framework to Mitigate Control-Flow Attacks on Smartphones” in. 2012.
[27] J. Pewny, T. Holz. “Control-flow Restrictor: Compiler-based CFI for iOS”. Inthe, pp. 309-318, 2013.
[28] J. Tang. “Exploring Control Flow Guard in Windows 10”, http://sjc1-te-ftp.trendmicro.com/assets/wp/exploring-control-flow-guard-in-windows10.pdf, Jan. 2015.
[29] B. Niu,G. Tang. “Modular Control-Flow Integrity” in, pp. 577-587, 2014.
[30] L. Davi, P. Koeberl, and A. Sadeghi. “Hardware-Assisted Fine-Grained Control-Flow Integrity:Towards Efficient Protection of Embedded Systems Against Software Exploitation” in, pp.1-6, 2014.
[31] M. Budiu, U. Erlingsson, and M. Abadi. “Architectural Support for Software-Based Protection” in Proc. the 1st workshop on Architectural and system support for improving software dependability. (ASID’06), pp. 42-51, 2006.
[32] B. Zeng, T. Gang. and G. Morrisett. “Combining Control-Flow Integrity and Static Analysis for Efficient and Validated Data Sandboxing” in Proc..pp. 29-40, 2011.
[33] C. Tice,T. Roeder, S.Checkoway, U.Erlingsson, L. Locano, G. Pike, and P. Collingbournel. “Enforcing Forward-Edge Control-Flow Integrity in GCC & LLVM” inpp. 941-955, 2014.
[34] C. Zhang, T. Wei. Z. Chen, L. Duan, L. Szekeres, S. McCamant, D. Song, and W. Zou. “Practical Control Flow Integrity & Randomization for Binary Executables” in, pp. 559-573, 2013.
[35] Y. Xia,Y. Liu,H. Chen, and B. Zang. “CFIMon: Detecting Violation of control flow integrity using performance counters” in Proc., pp. 1-12, 2012.
[36] M. Zhang,R. Sekar. “Control flow integrity for COTS binaries.” in, pp. 337-352, 2013.
[37] J. Criswell, N. Dautenhahn, and V. Adve. “KCoFI: Complete control-flow integrity for commodity operating system kernels.” in Proc. The 2014,, pp. 292-307, 2014.
[38] W. Dai, Z. Liu, Y.H. Liu. “Function Pointer Attack Detection with address integrity checking”. Vol. 35, No. 2, pp. 424-429, 2015. (代偉, 劉智, 劉益和, “基于地址完整新檢查的函數(shù)指針攻擊檢測(cè)”,, 2015,35(2):424-429.)
[39] E. Athanasopoulos.H. Bos,G. Portokalidis, and E. Goktas. “Out of Control Overcoming Control-Flow Integrity” in, pp. 575-589, 2014.
[40] N. Carlin,A. Barresi,D. Wagner, M. Payer, and T. R. Gross. “Control-Flow Bending:On the Effectiveness of Control-Flow Integrity” in, pp. 161-176, 2015.
[41] C. Liebchen, M. Nergro, P. Larsen, M. Conti, S. Crane, L. Davi, M. Franz, M. Qunaibit, A. Sadeghi. “Losing Control : On the Effectiveness of Control-Flow Integrity under Stack Attacks” inpp. 952-963, 2015.
[42] I. Evans, F. Long, H. Shrobe, U. Otgonbaatar, and M. Rinard. “Control Jujutsu: On the Weaknesses of Fine-Grained Control Flow Integrity” in, pp. 901-913, 2015.
[43] A. Bittau, D. Boneh,D. Mazieres, and A.J.Mashtizadeh. “CCFI: Cryptographically Enforced Control Flow Integrity” in, pp. 941-951, 2015.
[44] D. Andriesse,V. Veen, B. Gras, H. Bos, L. Sambuc, A. Slowinska, and C. Giuffrida. “Practical Context-Sensitive CFI” in, pp. 927-940, 2015.
[45] PAX Team. “Address Space Layout Randomization” http://pax. grsecurity.net/docs/aslr.txt, 2003.
[46] H. Shacham,M. Page, B. Ptaff, E. Goh, N. Modadugu, and D. Boneh. “On the Effectiveness of Address-Space Randomization” in, pp. 298-307, 2004.
[47] G. Roglia, L. Martignoni, R. Paleari, and D. Bruschi. “Surgically Returning to Randomized Lib(c)” in, pp. 60-69, 2009.
[48] M. Backes, S. Nurnberger. “Oxymoron: Making Fine- Grained Memory Randomization Practical by Allowing Code Sharing” in, pp. 433-447, 2014.
[49] K. Snow, F. Monrose, L. Davi, A. Dmitrienko, C. Liebchen, and A. Sadeghi. “Just-In-Time Code Reuse:On the Effectiveness of Fine-Grained Address Space Layout Randomization” in Proc. the 2013 IEEE Symposium on Security and Privacy.(SP’13), pp. 574-588, 2013.
[50] J. Hiser, M. Co, M. Hall, A. Nguyen-Tuong, and J. Davidson. “ILR: Where’d My Gadgets Go?” in, pp. 571-585, 2012.
[51] V. Pappas, M. Polychronakis, and A. Keromytis. “Smashing the Gadgets: Hindering ROP Programming Using In-Place Code Randomization” in, pp. 601-615, 2012.
[52] R. Wartel, V. Mohan, K. Halen, and Z. Lin. “Binary Stirring: Self-randomizing Instruction Addresses of Legacy x86 Binary Code” in, pp. 157-168, 2012.
[53] L. Davi, A. Dmitrienko, A. Sadeghi, and S. Nurnberger. “Gadge Me If You Can: Secure and Efficient Ad-hoc Instruction-Level Randomization for X86 and ARM” in, pp. 299-310, 2013.
[54] L. Davi, C. Liebchen, A. Sadeghi, K. Snow, and F.Monrose. “Isomeron: Code Randomization Resilient to (Just-In-Time) Return-Oriented Programming” in, 2015
[55] L. Xiao. “The Design and Implementation of a Function Lever Randomization Defensing Method against ROP Attack [Master Degree Thesis],” Nanjing:Software School,Nanjing University, 2013. (肖亮.一種針對(duì)ROP攻擊的函數(shù)粒度隨機(jī)化防御方法的設(shè)計(jì)與實(shí)現(xiàn)[碩士學(xué)位論文]. 南京: 南京大學(xué)軟件學(xué)院, 2013.)
[56] X. Zhan. “The Research of Defending ROP Attacks Using Basic Block Level Randomization [Master Degree Thesis],” Nanjing: Software School, Nanjing University, 2014. (詹珣. 針對(duì)ROP攻擊的塊粒度地址空間隨機(jī)化防御技術(shù)的研究[碩士學(xué)位論文]. 南京: 南京大學(xué)軟件學(xué)院, 2014)
[57] S. Crane, C. Lirbchen, A. Homescu, L. Davi, P. Larsen, A. Sadeghi, S. Brunthaler, and M. Franz. “Readactor: Practical Code Randomization Resilient to Memory Disclosure” in. 2015
[58] M. Backes, T. Holz, B. Kollenda, P. Koppe, S. Nurnberger, and J. Pewny. “You Can Run but You Cant Read Preventing Disclosure Exploits in Executable Code” in, pp. 1342-1353, 2014.
[59] A. Tang, S. Sethumadhavan, S. Stolfo, “Heisenbyte: Thwarting Memory Disclosure Attacks using Destructive Code Reads” in, pp. 256-267, 2015.
[60] K. Lu, C. Song, W. Lee, S. Chung, T. Kim, and W. Lee. “ASLR-Guard:Stopping Address Space Leakage for Code Reuse Attacks” in, pp. 280-291, 2015.
[61] C. Yang, Q.X. Wang, Q. Wei, “Code Reuse Attack Mitigation Based on Unreadable Property of Executable Memory”, Journal of Information Engineering University. Vol. 17, No. 1, 2016.(楊超, 王清賢, 魏強(qiáng), “基于可執(zhí)行內(nèi)存不可讀屬性的防代碼重用技術(shù)”,, 2016,17(1):59-64.)
柳童 于2013年在西安電子科技大學(xué)計(jì)算機(jī)科學(xué)與技術(shù)專業(yè)獲得學(xué)士學(xué)位?,F(xiàn)在中國(guó)科學(xué)院信息工程研究所系統(tǒng)結(jié)構(gòu)專業(yè)攻讀博士學(xué)位。研究領(lǐng)域?yàn)橛?jì)算機(jī)系統(tǒng)安全。研究興趣包括代碼重用攻擊、系統(tǒng)防御等。Email: liutong9017@iie.ac.cn史崗 于2004年在中國(guó)科學(xué)院計(jì)算技術(shù)研究所計(jì)算機(jī)體系結(jié)構(gòu)專業(yè)獲得博士學(xué)位?,F(xiàn)任中國(guó)科學(xué)院信息工程研究所第五研究室高級(jí)工程師。研究領(lǐng)域?yàn)橛?jì)算機(jī)系統(tǒng)安全。研究興趣包括計(jì)算機(jī)架構(gòu), 計(jì)算機(jī)芯片安全等。Email: shigang@iie.ac.cn 孟丹 于1995年在哈爾濱工業(yè)大學(xué)獲得計(jì)算機(jī)體系結(jié)構(gòu)專業(yè)博士學(xué)位?,F(xiàn)任中國(guó)科學(xué)院信息工程研究所所長(zhǎng)。研究領(lǐng)域包括計(jì)算機(jī)系統(tǒng)安全, 大數(shù)據(jù)與云計(jì)算等。研究興趣包括計(jì)算機(jī)系統(tǒng)安全, 云計(jì)算安全等。Email: mengdan@iie.ac.cn
A Survey of Code Reuse Attack and Defense Mechanisms
LIU Tong1, 2, SHI Gang1, MENG Dan1
1Institute of Information Engineering, Chinese Academy of Science, Beijing 100093, China2University of Chinese Academy of Science, Beijing 100049, China
Due to the wide existence of vulnerabilities in computer programs such as C and C++, computer systems is vulnerable to be tampered by adversary changing the original running states. Researchers have made great efforts and take some effective protection mechanisms, for instance, Data Execution Prevention and Address Space Layout Randomization. These security mechanisms have a great effect against the primitive attack patterns like code-injection attack. However, the security of computer system is still not optimistic. Though the adversary could not inject their own codes into the memory then run them ever again, they began to use the original benign codes in the memory, manipulate them to achieve malicious purpose by changing their order of operating, which is called code-reuse attack. And it is able to bypass a variety of security mechanisms of commodity computer systems, thus it has become a major threat and the main pattern of hacking. For this reason, researches about code-reuse attack have been taken up in recent years. This paper illustrates the origin of code-reuse attack and achieved way of attack, summarizes the existing defense mechanisms and simply evaluates these defense mechanisms systematically. Meanwhile, this paper analyzes briefly the basic reason of code reuse attack and puts forward an new idea of defense mechanism designing.
computer system security; memory security; code-reuse attack
TP309.2
柳童, 博士研究生, Email: liutong9017@iie.ac.cn。
2016-2-24; 修改日期: 2015-4-14; 定稿日期: 2016-4-18
DOI號(hào) 10.19363/j.cnki.cn10-1380/tn.2016.02.002