一種抵御代碼重用攻擊的方法
【技術(shù)領(lǐng)域】
[0001]本發(fā)明涉及應(yīng)用軟件的安全和防護(hù)(Security and Protect1n)技術(shù)領(lǐng)域以及代碼生成(Code generat1n)技術(shù)領(lǐng)域,具體地說,本發(fā)明涉及一種抵御代碼重用攻擊的方法。
【背景技術(shù)】
[0002]為了抵御代碼注入攻擊(code inject1n),計(jì)算機(jī)系統(tǒng)中引入了數(shù)據(jù)執(zhí)行保護(hù)機(jī)制(data execut1n prevent1n,DEP),限定任何一塊內(nèi)存區(qū)的屬性為W ? X,該機(jī)制使得攻擊者上載的惡意代碼(shell code)無法執(zhí)行。DEP機(jī)制可參考:Pax.homepage ofthe pax team, 2001.http://pax.grsecurity.net。作為回應(yīng),攻擊者則提出代碼重用攻擊(code reuse),該攻擊手段能夠有效繞過DEP機(jī)制。代碼重用攻擊方案中,攻擊者會首先獲得目標(biāo)機(jī)器的代碼布局,然后通過精心構(gòu)造載體(payload)利用目標(biāo)機(jī)器的間接跳轉(zhuǎn)(indirect jmp)、間接調(diào)用(indirect call)和函數(shù)返回指令(ret),將目標(biāo)機(jī)器的代碼片段編織起來,進(jìn)而實(shí)現(xiàn)攻擊者所需的功能。返回Iibc庫函數(shù)(Return-to-libc)和面向return的編程(Return-Oriented Programming, ROP)是兩種最為典型的代碼重用攻擊手段。Return-to-libc通過緩沖區(qū)溢出(buffer overflow)覆蓋桟上的返回地址來改變程序的執(zhí)行流,將控制轉(zhuǎn)移到一個特定的庫函數(shù)中。ROP則利用代碼中的gadget (以ret、indirect jmp和indirect call指令為結(jié)尾的指令序列)組成載體并通過緩沖區(qū)溢出執(zhí)行載體來完成攻擊者的意圖。
[0003]代碼重用攻擊的前提條件是要掌握目標(biāo)機(jī)器上代碼的布局。因此人們又提出了地址隨機(jī)化(Address Space Layout Randomizat1n, ASLR)的方案來抵御代碼重用攻擊的。目前,地址隨機(jī)化方法已經(jīng)部署到大多數(shù)主流操作系統(tǒng)中,其具體做法是在裝載應(yīng)用時,系統(tǒng)為各個模塊隨機(jī)加載地址,這樣攻擊者就無法推斷出應(yīng)用運(yùn)行時的代碼布局情況。為了進(jìn)一步增加攻擊者破解代碼布局的難度,人們還探討了更加細(xì)粒度(fine-grained)的隨機(jī)化方法,如函數(shù)級別(Funct1n-level)、基本塊級別(BasicBlock-1evel)、指令級別(Instruct1n-level)的隨機(jī)化方法。
[0004]然而,商業(yè)軟件常常存在內(nèi)存泄露(memory disclosure)漏洞,攻擊者利用這種漏洞可以動態(tài)讀取被攻擊程序的內(nèi)存,進(jìn)而突破DEP+ASLR機(jī)制的防御能力。也就是說,即使一個系統(tǒng)同時部署了 ASLR和DEP機(jī)制,攻擊者依然可以利用內(nèi)存泄露漏洞,對隨機(jī)化后的代碼布局進(jìn)行破解,然后對系統(tǒng)發(fā)動代碼重用攻擊,從而獲得目標(biāo)機(jī)器的控制權(quán)。利用內(nèi)存泄露發(fā)動代碼重用攻擊的方法有JIT-ROP方案等(可參考K.Snow, F.Monrose, L.Davij A.DmitrienkojC.Liebchenj and A.Sadegh1.Just-1n-time code reuse: On theeffectiveness of fine-grained address space layout randomizat1n.1n Securityand Privacy (SP), 2013IEEE Symposium on, pages 574-588, May 2013.)。JIT-ROP 可以對付任意粒度的ASLR,其方法是從程序某一處開始,讀取該代碼所在的內(nèi)存頁,然后反匯編分析該頁可能跳轉(zhuǎn)/調(diào)用的其它代碼頁,依據(jù)這些信息,讀取對應(yīng)代碼頁的內(nèi)容。反復(fù)上述過程,就可以獲得所有的代碼頁,從而實(shí)現(xiàn)對代碼布局的破解。完成代碼布局破解后,再通過JIT編譯技術(shù),構(gòu)造ROP載體再配合緩沖區(qū)溢出漏洞實(shí)現(xiàn)代碼重用攻擊。
[0005]基于內(nèi)存泄露漏洞的代碼重用攻擊給應(yīng)用系統(tǒng)帶來了嚴(yán)重威脅,為了抵御這種攻擊,人們在多個方向展開了相應(yīng)的研究,包括:阻止攻擊者利用內(nèi)存泄露讀取代碼;執(zhí)行路徑多樣化;持續(xù)地進(jìn)行隨機(jī)化。
[0006]阻止攻擊者利用內(nèi)存泄露漏洞讀取代碼的防御方法有:XnR方法、HideM方法和Readactor方法等。上述三種防御方法主要解決的是如何在維護(hù)代碼頁可執(zhí)行權(quán)限的情況下,阻止處理器對代碼頁進(jìn)行有害的讀操作。下面以XnR方法為例進(jìn)行說明。XnR方法的主要思想是通過修改內(nèi)核內(nèi)存管理(MMU)相關(guān)代碼取消掉進(jìn)程中所有代碼頁的映射,因此當(dāng)進(jìn)程訪問代碼頁時會產(chǎn)生頁面異常(Page Fault)。XnR方案中,基于Page Fault捕捉到進(jìn)程對代碼頁的訪問,然后做如下處理:如果是執(zhí)行請求就正常執(zhí)行操作系統(tǒng)的缺頁異常處理;如果是讀請求就報錯殺掉當(dāng)前進(jìn)程。代碼頁在頁表中的映射關(guān)系建立起來以后,該頁就長時間具有可讀可執(zhí)行權(quán)限。為了能夠再次捕捉到這些代碼頁的讀操作,XnR方案中設(shè)置了一個滑動窗口,在某些時刻取消掉已經(jīng)建立好的映射關(guān)系,從而避免代碼頁長時間具有可讀可執(zhí)行權(quán)限。然而在滑動窗口內(nèi),還是有很多內(nèi)存頁是即可執(zhí)行又可讀的,如果攻擊者在滑動窗口內(nèi)進(jìn)行攻擊,XnR方案仍然是無法防御的。
[0007]執(zhí)行路徑多樣化的防御方法以Isomeron多樣化方法為代表。該方法的主要思想都是執(zhí)行流多樣化,使攻擊者生成的載體不能夠按照原有攻擊語意執(zhí)行。該方法在內(nèi)存中加載兩份不同版本的代碼,其中一個保存有原有代碼的布局,另一個是隨機(jī)化后的版本。它對所有的indirect call、ret和indirect jmp指令進(jìn)行動態(tài)插粧,然后在運(yùn)行時決定跳轉(zhuǎn)的目標(biāo)是原有版本代碼還是隨機(jī)后的代碼版本。由于攻擊者并不知道這三類指令會跳轉(zhuǎn)到哪個版本,因此攻擊者上傳的載體在執(zhí)行時可能會出錯。理論上載體有能夠正確執(zhí)行的可能性,但是概率非常低,僅為0.5的η次方(η為載體使用的gadget數(shù)量)。然而,Isomeron執(zhí)行流多樣化方法需要在跳轉(zhuǎn)指令處進(jìn)行擲骰子選擇跳轉(zhuǎn)目標(biāo),因此該方法存在開銷非常大的問題。又由于Isomeron方案需要進(jìn)行動態(tài)插粧,因此它還會破壞DEP防護(hù)機(jī)制,帶來另外的安全隱患。
[0008]Cristiano Giuffrida提出了一種基于重新設(shè)計(jì)內(nèi)核的持續(xù)隨機(jī)化方法。該方法重新設(shè)計(jì)了自己的操作系統(tǒng)內(nèi)核Minix microkernel,由專門的內(nèi)核隨機(jī)線程對其它內(nèi)核線程進(jìn)行持續(xù)隨機(jī)化。其做法是基于LLVM框架,由編譯器通過對操作系統(tǒng)源碼進(jìn)行編譯生成比特碼(Bitcode)。在操作系統(tǒng)運(yùn)行過程中,周期性地由JIT編譯器生成新代碼。該方法會在形成的每個版本的代碼中插入同步點(diǎn),隨機(jī)線程會發(fā)送信息(message)通知舊版本停下來(停在同步點(diǎn)),然后利用內(nèi)核線程將原有線程的狀態(tài)迀移到新線程上執(zhí)行,最后銷毀原有線程。該方法不僅有效地改變了進(jìn)程內(nèi)存代碼布局而且還可以低開銷地防御代碼重用攻擊。然而,由于Cristiano Giuffrida方案需要修改整個操作系統(tǒng)的內(nèi)核來支持其部署LLVM的JIT編譯器等,因此無法在已有操作系統(tǒng)上進(jìn)行部署。又由于該方法需要源代碼的支持,因此也不能有效部署到應(yīng)用層下(主要原因有:版權(quán)保護(hù),商業(yè)機(jī)密和遺產(chǎn)代碼等)。
【發(fā)明內(nèi)容】
[0009]因此,本發(fā)明的任務(wù)是克服現(xiàn)有技術(shù)的缺陷,提供一種抵御代碼重用攻擊的解決方案。
[0010]本發(fā)明提供了一種抵御代碼重用攻擊的方法,包括下列步驟:
[0011 ] I)在工作進(jìn)程運(yùn)行過程中,洗牌進(jìn)程生成工作進(jìn)程的新版本代碼并將其存入代碼緩存區(qū),所述代碼緩存區(qū)被工作進(jìn)程和洗牌進(jìn)程所共享,對于工作進(jìn)程,所述代碼緩存區(qū)的權(quán)限被設(shè)置為可讀可執(zhí)行但不可寫,對于洗牌進(jìn)程,所述代碼緩存區(qū)的權(quán)限被設(shè)置為可讀可寫不可執(zhí)行;所述洗牌進(jìn)程不對外提供服務(wù);這樣就可以利用共享內(nèi)存機(jī)制動態(tài)生成或修改代碼來維護(hù)工作進(jìn)程的DEP防護(hù)機(jī)制,進(jìn)而阻止代碼注入攻擊;
[0012]2)所述工作進(jìn)程完成新舊版本代碼的切換。
[0013]其中,所述步驟I)中,所述新版本代碼做隨機(jī)化處理確保新代碼的布局與之前的舊代碼不同。
[0014]其中,所述步驟I)之前,所述洗牌進(jìn)程在啟動時進(jìn)行初始化,包括:洗牌進(jìn)程對工作進(jìn)程的所有代碼段進(jìn)行反匯編并記錄下中間表示,識別代碼段中的函數(shù)信息,分析函數(shù)內(nèi)的執(zhí)行流并劃分basic block (基本塊)。
[0015]其中,所述步驟I)中,所述新版本代碼的生成方法包括下列子步驟:
[0016]11)對舊版本代碼的函數(shù)內(nèi)的基本塊進(jìn)行亂序處理;
[0017]12)在基本塊內(nèi)部隨機(jī)插入一些無關(guān)指令,得到新版本代碼。
[0018]其中,所述步驟2)包括下列子步驟:
[0019]21)洗牌進(jìn)程觸發(fā)工作進(jìn)程中斷;
[0020]22)洗牌進(jìn)程將工作進(jìn)程由舊版本代碼迀移