馬夢(mèng)雨 , 陳李維 , 史 崗 , 孟 丹
1中國(guó)科學(xué)院信息工程研究所 北京 中國(guó) 100093
2中國(guó)科學(xué)院大學(xué) 網(wǎng)絡(luò)空間安全學(xué)院 北京 中國(guó) 100049
攻擊者利用軟件漏洞控制應(yīng)用程序的行為和邏輯, 進(jìn)而通過(guò)提權(quán)威脅計(jì)算機(jī)系統(tǒng)的安全。傳統(tǒng)的代碼注入攻擊通過(guò)外部輸入的方式在程序內(nèi)存中存儲(chǔ)惡意代碼, 同時(shí)利用軟件漏洞劫持程序控制流轉(zhuǎn)向惡意代碼。但是研究者提出的數(shù)據(jù)執(zhí)行保護(hù)(Data Execution Prevention, DEP)能夠從本質(zhì)上緩解代碼注入攻擊, DEP規(guī)定所有可寫(xiě)的內(nèi)存頁(yè)不可執(zhí)行, 因此用戶輸入的惡意代碼僅僅被當(dāng)作數(shù)據(jù), 即使程序指針跳轉(zhuǎn)到惡意代碼所在的內(nèi)存頁(yè), 攻擊也無(wú)法繼續(xù)執(zhí)行。隨后, 研究者提出了代碼重用攻擊(Code Reuse attack, CRA), 它使用程序中原有的指令片段替代外部輸入的指令, 從而繞過(guò) DEP的防御。根據(jù)重用指令的不同可分為返回導(dǎo)向編程(Return-oriented Programming, ROP)[1]和跳轉(zhuǎn)導(dǎo)向編程(Jump-oriented Programming, JOP)[2]兩種主流攻擊方式。如今, CRA逐漸取代代碼注入成為主要的攻擊手段。
CRA的核心思想是重用程序中已經(jīng)存在的指令,這些指令能夠完成一定的計(jì)算或賦值等功能, 然后以ret指令或jmp指令結(jié)尾構(gòu)成一段指令片段, 稱之為配件(Gadget), 多個(gè)配件相連構(gòu)成惡意的shellcode。攻擊者通過(guò)軟件漏洞劫持程序控制流轉(zhuǎn)向第一個(gè)配件的地址, 系統(tǒng)就會(huì)自動(dòng)地執(zhí)行配件鏈完成攻擊。CRA被證明是圖靈完備的[2], 且能夠通過(guò)固定的模式形成自動(dòng)化的攻擊工具[3], 因此 CRA具備容易使用、難以防御、圖靈完備的特性。隨后, 研究者提出的控制流完整性(Control Flow Integrity,CFI)[4-5]理論上能夠完全防御ROP和JOP兩種主流攻擊方式, CFI首先分析程序中的所有合法執(zhí)行路徑并生成控制流圖(Control Flow Graph, CFG), 其次在CFG路徑上添加標(biāo)記信息, 最后嚴(yán)格按照CFG執(zhí)行程序, 因此攻擊者無(wú)法隨意更改控制流, 也就打斷了配件鏈的執(zhí)行過(guò)程。但是 CFI有兩個(gè)主要的缺點(diǎn),第一, 較高的復(fù)雜性造成近百分之五十的系統(tǒng)開(kāi)銷(xiāo)[4];第二, 構(gòu)建完善且精確的CFG幾乎不可能實(shí)現(xiàn)。
為了解決 CFI的兩個(gè)主要問(wèn)題, 研究者提出了很多實(shí)際的解決方案[6-9]。制定更為寬松的CFI策略來(lái)降低系統(tǒng)的性能開(kāi)銷(xiāo), 首先, 通過(guò)分析普通程序的合法控制流轉(zhuǎn)移, 總結(jié)出一些控制流轉(zhuǎn)移規(guī)律,例如call指令應(yīng)該指向一個(gè)函數(shù)入口的地址等; 其次,不依賴完整的 CFG, 而是利用這些規(guī)律識(shí)別目標(biāo)程序中合法與非法的執(zhí)行路徑。這些寬松的 CFI策略被稱之為粗粒度CFI, 它并沒(méi)有構(gòu)建程序的CFG, 而是從中抽取控制流轉(zhuǎn)移的規(guī)律來(lái)制定相應(yīng)的規(guī)則,雖然降低了系統(tǒng)性能開(kāi)銷(xiāo), 但其安全保障要低于基于 CFG的原始 CFI, 最近也有很多學(xué)者提出使用特殊配件繞過(guò)粗粒度CFI的方案[10-13]。
我們分析現(xiàn)有能夠被CRA利用的配件, 發(fā)現(xiàn)配件的幾個(gè)特征如下: 僅僅占據(jù)整個(gè)代碼空間的很小一部分; 在普通程序中很少出現(xiàn)且不連續(xù); 在 CRA中連續(xù)出現(xiàn)并形成配件鏈。因此, 我們能夠通過(guò)監(jiān)控程序運(yùn)行時(shí)的配件特征來(lái)區(qū)分普通和惡意程序, 如圖1所示。
本文提出配件加權(quán)標(biāo)記(Gadget Weighted Tagging, GWT)的思想, 一種靈活地檢測(cè)并防御CRAs的防御機(jī)制。首先, 我們根據(jù)配件在CRA中發(fā)揮的作
圖1 普通程序和CRA的配件分布規(guī)律Figure 1 The Gadget Distribution in Normal Programs and CRAs
用, 把所有可能的配件分成三種主要類(lèi)型: 功能配件, NOP配件和普通代碼; 其次, 我們?yōu)椴煌?lèi)型的配件分配不同的權(quán)值, 并在二進(jìn)制文件中附加對(duì)應(yīng)的權(quán)值標(biāo)記; 最后, 在程序運(yùn)行時(shí)監(jiān)控各類(lèi)配件權(quán)值的累加值, 當(dāng)這個(gè)值超過(guò)設(shè)定的閾值時(shí), GWT判斷為發(fā)生CRA。除此之外, 我們還提出了GWT結(jié)合粗粒度CFI的思想, 因?yàn)槲覀儼l(fā)現(xiàn)粗粒度CFI對(duì)控制流轉(zhuǎn)移的策略是對(duì) GWT很好的補(bǔ)充, 采用GWT+CFI可以更精準(zhǔn)的識(shí)別配件并且完善框架的安全策略。
GWT的實(shí)現(xiàn)依賴一些重要的參數(shù), 如不同配件類(lèi)型對(duì)應(yīng)的權(quán)值, 用戶可根據(jù)實(shí)際需求對(duì)這些參數(shù)進(jìn)行調(diào)整并重新配置。同時(shí)如果用戶需要添加一些新的特殊配件, 也可以在GWT中添加相應(yīng)的配件類(lèi)型并分配權(quán)值。正是因?yàn)镚WT具備靈活的可擴(kuò)展性,所以 GWT能夠檢測(cè) CRA的多種利用方式, 而且GWT的安全性也能夠隨著配件類(lèi)型的不斷完善而逐漸加強(qiáng)。當(dāng)研究者提出一種新的CRA方式或配件類(lèi)型時(shí), 通常會(huì)介紹攻擊的構(gòu)建方法或配件的尋找算法, 所以GWT可以重用這些方法或算法找到程序中可能存在的配件, 完善其配件類(lèi)型和安全策略。我們基于軟件和硬件模擬的設(shè)計(jì)框架實(shí)現(xiàn) GWT以及GWT+CFI系統(tǒng), 結(jié)果表明其性能開(kāi)銷(xiāo)分別為2.31%和3.55%, 并且GWT理論上能夠檢測(cè)使用自動(dòng)化工具 Q[3]生成配件鏈的 CRA, 以及使用特殊配件的新型CRA。
這篇論文的主要貢獻(xiàn)如下:
1) 我們提出一種防御代碼重用攻擊(Code Reuse Attack, CRA)的新型系統(tǒng)化框架: 配件加權(quán)標(biāo)記(Gadget Weighted Tagging, GWT), 具備靈活可配置、高安全性、低開(kāi)銷(xiāo)、易用的特點(diǎn)。
2) 我們提出GWT結(jié)合粗粒度CFI的防御思想,相比基礎(chǔ)的GWT, GWT+CFI尋找配件更加精確。
3) 我們基于軟件和硬件模擬的設(shè)計(jì)框架實(shí)現(xiàn)GWT和GWT+CFI系統(tǒng), 并且評(píng)估了其安全性和性能開(kāi)銷(xiāo)。
本文內(nèi)容組織如下: 第二章節(jié)介紹相關(guān)研究背景, 包括CRA、CFI、合法配件以及威脅模型; 第三和第四章節(jié)分別闡述GWT以及GWT+CFI的基本原理和實(shí)現(xiàn)細(xì)節(jié); 第五章節(jié)為實(shí)驗(yàn)評(píng)估, 包括GWT的安全性分析和性能分析; 第六章節(jié)對(duì)配件分類(lèi)和GWT框架的靈活性進(jìn)行討論; 第七章節(jié)介紹防御CRA的研究現(xiàn)狀; 第八章節(jié)對(duì)全文進(jìn)行總結(jié)。
CRA本質(zhì)就是在已有的代碼空間中尋找具備一定功能的指令片段, 稱之為配件(Gadget), 然后串連配件形成圖靈完備的配件鏈執(zhí)行惡意功能, 比如打開(kāi)一個(gè)非法 Shell。配件通常由幾條具備計(jì)算功能的普通指令加上一條間接轉(zhuǎn)移指令組成, 普通指令完成惡意功能, 間接轉(zhuǎn)移指令劫持程序控制流并串連多個(gè)配件。通過(guò)上述分析, CRA的核心在于配件, 而配件的特征在于結(jié)尾的間接跳轉(zhuǎn)指令, 所以本文關(guān)注三類(lèi)通用的間接轉(zhuǎn)移指令: call, return, indirect-jmp。除此之外, 多數(shù) CRAs中使用的配件還具備以下兩點(diǎn)重要特征:
1) 稀疏的配件分布
配件都是以間接轉(zhuǎn)移指令為結(jié)尾, 然而間接轉(zhuǎn)移指令僅僅占整個(gè)代碼空間的很小一部分, 因此CRA使用的配件在普通程序中的分布應(yīng)該是非常稀少的。
2) 短小的指令片段
通常配件中包含的指令條數(shù)越多, 完成的功能也就越多, 但同時(shí)也不可避免的造成一些副作用,比如寄存器的依賴沖突將會(huì)導(dǎo)致相關(guān)數(shù)據(jù)被覆寫(xiě)。因此攻擊者會(huì)使用簡(jiǎn)單且指令條數(shù)較少的配件來(lái)消除這些副作用[3], 而不是為了完成更多的操作, 選擇冗長(zhǎng)且復(fù)雜的配件。實(shí)際上, 在真實(shí)的 CRA中, 配件的指令數(shù)大約為2~6條[8]。
根據(jù)配件中間接轉(zhuǎn)移指令的不同可以把傳統(tǒng)CRA分為ROP攻擊和JOP攻擊。ROP攻擊依賴棧指針的返回機(jī)制完成控制流的劫持, 多個(gè)配件通過(guò)ret指令跳轉(zhuǎn)相連。JOP攻擊相比ROP要復(fù)雜一些, 因?yàn)樗胍环N新的配件, 稱之為調(diào)度配件(dispatcher gadget), 所以 JOP并不依賴于棧的返回機(jī)制完成攻擊, 而是使用一種調(diào)度表(dispatch table)或具有連接各個(gè)配件功能的結(jié)構(gòu)保存所有配件的地址, 通過(guò)調(diào)度配件劫持程序控制流, 然后驅(qū)動(dòng)調(diào)度表或同等結(jié)構(gòu)中的各個(gè)配件完成攻擊[14]。調(diào)度配件是構(gòu)造 JOP攻擊的關(guān)鍵, 它通常包含一些自修改跳轉(zhuǎn)地址的操作, 并且以indirect-jmp指令結(jié)尾, 相當(dāng)于程序eip指針的作用, 可用過(guò)程1簡(jiǎn)單描述調(diào)度配件的功能[14]。
過(guò)程1. 調(diào)度配件的功能描述PC <—f(PC);GOTO*PC;
CFI作為對(duì)抗CRA的主流防御方法之一, 自然備受研究者關(guān)注, 近年來(lái)也提出了很多實(shí)際的實(shí)施方案[5-9,15]。本文把這些CFI方案大體分類(lèi)兩類(lèi): 基于CFG的CFI和基于策略的CFI。
2.2.1 基于CFG的CFI
基于CFG的CFI, 也稱之為細(xì)粒度CFI, 通過(guò)靜態(tài)分析生成 CFG, 并嚴(yán)格按照 CFG執(zhí)行程序, 具備很高的安全性, 理論上能夠檢測(cè)任何非法的控制流劫持。但是, 僅僅通過(guò)靜態(tài)分析幾乎不可能生成包含所有可達(dá)路徑的理想 CFG, 且細(xì)粒度 CFI的性能開(kāi)銷(xiāo)很大[4]。正因?yàn)樯鲜霾蛔? 近幾年一些研究者提出了針對(duì)基于保守CFG的CFI的繞過(guò)方法[16,17], 更有研究者表明即使能夠生成理想的 CFG, 也可以通過(guò)污染非控制數(shù)據(jù)使得控制流合法轉(zhuǎn)移, 繞過(guò)基于理想CFG的CFI[18]。
2.2.2 基于策略的CFI
基于策略的 CFI, 也稱之為粗粒度 CFI, 它并不依賴靜態(tài)生成的 CFG, 而是通過(guò)制定一些控制流轉(zhuǎn)移的規(guī)則來(lái)防御多數(shù)CRAs, 即依據(jù)普通程序的合法控制流轉(zhuǎn)移規(guī)律來(lái)制定安全策略, 因此粗粒度 CFI具備低開(kāi)銷(xiāo), 易部署的優(yōu)勢(shì)。這些規(guī)則大體上可分為以下兩類(lèi):
1) 控制流轉(zhuǎn)移策略: 這些策略主要規(guī)定不同間接轉(zhuǎn)移指令的合法目的地址[7,19]。
RETURN指令 一條return指令應(yīng)當(dāng)指向call指令的下一條指令(call-preceded指令)。
CALL指令 一條 call指令應(yīng)當(dāng)指向一個(gè)函數(shù)開(kāi)始執(zhí)行的第一條指令(函數(shù)入口指令)。
Indirect-JUMP指令 一條indirect-jmp指令要么指向所在函數(shù)地址范圍內(nèi)的任意一條指令, 那么指向其他函數(shù)開(kāi)始執(zhí)行的第一條指令(函數(shù)入口指令)。
2) 代碼長(zhǎng)度策略: 這些策略規(guī)定單一配件的長(zhǎng)度, 以及完成CRA使用的配件鏈長(zhǎng)度[8,9]。
配件長(zhǎng)度 考慮單一配件, 除了指令片段應(yīng)當(dāng)以間接轉(zhuǎn)移指令為結(jié)尾, 還應(yīng)當(dāng)滿足包含的指令條數(shù)大致在 2~6的數(shù)量范圍之內(nèi), 更長(zhǎng)的指令片段不再認(rèn)為是配件。
配件鏈長(zhǎng)度 考慮配件鏈中配件數(shù)量的統(tǒng)計(jì)規(guī)律, 通常完成多數(shù)CRAs至少需要六個(gè)配件, 因此更短的配件鏈長(zhǎng)度不再認(rèn)為是CRA。
粗粒度CFI通過(guò)定義一些規(guī)則(如2.2節(jié)中提到的控制流轉(zhuǎn)移和代碼長(zhǎng)度策略)來(lái)識(shí)別程序中哪些代碼片段是合法的指令, 哪些是攻擊者利用的配件。但是, 攻擊者能夠找到繞過(guò)這些規(guī)則的特殊配件(Special Gadgets), 本文稱之為合法配件。因此在CRA中使用合法配件就可以繞過(guò)粗粒度CFI的防御,下面介紹三類(lèi)合法配件的概念:
1) Call-Preceded配件
Call-Preceded指令是指代碼空間中 call指令緊鄰的下一條指令[13]。Call-Preceded配件表示以一條Call-Preceded指令開(kāi)頭的配件類(lèi)型, 因此它能夠符合粗粒度 CFI的控制流轉(zhuǎn)移策略, 作為任何一條return指令的目的地址。
2) Entry-Point配件
Entry-Point配件是指以函數(shù)入口指令為開(kāi)頭的配件類(lèi)型, 因此它能夠符合粗粒度 CFI的控制流轉(zhuǎn)移策略, 作為任何一條call指令或indirect-jmp指令的目的地址。
3) Long-NOP配件
Long-NOP配件是指包含足夠指令數(shù)量的配件類(lèi)型, 且不能和普通配件依賴的數(shù)據(jù)產(chǎn)生沖突。通常Long-NOP配件包含一些如NOP等不修改寄存器的指令, 或者包含一些寫(xiě)內(nèi)存指令(修改無(wú)關(guān)緊要的內(nèi)存地址), 這些指令不會(huì)影響配件鏈的正常功能。因此攻擊者可以使用 Long-NOP配件構(gòu)建更長(zhǎng)的指令片段作為攻擊配件, 以此繞過(guò)粗粒度 CFI中基于代碼長(zhǎng)度的策略。
本文提出的防御機(jī)制主要針對(duì)于各類(lèi)CRAs, 因此我們假設(shè)攻擊者擁有對(duì)數(shù)據(jù)和堆棧的控制權(quán), 同時(shí)能夠修改處理器中通用寄存器的值。對(duì)于攻擊手段, 我們假設(shè)系統(tǒng)中已經(jīng)部署DEP, 因此攻擊者不能夠使用代碼注入攻擊而不得不選擇使用代碼重用的攻擊方式。對(duì)于攻擊目的, 我們假設(shè)主要是為了獲得系統(tǒng)權(quán)限。另外我們假設(shè)攻擊者不使用非對(duì)齊配件,所謂非對(duì)齊配件, 是由不定長(zhǎng)指令集(例如x86平臺(tái))導(dǎo)致對(duì)于相同一段機(jī)器碼, 從不同位置開(kāi)始讀取,得到的指令是不一樣的。而這種情況很容易被 CFI的控制流轉(zhuǎn)移策略檢測(cè)[19], 因此本文不考慮非對(duì)齊配件的情況。原因有兩點(diǎn), 第一, GWT框架要求所有的間接跳轉(zhuǎn)指令之前都接一條預(yù)取指令, 增加了攻擊者尋找非對(duì)齊配件的難度, 如果一個(gè)間接跳轉(zhuǎn)指令之前沒(méi)有預(yù)取指令, 或者預(yù)取指令包含的信息有誤, 我們就可以認(rèn)為這是一個(gè)非對(duì)齊配件; 第二,GWT和粗粒度CFI結(jié)合使用, 規(guī)定了間接跳轉(zhuǎn)指令的目標(biāo)地址(如函數(shù)頭, call指令的下一條指令), 也就避免了非對(duì)齊配件地出現(xiàn)。
為了更好地介紹我們提出的防御方法 GWT, 本文提出了以下兩種不同的系統(tǒng)環(huán)境:
1) 基礎(chǔ)環(huán)境
基礎(chǔ)環(huán)境是指系統(tǒng)中不包含任何其他特殊的防御機(jī)制, 僅僅部署DEP技術(shù)。
2) 保護(hù)環(huán)境
保護(hù)環(huán)境是指系統(tǒng)中除了部署 DEP, 還添加了如2.2節(jié)描述的粗粒度CFI技術(shù), 對(duì)控制流轉(zhuǎn)移進(jìn)行保護(hù)。
本章節(jié)包括兩個(gè)部分, 第一部分在3.1~3.3節(jié)介紹基礎(chǔ)環(huán)境中配件加權(quán)標(biāo)記(Gadget Weighted tagging, GWT)的整體框架, 主要包含三個(gè)步驟: 尋找所有可能被CRA利用的配件; 根據(jù)權(quán)值信息標(biāo)記第一步找到的配件; 程序運(yùn)行時(shí)監(jiān)控權(quán)值標(biāo)記的變化情況, 判斷是否發(fā)生CRA。
第二部分作為對(duì)第一部分的補(bǔ)充, 在3.4節(jié)介紹保護(hù)環(huán)境中 GWT結(jié)合粗粒度 CFI的框架(GWT+CFI)。粗粒度 CFI包含控制流轉(zhuǎn)移策略和代碼長(zhǎng)度策略, 但是GWT中已經(jīng)考慮了配件的長(zhǎng)度和類(lèi)型, 也就是說(shuō)GWT已經(jīng)包含了代碼長(zhǎng)度策略, 所以 GWT要比單獨(dú)考慮代碼長(zhǎng)度策略的防御機(jī)制更加精確[8,9], 因此我們添加控制流轉(zhuǎn)移策略作為GWT的補(bǔ)充即可。
3.1.1 尋找配件的結(jié)尾
因?yàn)榕浼闹饕卣魇且蚤g接轉(zhuǎn)移指令(return,call, indirect-jmp)為結(jié)尾, 所以理論上所有以間接轉(zhuǎn)移指令結(jié)尾的代碼片段都有可能作為配件。因此, 我們首先搜索程序代碼空間中所有的間接轉(zhuǎn)移指令,并把這些指令定義為配件的結(jié)尾。
3.1.2 定義配件類(lèi)型
著名的ROP攻擊框架Q[3]開(kāi)源了一種支持多種架構(gòu)的ROP編譯器, 它能夠根據(jù)Q中定義的配件類(lèi)型判斷一段指令是否屬于配件以及配件的具體類(lèi)型。Q依據(jù)指令片段表示的功能定義不同的配件類(lèi)型,包括NoOp, Jump, MoveReg, LoadConst, Arithmetic,LoadMem, StoreMem, ArithmeticLoad, Arithmetic-Store共九種基本配件類(lèi)型[3], 并提出了一種算法來(lái)識(shí)別每個(gè)配件的類(lèi)型, 且每個(gè)配件應(yīng)當(dāng)僅僅符合定義中的一種功能。
在GWT中, 我們定義四種配件類(lèi)型, 如圖2所示。其中, 功能配件和Q定義的配件類(lèi)型一致, 但不包括NoOp, 調(diào)度配件(Dispatcher Gadget)和系統(tǒng)調(diào)用配件(Syscall Gadget)是功能配件(Functional Gadget)中的兩類(lèi)特殊配件, 并且這兩類(lèi)特殊配件在CRA中具備至關(guān)重要的功能。下面對(duì)具體的配件類(lèi)型進(jìn)行介紹:
圖2 GWT中配件類(lèi)型的分類(lèi)Figure 2 The Gadget Types in GWT
1) 功能配件
在CRA中, 功能配件是穩(wěn)定完成某些實(shí)際操作且不產(chǎn)生任何副作用的指令片段, 例如算數(shù)邏輯運(yùn)算、分支轉(zhuǎn)移、從內(nèi)存讀取數(shù)據(jù)等。GWT中功能配件的定義與Q基本一致, 但不包括NoOp配件。
2) 調(diào)度配件
調(diào)度配件是一種特殊的功能配件, 它在 JOP中扮演重要的角色[14], 包含一些自修改跳轉(zhuǎn)地址的操作, 并且以 indirect-jmp指令結(jié)尾。調(diào)度配件的本質(zhì)就是模擬了一個(gè)虛擬的PC指針, 驅(qū)動(dòng)JOP攻擊的可持續(xù)過(guò)程, 連接一個(gè)又一個(gè)功能配件。
3) 系統(tǒng)調(diào)用配件
系統(tǒng)調(diào)用配件是一種以syscall指令結(jié)尾的特殊功能配件, 攻擊者首先污染rax填充任意系統(tǒng)調(diào)用號(hào),然后結(jié)合系統(tǒng)調(diào)用配件實(shí)現(xiàn)惡意的系統(tǒng)調(diào)用劫持。例如, 為了使 CRA更加簡(jiǎn)單, 攻擊者通過(guò)系統(tǒng)調(diào)用配件陷入內(nèi)核, 強(qiáng)行關(guān)閉一部分內(nèi)存頁(yè)的不可執(zhí)行位(使得 DEP防御失效), 然后向這部分內(nèi)存注入惡意代碼, 最后劫持控制流轉(zhuǎn)向惡意代碼完成攻擊[10]。
4) NOP配件
NOP配件指那些既不產(chǎn)生功能也不產(chǎn)生副作用的配件類(lèi)型, 它包括Q提出的NoOp配件和本文第二章提到的Long-NOP配件。為了確保添加NOP配件不改變CRA配件鏈的原始語(yǔ)義, NOP配件通常只使用很少一部分寄存器[13], 這樣可以避免和功能配件使用的寄存器產(chǎn)生沖突。攻擊者使用NOP配件的目的往往是繞過(guò)一些防御機(jī)制, 例如基于策略的粗粒度CFI[8-9]。
3.1.3 尋找配件的開(kāi)端(最大配件長(zhǎng)度)
根據(jù)配件的組成特點(diǎn), 很容易找到它的結(jié)尾(間接轉(zhuǎn)移指令), 但尋找配件的開(kāi)端相對(duì)困難。根據(jù)之前研究者的工作, 往往通過(guò)代碼的長(zhǎng)度去識(shí)別配件,因?yàn)榕浼拈L(zhǎng)度具有一定的規(guī)律, 過(guò)長(zhǎng)的代碼片段會(huì)產(chǎn)生副作用, 也有可能會(huì)和其他配件相互沖突。通常配件的長(zhǎng)度在2~6條指令之間[8], 但是不排除攻擊者為了躲避一些防御機(jī)制, 使用幾乎對(duì)CRA沒(méi)有副作用的特殊配件(例如Long-NOP配件), 將其插入常規(guī)配件鏈中以躲避基于規(guī)則的防御。
在GWT框架中, 隨著配件長(zhǎng)度的增加, 包含過(guò)多的指令將產(chǎn)生無(wú)法避免的副作用, 所以NOP配件終將變成普通代碼。普通代碼就是無(wú)法被任何CRAs利用的配件, 本文假設(shè)所有不是功能配件和NOP配件的代碼都是普通代碼。類(lèi)似, 若配件包含過(guò)多的指令, 功能配件也終將變成NOP配件或普通代碼。因此, GWT使用每種配件類(lèi)型的最大長(zhǎng)度來(lái)識(shí)別配件的開(kāi)端。下面分析功能配件和NOP配件的最大長(zhǎng)度:
1) 功能配件的最大長(zhǎng)度
尋找到配件的結(jié)尾以后, 采用回溯的方法尋找配件的最大長(zhǎng)度, 每次向前增加一條指令, 并結(jié)合Q[3]中識(shí)別配件的模塊(ROP編譯器)判斷該指令片段是否屬于配件, 屬于什么類(lèi)型的配件。如果屬于功能配件, 則繼續(xù)回溯指令, 直到該指令片段不再屬于功能配件為止, 此時(shí)前一狀態(tài)下的指令數(shù)就是該功能配件的最大長(zhǎng)度, 指令片段的第一條指令就是該功能配件的開(kāi)端。對(duì)于調(diào)度配件和系統(tǒng)調(diào)用配件, 因?yàn)樗鼈儗儆诠δ芘浼奶厥馇闆r, 所以它們最大長(zhǎng)度的尋找過(guò)程同普通功能配件一致。
2) NOP配件的最大長(zhǎng)度
類(lèi)似功能配件, 當(dāng) Q判斷出該指令片段屬于NOP配件時(shí), 繼續(xù)回溯, 直到該指令片段不再能夠被 CRA利用為止(例如普通代碼), 此時(shí)前一狀態(tài)下的指令數(shù)就是該NOP配件的最大長(zhǎng)度, 指令片段的第一條指令就是該NOP配件的開(kāi)端。
GWT框架需要為找到的所有配件附加權(quán)值標(biāo)記信息, 權(quán)值標(biāo)記的結(jié)構(gòu)包含三個(gè)部分: 配件類(lèi)型, 功能配件的最大長(zhǎng)度, 以及 NOP配件的最大長(zhǎng)度。這里的配件類(lèi)型除了 3.1.2節(jié)中定義的四種之外,還包括普通代碼, 表示無(wú)法被任何CRAs利用的配件類(lèi)型。
其中功能配件最大長(zhǎng)度的概念涵蓋了特殊配件的情況, 即包括普通的功能配件和調(diào)度配件以及系統(tǒng)調(diào)用配件的最大長(zhǎng)度。隨著配件長(zhǎng)度的增加, 功能配件可能先變?yōu)镹OP配件再變?yōu)槠胀ùa, 所以存在同一條配件結(jié)尾指令(間接轉(zhuǎn)移指令)在不同狀態(tài)下對(duì)應(yīng)兩種配件類(lèi)型的最大長(zhǎng)度。因此我們假設(shè)如果同一條配件結(jié)尾指令對(duì)應(yīng)不同的配件類(lèi)型, 依據(jù)NOP配件的最大長(zhǎng)度不小于功能配件的最大長(zhǎng)度進(jìn)行進(jìn)一步判斷。
不同的配件類(lèi)型在 CRA中扮演著不同的角色,產(chǎn)生不同的效果, 因此我們依據(jù)對(duì)系統(tǒng)的威脅程度為不同配件類(lèi)型分配不同的權(quán)值, 權(quán)值越高, 則表示對(duì)應(yīng)的配件類(lèi)型對(duì)系統(tǒng)威脅越大, 同時(shí)在CRA中也越可能被使用。
每一種配件類(lèi)型的具體權(quán)值分配如表 1所示,不同配件類(lèi)型的權(quán)值可以由用戶根據(jù)安全需求自行配置, 而且也可以添加新的配件類(lèi)型和新的權(quán)值。對(duì)于NOP配件, 因?yàn)樗鼘?duì)CRA并無(wú)實(shí)質(zhì)性的幫助, 只是為了稀釋配件鏈的長(zhǎng)度而存在, 所以分配給它的權(quán)值為 0。對(duì)于功能配件, 因?yàn)樗?CRA中一系列的具體功能操作, 所以分配給它的權(quán)值為1。對(duì)于調(diào)度配件, 因?yàn)樗?JOP攻擊中的核心配件且管理其他配件的運(yùn)行, 所以分配給它的權(quán)值為2。對(duì)于系統(tǒng)調(diào)用配件, 因?yàn)樗遣僮飨到y(tǒng)內(nèi)核函數(shù)的入口,并且多數(shù) CRAs的最終目的是通過(guò)系統(tǒng)調(diào)用提權(quán)或禁用系統(tǒng)安全機(jī)制, 它比其他類(lèi)型的配件都重要,所以分配給它的權(quán)值為4。對(duì)于普通代碼, 因?yàn)镃RA中配件鏈的執(zhí)行是連續(xù)無(wú)間斷的, 另外本文假設(shè)普通代碼包含過(guò)多實(shí)際的功能操作, 對(duì)CRA具有很強(qiáng)的干擾, 會(huì)破壞配件之間的數(shù)據(jù)傳遞, 不可能被當(dāng)作配件使用, 攻擊者不可能把普通代碼插入到任何的配件鏈中, 所以當(dāng)遇到普通代碼時(shí), 則可判斷此時(shí)不會(huì)發(fā)生惡意攻擊, 對(duì)權(quán)值進(jìn)行清零操作。
表1 不同配件類(lèi)型的權(quán)值分配Table 1 Weighted Scores of Different Gadget Types
因?yàn)镃RA由一系列連續(xù)的配件組成, 且每個(gè)配件以一條間接轉(zhuǎn)移指令為結(jié)尾, 基于這兩點(diǎn)特性,GWT截取程序運(yùn)行時(shí)每?jī)蓷l間接轉(zhuǎn)移指令之間的代碼片段(包含后執(zhí)行的那條間接轉(zhuǎn)移指令)組成不同長(zhǎng)度的可能配件, 本文稱之為候選配件。另外我們?cè)陟o態(tài)分析階段為每條間接轉(zhuǎn)移指令附加了權(quán)值標(biāo)記,且 GWT又能夠在動(dòng)態(tài)分析階段識(shí)別當(dāng)前的候選配件, 因此可以通過(guò)動(dòng)靜結(jié)合的方式判斷運(yùn)行時(shí)候選配件的真實(shí)類(lèi)型: 如果當(dāng)前候選配件的長(zhǎng)度大于NOP配件的最大長(zhǎng)度, 則候選配件可判斷為普通代碼; 如果當(dāng)前候選配件的長(zhǎng)度小于功能配件的最大長(zhǎng)度, 則候選配件可判斷為功能配件; 如果以上兩種情況都不滿足, 則可判斷候選配件為NOP配件。
通過(guò)上述過(guò)程, GWT對(duì)當(dāng)前程序運(yùn)行狀態(tài)下的候選配件進(jìn)行判斷, 若識(shí)別為普通代碼, 則表示當(dāng)前程序并無(wú)CRA發(fā)生。相反, 若GWT識(shí)別多個(gè)候選配件為功能配件時(shí), 則表示當(dāng)前程序很有可能發(fā)生了CRA。GWT通過(guò)動(dòng)態(tài)監(jiān)控當(dāng)前程序候選配件的真實(shí)類(lèi)型, 依據(jù)表1中不同配件類(lèi)型的權(quán)值分配, 累加候選配件對(duì)應(yīng)的權(quán)值, 最終得出一個(gè)數(shù)值, GWT根據(jù)這個(gè)數(shù)值得出發(fā)生CRA的概率。
3.4.1 GWT+CFI框架的動(dòng)機(jī)
GWT的主要不足之處在于無(wú)法準(zhǔn)確識(shí)別配件的開(kāi)端, 僅僅是通過(guò)尋找配件的最大長(zhǎng)度來(lái)確定, 這并不是十分精確, 因此我們提出 GWT結(jié)合粗粒度CFI的思想, GWT+CFI能夠帶來(lái)以下兩點(diǎn)好處:
1) 識(shí)別配件開(kāi)端
攻擊者為了能夠繞過(guò)粗粒度 CFI的防御, 常見(jiàn)的思路就是使用特殊配件, 例如 Call-Preceded配件和Entry-Point配件。正因?yàn)槿绱? 特殊配件也帶來(lái)了無(wú)法避免的特征, 那就是攻擊者必須要求配件的第一條指令, Call-Preceded配件需要以Call-Preceded指令為開(kāi)端, Entry-Point配件需要以函數(shù)入口指令為開(kāi)端。因此, 我們能夠使用GWT+CFI的思想更精確地識(shí)別配件的開(kāi)端。
2) 減少配件數(shù)量
除了合法配件, 粗粒度 CFI能夠檢測(cè)出其他非法的配件, 所以我們能夠使用GWT+CFI的思想減少能夠被CRA利用的配件數(shù)量, 因此我們能夠更加精確定位代碼空間中可能被CRA利用的配件。
3.4.2 尋找合法配件
GWT和GWT+CFI的最大區(qū)別在于尋找配件的過(guò)程。GWT+CFI只需去尋找合法的配件即可, 對(duì)于配件的權(quán)值標(biāo)記和動(dòng)態(tài)監(jiān)控都和基礎(chǔ)的 GWT框架一致。
GWT+CFI尋找配件的過(guò)程大致如下: 首先, 需要找到所有的間接轉(zhuǎn)移指令, 即配件的結(jié)尾; 其次,需要找到所有合法配件的開(kāi)端, Call-Preceded配件的開(kāi)端就是Call-Preceded指令, Entry-Point配件的開(kāi)端就是函數(shù)的入口指令; 然后, 根據(jù)配件的結(jié)尾和開(kāi)端識(shí)別所有的合法配件; 最后, 應(yīng)當(dāng)從合法配件中選擇能夠被CRA利用的配件, 選擇過(guò)程和3.1節(jié)中介紹的基本一致, 區(qū)別在于對(duì)配件類(lèi)型的劃分。GWT+CFI包含的配件類(lèi)型有功能配件、調(diào)度配件、系統(tǒng)調(diào)用配件、NOP配件、普通代碼, 同時(shí)引入了合法配件和非法配件的概念, 如圖3所示。
圖3 GWT+CFI中配件類(lèi)型的分類(lèi)Figure 3 The Gadget Types in GWT+CFI
需要注意的是間接 jmp指令在相同的函數(shù)內(nèi)部能夠任意位置跳轉(zhuǎn), 且并不違背粗粒度 CFI中關(guān)于控制流轉(zhuǎn)移的策略。攻擊者能夠利用這一點(diǎn)在函數(shù)內(nèi)部找到除Call-Preceded或Entry-Point配件之外的合法配件, 因此對(duì)于包含 jmp指令函數(shù)內(nèi)部的配件尋找過(guò)程應(yīng)當(dāng)按照 GWT框架中的算法, 而不是GWT+CFI框架中合法配件的尋找算法。
本節(jié)內(nèi)容主要介紹GWT和GWT+CFI的配件尋找過(guò)程, 此過(guò)程能夠找到并確定所有可能配件的類(lèi)型和長(zhǎng)度, 分為四步, 可用過(guò)程2描述如下:
過(guò)程2. 配件尋找過(guò)程
步驟一: 利用二進(jìn)制分析工具IDA pro編寫(xiě)腳本找到程序中所有的間接轉(zhuǎn)移指令(配件的結(jié)尾), 另外在GWT+CFI框架中, 還要找到所有的Call-Preceded指令和函數(shù)入口指令(配件的開(kāi)端)。
FOR EACH(間接轉(zhuǎn)移指令){
步驟二: 通過(guò)回溯的思想篩選出每一個(gè)可能的配件, 直到找到功能配件的最大長(zhǎng)度為止。
步驟三: 對(duì)步驟二中得到的每一個(gè)可能配件,利用Q[3]進(jìn)一步得到配件的類(lèi)型。
步驟四: 獲取 NOP配件的最大長(zhǎng)度, 這個(gè)值不能夠小于功能配件的最大長(zhǎng)度。
}
END EACH
我們基于Q[3]提出的算法判斷每個(gè)配件的類(lèi)型。對(duì)于功能配件, 它往往包含一系列具有目的性的操作, 并且應(yīng)當(dāng)只完成 Q中定義的一種操作, 例如MoveReg, 算術(shù)邏輯運(yùn)算等。識(shí)別功能函數(shù)的算法細(xì)節(jié)可以參考文獻(xiàn)[3], 核心思想是提取指令片段執(zhí)行前后的狀態(tài)變化(相關(guān)寄存器和內(nèi)存值的變化), 用先決條件公式判斷這些變化是否滿足某個(gè)配件類(lèi)型的特征條件, 從而得出功能配件的具體類(lèi)型。但是 Q中的原始算法僅僅能夠用來(lái)尋找以 ret指令結(jié)尾的ROP配件(Q開(kāi)源的 ROP編譯器框架更新了對(duì)indirect-jmp、indirect-call, 和syscall的支持, 通過(guò)間接跳轉(zhuǎn)指令之前的代碼片段判斷該配件的類(lèi)型), 因此我們需要添加新的特征模塊去尋找 GWT中定義的合法配件。
如果一個(gè)配件被判斷是功能配件, 我們還需要進(jìn)一步識(shí)別它是否屬于特殊的功能配件。如果它以syscall指令結(jié)尾, 則屬于系統(tǒng)調(diào)用配件。如果它以indirect-jmp指令結(jié)尾, 且配件中包含修改indirect-jmp目標(biāo)寄存器的指令操作, 則屬于調(diào)度配件。其他情況則屬于普通的功能配件。
如果一個(gè)配件不屬于功能配件, 則它可能屬于NOP配件或者普通代碼。為了不改變CRA中配件鏈的原始語(yǔ)義, NOP配件應(yīng)該盡可能少的包含操作寄存器的指令。例如, 對(duì)于超長(zhǎng)的配件, 如果該配件內(nèi)部操作簡(jiǎn)單, 則該配件仍然會(huì)被當(dāng)作 NOP配件, 如果該配件的操作很復(fù)雜, 對(duì)寄存器的操作很多, 則認(rèn)為該配件無(wú)法被攻擊者利用, 所以被認(rèn)為是普通代碼。因此我們定義一個(gè)重要的變量MaxRegMod,表示NOP配件中修改寄存器的最大個(gè)數(shù)。如果一個(gè)配件修改寄存器的個(gè)數(shù)不超過(guò)我們定義的MaxRegMod, 則這個(gè)配件就屬于 NOP配件, 否則不屬于。需要注意的是, 在GWT中功能配件的優(yōu)先級(jí)要高于NOP配件, 即如果同一個(gè)配件同時(shí)屬于兩種類(lèi)型, 那么應(yīng)當(dāng)首先考慮它屬于功能配件的情況。另外NOP配件和普通代碼的區(qū)分是比較模糊的, 使用MaxRegMod也只是一種折中的辦法, 并不能徹底將這兩類(lèi)配件完全分開(kāi)。但是對(duì)于當(dāng)前實(shí)際的攻擊, 我們認(rèn)為GWT已經(jīng)基本滿足需求, 并且優(yōu)于其他基于配件長(zhǎng)度的檢測(cè)[8-9]方法。
GWT尋找功能配件和 NOP配件的方法不是一成不變的, 而是隨著配件分類(lèi)地不斷完善, 尋找算法也會(huì)不斷優(yōu)化。例如, 文獻(xiàn)[21]提出了一種基于函數(shù)的 CRA, 使用整個(gè)函數(shù)作為一個(gè)配件, 這種思想能夠繞過(guò)許多防御機(jī)制, 包括基于 CFG的理想CFI[18]。因此, 我們能夠依據(jù)攻擊者使用新型配件的定義在GWT中構(gòu)建對(duì)應(yīng)的配件尋找算法, 以此來(lái)可能防御基于函數(shù)的CRAs。
圖4表示GWT在程序中尋找配件的整個(gè)過(guò)程。第一, 找到一個(gè)間接轉(zhuǎn)移指令, 例如 ret指令; 第二,判斷配件的類(lèi)型, 例如配件1包含兩條指令(push和ret指令), 因此它屬于一個(gè)普通功能配件(StoreMem),在添加標(biāo)記信息時(shí)則注明為功能配件。同樣, 配件2也是一個(gè)功能配件(ArithmeticStore)。配件3和配件2相比多了一條 pop指令, 但這條指令會(huì)改變當(dāng)前函數(shù)的棧布局, 對(duì)CRA產(chǎn)生一定的副作用, 因此配件3不屬于功能配件。但是, 配件3修改寄存器的數(shù)量為2, 如果我們?cè)O(shè)定變量MaxRegMod的值為6, 根據(jù)前兩段的描述, 則它屬于 NOP配件, 此時(shí)功能配件的最大長(zhǎng)度就是3(配件2包含的指令數(shù))。隨著更多指令的回溯, 我們假設(shè)配件4和配件5修改寄存器的數(shù)量分別為6和7, 變量MaxRegMod的值依舊為6, 則配件4屬于NOP配件, 它的最大長(zhǎng)度就是配件4包含的指令數(shù), 而配件 5因?yàn)樾薷募拇娴臄?shù)量大于我們?cè)O(shè)定的MaxRedMod, 所以它不屬于任何配件類(lèi)型,可判斷為普通代碼。
圖4 配件尋找示例Figure 4 An Example of Gadget Search
在 GWT+CFI框架中, 除了考慮配件的結(jié)尾,我們還應(yīng)該找到配件的開(kāi)端(例如圖4中的mov指令)。因此, 在GWT+CFI中, 只有配件5可能屬于某種類(lèi)型配件。如果按照前面的假設(shè), 配件5不屬于功能配件也不是 NOP配件, 僅僅為普通代碼,則對(duì)應(yīng)的功能配件和NOP配件的最大長(zhǎng)度就是無(wú)效的。
權(quán)值標(biāo)記的結(jié)構(gòu)如圖 5所示, 使用 32位結(jié)構(gòu),包含 3個(gè)參數(shù): 配件類(lèi)型、功能配件的最大長(zhǎng)度、NOP配件的最大長(zhǎng)度。其中, 配件類(lèi)型占用 3個(gè)比特, 具體表示的含義和表1一致, 功能配件的最大長(zhǎng)度占用14個(gè)比特, NOP配件的最大長(zhǎng)度占用剩下 15個(gè)比特。
圖5 權(quán)值標(biāo)記的結(jié)構(gòu)示意圖Figure 5 The Structure of Weighted Tagging for Gadget End
我們利用圖 5中的標(biāo)記結(jié)構(gòu), 在可執(zhí)行程序的二進(jìn)制文件中添加每個(gè)配件的標(biāo)記信息。如圖 4所示, 在每個(gè)間接轉(zhuǎn)移指令前添加一個(gè)32位的權(quán)值標(biāo)記, 包含以該間接轉(zhuǎn)移指令結(jié)尾的所有可能配件類(lèi)型和相應(yīng)配件類(lèi)型的最大長(zhǎng)度。為了保證二進(jìn)制文件的兼容性, 標(biāo)記結(jié)構(gòu)以一條預(yù)取指令為開(kāi)端, 預(yù)取指令之后是加權(quán)配件的信息, 這和文獻(xiàn)[4,19]中的方法類(lèi)似。因?yàn)槲覀兗僭O(shè)系統(tǒng)支持 DEP技術(shù), 所以攻擊者無(wú)法篡改權(quán)值標(biāo)記的結(jié)構(gòu), 同時(shí)預(yù)取指令和標(biāo)記信息相鄰, 所以攻擊者也無(wú)法偽造虛假的權(quán)值標(biāo)記結(jié)構(gòu)。
在程序運(yùn)行時(shí), 每執(zhí)行一條指令, 將配件的長(zhǎng)度加一, 當(dāng)執(zhí)行一條間接跳轉(zhuǎn)指令時(shí), 讀取對(duì)應(yīng)的配件標(biāo)記信息, 包括配件的類(lèi)型和最大長(zhǎng)度, 判斷當(dāng)前候選配件的真實(shí)類(lèi)型。另外, 我們定義四個(gè)中間變量來(lái)計(jì)算CRA發(fā)生的概率, 分別是當(dāng)前配件的類(lèi)型(Current Gadget Type, CGT), 當(dāng)前配件的長(zhǎng)度(Current Gadget Length, CGL), 當(dāng)前配件的真實(shí)類(lèi)型(Real Gadget Type, RGT), 以及CRA發(fā)生的概率因子(CRA Occurrence Index, COI)。
運(yùn)行時(shí)配件的真實(shí)類(lèi)型RGT需要依據(jù)CGT和CGL來(lái)做出判斷。有關(guān)RGT的實(shí)現(xiàn)過(guò)程由算法1描述如下,MaxFunc表示功能配件的最大長(zhǎng)度,Max-NOP表示NOP配件的最大長(zhǎng)度。
算法1. RGT的判斷
輸入: CGT, CGL,MaxFunc, MaxNOP
輸出: RGT
IF (CGT = = Normal Code){
RGT = Normal Code;
}
ELSEIF (CGT = = NOP Gadget){
IF (CGL <=MaxNOP){
RGT = NOP Gadget;
}
ELSE{
RGT = Normal Code;
}
}
//CGT=Functional/Dispatcher/Syscall Gadget
ELSE{
IF (CGL <=MaxFunc){
RGT = CGT;
}
ELSEIF (CGL <=MaxNOP){
RGT = NOP gadget;
}
ELSE{
RGT = Normal Code;
}
}
我們使用COI表示CRA發(fā)生的概率, COI越大意味著發(fā)生 CRA的概率就越大。COI的值由 RGT和配件對(duì)應(yīng)的權(quán)值決定, 詳細(xì)的過(guò)程如算法 2描述如下。除此之外, 我們定義變量MaxCOI, 表示 COI的最大值, 也是預(yù)先設(shè)定的閾值, 如果COI的值大于MaxCOI, 則我們認(rèn)為發(fā)生了 CRA, 否則程序沒(méi)有異常行為。
算法2. COI的判斷
輸入: RGT,MaxCOI, RGT對(duì)應(yīng)的權(quán)值
輸出: COI
COI = 0; //initialization
FOR EACH (間接轉(zhuǎn)移指令){
IF (COI <=MaxCOI){
IF (RGT = = Normal Code){
COI = 0;
}
ELSE{
COI = COI + RGT相應(yīng)權(quán)值;
}
}
//COI >MaxCOI
ELSE {
exit(); // CRA發(fā)生
}
}
關(guān)于GWT和GWT+CFI的硬件執(zhí)行架構(gòu)如圖6所示, 包含三個(gè)重要的硬件模塊: 控制流監(jiān)控器(Control-flow Monitor, CFM), 權(quán)值標(biāo)記配置(Weighted Tag Configuration, WTC), 以及CRA檢測(cè)模塊(CRA Detection Module, CDM)。另外, 我們假設(shè)基于策略的粗粒度CFI已經(jīng)集成在這個(gè)系統(tǒng)環(huán)境中。
圖6 GWT和GWT+CFI的硬件執(zhí)行架構(gòu)Figure 6 The Hardware Implementation of GWT and GWT+CFI
CFM 是監(jiān)控配件權(quán)值信息的主要模塊, 它記錄了程序運(yùn)行時(shí)系統(tǒng)執(zhí)行的指令數(shù)(CGL)和當(dāng)前配件的類(lèi)型(CGT)。當(dāng)一條間接轉(zhuǎn)移指令被執(zhí)行時(shí), CFM根據(jù)算法1判斷RGT的內(nèi)容, 把RGT作為輸出結(jié)果的同時(shí)輸入CDM。CDM根據(jù)算法2計(jì)算COI的值,并比較COI和閾值MaxCOI的大小關(guān)系, 如果 COI的值大于MaxCOI, 則判定為發(fā)生了CRA, 發(fā)送一個(gè)例外并記錄攻擊日志。
WTC主要負(fù)責(zé)存貯CFM和CDM使用的相關(guān)參數(shù), 例如MaxCOI和表 1中不同配件類(lèi)型對(duì)應(yīng)的權(quán)值。由于這些參數(shù)具有靈活可配置的特性, 因此用戶能夠根據(jù)自身需求修改這些參數(shù), 例如, 若用戶要提高系統(tǒng)的安全性, 他們可以降低閾值MaxCOI, 或者提高配件的權(quán)值。相反, 若用戶要緩解GWT的限制, 他們可以增加閾值MaxCOI, 或者減少配件的權(quán)值。當(dāng)然, 攻擊者無(wú)法直接篡改存貯在WTC中的參數(shù), 因?yàn)槲覀円?guī)定參數(shù)的初始值設(shè)定之后無(wú)法在GWT運(yùn)行時(shí)更改。
因?yàn)镚WT的硬件架構(gòu)非常簡(jiǎn)單, 僅僅需要記錄配件的信息和計(jì)算 COI的值。因此, 為了簡(jiǎn)化分析,我們利用著名的動(dòng)態(tài)插樁工具Pin[22]來(lái)分析GWT框架的安全性。Pin是動(dòng)態(tài)程序分析工具, 能夠?qū)γ織l指令的執(zhí)行進(jìn)行監(jiān)控, 通過(guò)編寫(xiě) PinTools來(lái)模擬GWT硬件執(zhí)行的功能。關(guān)于測(cè)試樣例, 我們選擇Ubuntu系統(tǒng)目錄/bin和/usr/bin/下被用戶廣泛使用的程序。為了維護(hù)GWT框架的安全性和穩(wěn)定性, 我們?cè)O(shè)置重要參數(shù)MaxRegMod的值為6,MaxCOI的值為8, 不同配件類(lèi)型對(duì)應(yīng)的權(quán)值和表1一致。
因?yàn)镚WT和GWT+CFI框架的主要不同在于配件的尋找過(guò)程, 而兩者對(duì)于CRA的檢測(cè)過(guò)程是一致的, 因此我們主要關(guān)注GWT框架的安全性分析, 而GWT+CFI和它是一致的。
5.1.1 配件尋找過(guò)程
在GWT框架中, 每個(gè)測(cè)試程序40KB的代碼空間中平均存在 1072個(gè)可能屬于配件的代碼片段(候選配件)。進(jìn)一步分析不同配件類(lèi)型的數(shù)量關(guān)系得出,功能配件、調(diào)度配件、系統(tǒng)調(diào)用配件, 以及NOP配件的平均數(shù)量分別為452、7、1.5, 以及612, 如圖7所示。另外, 每個(gè)程序中包含的所有候選配件的平均長(zhǎng)度為9.9, 其中功能配件(包括調(diào)度配件和系統(tǒng)調(diào)用配件)的平均長(zhǎng)度為5.3, NOP配件的平均長(zhǎng)度為13.3,如圖8所示。
在GWT+CFI框架中, 每個(gè)測(cè)試程序40KB的代碼空間中, 合法配件的平均數(shù)量是 471個(gè), 相比較GWT基礎(chǔ)框架中候選配件的數(shù)量, 合法配件的數(shù)量大幅減少, 尤其是合法的功能配件。其中, 功能配件、調(diào)度配件、系統(tǒng)調(diào)用配件, 以及NOP配件的平均數(shù)量分別為45、0.9、0.15, 以及425, 如圖7所示。相反, 合法配件的平均長(zhǎng)度為13.5, 要大于GWT中配件的平均長(zhǎng)度。其中功能配件和NOP配件的平均長(zhǎng)度分別為7.7和14.1, 如圖8所示。
圖7 GWT和GWT+CFI中不同配件的平均數(shù)量Figure 7 The Average Number of Different Gadgets in GWT and GWT+CFI
圖8 GWT和GWT+CFI中不同配件的平均長(zhǎng)度Figure 8 The Average Lengths of Different Gadgets in GWT and GWT+CFI
對(duì)于 GWT中的重要參數(shù)MaxRegMod, 即配件修改寄存器的最大數(shù)量, 同時(shí)也是劃分NOP配件和普通代碼的邊界閾值。顯而易見(jiàn), 如果增加MaxRegMod的值, 候選NOP配件的最大長(zhǎng)度也會(huì)隨之增加, 造成更多的普通代碼轉(zhuǎn)變?yōu)?NOP配件, 因此會(huì)一定程度上增加GWT的誤報(bào)率。我們改變參數(shù)MaxRegMod的初始化值, 重復(fù)前文過(guò)程2的配件尋找過(guò)程, 對(duì)測(cè)試集合中的程序進(jìn)行靜態(tài)分析, 統(tǒng)計(jì)不同MaxRegMod值對(duì)應(yīng)的NOP配件的平均長(zhǎng)度。實(shí)驗(yàn)表明, 隨著MaxRegMod的增加, GWT和GWT+CFI中NOP配件平均長(zhǎng)度的變化情況如圖9所示。盡管處理器中有很多寄存器, 但多數(shù)都有特定的用途, 僅僅只有 8個(gè)通用目標(biāo)寄存器(32位系統(tǒng))常常被使用, 因此當(dāng)MaxRegMod的值大于8時(shí), NOP配件的平均長(zhǎng)度幾乎不再改變, 這和圖 9顯示的實(shí)驗(yàn)結(jié)果一致。另外由于NOP配件對(duì)CRA的貢獻(xiàn)不是很大, 也就是說(shuō) NOP配件并不具備實(shí)際的功能價(jià)值, 所以我們分配給它的權(quán)值為0, 因此適當(dāng)?shù)脑黾覯axReg Mod的值并不會(huì)影響GWT對(duì)CRA的檢測(cè)效果。
圖9 GWT和GWT+CFI中NOP配件的平均長(zhǎng)度Figure 9 The Average Lengths of NOP Gadgets in GWT and GWT+CFI
5.1.2 實(shí)際的攻擊
首先, 我們使用自動(dòng)化工具Q[3]生成實(shí)際可被攻擊者利用的配件鏈, 然后針對(duì)已知的漏洞程序構(gòu)造CRA來(lái)檢測(cè)GWT框架的安全性。因?yàn)槲覀円呀?jīng)提前標(biāo)記了目標(biāo)程序中所有的可能配件, 所以GWT能夠輕易檢測(cè)出由連續(xù)配件組成的 shellcode, 并記錄配件鏈中配件的權(quán)值信息。對(duì)于配件權(quán)值, 因?yàn)?Q主要生成以ret指令結(jié)尾的配件, 且配件類(lèi)型都屬于GWT中的普通功能配件, 所以分配的權(quán)值均為 1。針對(duì)構(gòu)造的攻擊樣本和 Linux系統(tǒng)目錄 /bin 和/usr/bin/ 下一百多個(gè)常用程序進(jìn)行實(shí)驗(yàn), GWT能夠成功檢測(cè)所有由Q生成的惡意配件鏈。
其次, 我們使用手動(dòng)構(gòu)造一些特殊的CRAs來(lái)試圖繞過(guò)GWT的防御, 以此檢測(cè)GWT的安全性。在GWT框架中, 識(shí)別功能配件的標(biāo)準(zhǔn)非常嚴(yán)格, 而識(shí)別NOP配件的標(biāo)準(zhǔn)則相對(duì)寬松, 因此我們精心選擇一些特殊的NOP配件(替代功能配件)構(gòu)造CRA。但是這些NOP配件可能會(huì)包含一些額外的操作, 因此構(gòu)造一個(gè)長(zhǎng)的NOP配件鏈去做一些復(fù)雜的操作是非常困難的, 原因在于NOP配件可能會(huì)產(chǎn)生副作用。一個(gè)實(shí)際可行的攻擊方法是通過(guò)構(gòu)建簡(jiǎn)單短小的配件鏈去關(guān)閉 DEP, 然后通過(guò)注入惡意代碼的方式完成復(fù)雜的攻擊目的。
配件類(lèi)型對(duì)應(yīng)的權(quán)值和變量MaxCOI是CRA檢測(cè)模塊的兩個(gè)關(guān)鍵參數(shù), 更大的權(quán)值分配和更小的MaxCOI能夠提供更高的安全性, 但同時(shí)也會(huì)造成系統(tǒng)高的誤報(bào)率, 因此我們應(yīng)當(dāng)選擇合適的參數(shù)值來(lái)平衡安全性和穩(wěn)定性的關(guān)系。我們改變參數(shù)MaxCOI的初始化值, 重復(fù) PinTools的插樁模塊, 依據(jù)第 4.3節(jié)CRA的檢測(cè)算法對(duì)測(cè)試集合中的程序進(jìn)行動(dòng)態(tài)分析, 統(tǒng)計(jì)不同MaxCOI值對(duì)應(yīng)的實(shí)驗(yàn)數(shù)據(jù)。如圖 10和圖11描述了隨著MaxCOI值的變化, GWT中CRA檢測(cè)模塊查全率和誤報(bào)率的變化情況。MaxCOI的值變大, GWT判定發(fā)生CRA則需要更多的配件, 一方面, 因?yàn)橛?Q 編譯器生成的配件鏈通常包含 20~40個(gè)配件, 所以我們?cè)O(shè)置MaxCOI的值小于20才能檢測(cè)由 Q編譯器生成的大部分配件鏈; 另一方面, 隨著MaxCOI的減小, GWT可能會(huì)誤判普通程序發(fā)生了 CRA, 例如一個(gè)普通程序陷入一個(gè)系統(tǒng)調(diào)用, 這個(gè)系統(tǒng)調(diào)用可能被識(shí)別為系統(tǒng)調(diào)用配件, 如果我們?cè)O(shè)置MaxCOI的值小于4, GWT則判定這個(gè)普通程序陷入系統(tǒng)調(diào)用的行為是惡意的CRA。
5.1.3 檢測(cè)不同的CRAs
圖10 GWT中CRA檢測(cè)模塊的查全率Figure 10 The Recall Rate of CRA Detection Module in GWT
圖11 GWT中CRA檢測(cè)模塊的誤報(bào)率Figure 11 The False Positive Rate of CRA Detection Module in GWT
我們提出的 GWT框架理想情況下能夠檢測(cè)多種不同的CRAs, 包括: 普通的ROP攻擊[1], 普通的JOP攻擊[14], 特殊配件構(gòu)造的各種 CRAs[13,16], 基于函數(shù)的 CRA[21], 非控制數(shù)據(jù)攻擊[18]。本文在理論的支持下探討GWT對(duì)多種CRAs的防御效果, 對(duì)前三種CRAs進(jìn)行真實(shí)的實(shí)現(xiàn)和測(cè)試, 未來(lái)工作中會(huì)進(jìn)一步尋找新型CRAs(基于函數(shù)的CRA和非控制數(shù)據(jù)攻擊)的特征, 測(cè)試GWT的防御效果和性能損耗:
1) 普通的ROP攻擊
普通的ROP攻擊是指以 ret指令為結(jié)尾的配件構(gòu)成的 CRA, 例如攻擊者使用自動(dòng)化工具 Q生成ROP配件鏈, 因?yàn)槲覀円呀?jīng)標(biāo)記了這些配件, 所以一旦ROP配件的權(quán)值總和大于MaxCOI, GWT就能夠輕松檢測(cè)。
2) 普通的JOP攻擊
普通的JOP攻擊是指使用indirect-jmp指令為結(jié)尾的配件構(gòu)成的 CRA, 它包含了普通的功能配件和調(diào)度配件, 而調(diào)度配件在GWT中會(huì)被分配很高的權(quán)值, 因此相比較ROP攻擊, GWT更容易檢測(cè)和防御JOP攻擊。
3) 特殊配件的CRAs
NOP配件 通常 NOP配件被用來(lái)繞過(guò)基于策略的粗粒度CFI[13,20]。在GWT中, 我們識(shí)別NOP配件, 并分配給它的權(quán)值為 0, 一方面, 在配件鏈插入NOP配件并不會(huì)減少功能配件的數(shù)量, GWT能夠檢測(cè)插入任何數(shù)量NOP配件的CRA。另一方面, GWT無(wú)法檢測(cè)全部由NOP配件組成的CRA, 但是全部使用NOP配件幾乎不可能構(gòu)造出復(fù)雜的攻擊過(guò)程, 也無(wú)法被自動(dòng)化的工具生成。因此, GWT能夠檢測(cè)使用NOP配件來(lái)稀釋功能配件鏈的CRA, 同時(shí)不會(huì)受到NOP配件的誤導(dǎo)。
系統(tǒng)調(diào)用配件 系統(tǒng)調(diào)用配件主要被CRA用來(lái)減少配件鏈的長(zhǎng)度。如果我們?cè)O(shè)置MaxCOI的值為8, 系統(tǒng)調(diào)用配件的權(quán)值為4, GWT能夠檢測(cè)出執(zhí)行系統(tǒng)調(diào)用之前包含不少于4條功能配件的CRA。當(dāng)然我們也可以減小MaxCOI的值并增大系統(tǒng)調(diào)用的權(quán)值來(lái)檢測(cè)包含更少配件數(shù)量的CRA。
其他特殊配件 如果攻擊者提出了一些新的配件類(lèi)型來(lái)繞過(guò)現(xiàn)有的防御機(jī)制, 我們可以在GWT中添加這些特殊的配件并分配它們合適的權(quán)值, 例如文獻(xiàn)[16]提出了一種新的配件類(lèi)型, 它能夠繞過(guò)基于不精確 CFG的細(xì)粒度 CFI, 稱之為間接函數(shù)調(diào)用的參數(shù)污染配件(Argument Corruptible Indirect Call Sites, ACICS), 包含一個(gè)間接調(diào)用指令和一個(gè)目標(biāo)函數(shù), 且目標(biāo)函數(shù)能夠在符合CFG的情況下執(zhí)行遠(yuǎn)程代碼[16]。我們可以根據(jù)文獻(xiàn)中關(guān)于ACICS配件的描述, 在目標(biāo)程序中找到并標(biāo)記這類(lèi)配件, 這樣 GWT就能夠檢測(cè)并防御使用ACICS配件的CRA。
4) 基于函數(shù)的CRA
基于函數(shù)的 CRA使用整個(gè)函數(shù)作為配件[18,21],它能夠繞過(guò)大多數(shù)的CFI方案。如圖12所示, 基于函數(shù)的CRA也需要調(diào)度配件來(lái)管理程序中能夠被利用的函數(shù)配件, 如果我們能夠找到并標(biāo)記這些調(diào)度配件, GWT就能夠檢測(cè)基于函數(shù)的CRA。不過(guò)要準(zhǔn)確區(qū)分普通程序和基于函數(shù)的CRA在調(diào)用函數(shù)時(shí)的不同特征, 正如圖 12所示, 如果程序僅僅調(diào)用單一目標(biāo)函數(shù), 則它屬于普通程序, 若連續(xù)調(diào)用許多不同函數(shù), 則它可能屬于 CRA, 例如我們應(yīng)當(dāng)標(biāo)記圖12中的test()函數(shù)為普通代碼而不是調(diào)度配件。
圖12 基于函數(shù)的CRA和普通程序的對(duì)比Figure 12 The Comparison of Function-based CRAs and Normal Programs
5) 非控制數(shù)據(jù)攻擊
文獻(xiàn)[18]提出了一種控制流彎曲的新型 CRA,它結(jié)合了非控制數(shù)據(jù)攻擊的思想, 通過(guò)中轉(zhuǎn)函數(shù)繞過(guò)基于精確CFG的細(xì)粒度CFI。但是在GWT框架中, 我們可以標(biāo)記所有能夠被控制流彎曲利用的漏洞函數(shù), 這些函數(shù)中存在可被利用的功能配件, 例如printf(), fputs()。如果這些庫(kù)函數(shù)連續(xù)執(zhí)行的數(shù)量超過(guò)了MaxCOI, GWT就能夠檢測(cè)控制流彎曲攻擊。相反, 普通程序通常很少連續(xù)多次執(zhí)行這些庫(kù)函數(shù),另外, 控制流彎曲的攻擊也需要調(diào)度配件來(lái)管理這些中轉(zhuǎn)函數(shù), 所以我們標(biāo)記和監(jiān)控調(diào)度配件理論上也可以成功防御控制流彎曲攻擊, 方法類(lèi)似基于函數(shù)的CRA。
我們?cè)谂渲脼?CPU Intel x/E7-4820, 頻率2.5GHz,內(nèi)存類(lèi)型 DDR3-1600, 大小 8G, 共享緩存16MB的服務(wù)器上安裝Ubuntu 16.04, 系統(tǒng)內(nèi)核版本4.4(x86)。我們通過(guò)運(yùn)行硬件模擬器SimpleScalar, 實(shí)現(xiàn)了GWT和GWT+CFI的硬件架構(gòu), 如圖6所示。
因?yàn)镚WT和GWT+CFI框架的主要不同在于配件的尋找過(guò)程, 而兩者對(duì)于CRA的檢測(cè)過(guò)程是一致的, 因此它們?cè)赟impleScalar中的功能實(shí)現(xiàn)可由過(guò)程3描述如下, 共添加代碼310余行。另外, 關(guān)于處理器參數(shù)的具體配置細(xì)節(jié)總結(jié)于表 2。我們從標(biāo)準(zhǔn)的SPEC CPU2006[23]中選取性能測(cè)試套件, 這些標(biāo)準(zhǔn)測(cè)試程序均通過(guò)GCC編譯器進(jìn)行O3級(jí)優(yōu)化編譯。
表2 處理器配置信息Table 2 The Configuration of Processor
過(guò)程3. GWT和GWT+CFI在SimpleScalar中的邏輯實(shí)現(xiàn)
sim-safe.c main():
INITWTC()
MD_FETCH_INST()
IF(Indirect-Branch):
THEN:
INPUTstatic_result
IF(EXIST):
THEN:
EXECUTECFM()
ELSE:
CONTINUE
FI
EXECUTECDM()
IF(CRA):
THEN:
Exception()
ELSE:
CONTINUE
FI
ELSE:
CONTINUE
FI
MD_SET_OPCODE()
基于所有的測(cè)試套件, 比較程序在不同架構(gòu)(基本架構(gòu)和粗粒度CFI/GWT架構(gòu))上的運(yùn)行時(shí)間, 從而得到性能開(kāi)銷(xiāo)的具體數(shù)據(jù)。我們比較了 GWT, 粗粒度CFI, 以及GWT+CFI的性能開(kāi)銷(xiāo), 如圖13所示。因?yàn)?GWT已經(jīng)考慮了代碼長(zhǎng)度策略, 所以粗粒度CFI只需要添加三條控制流轉(zhuǎn)移策略即可。實(shí)驗(yàn)結(jié)果表明GWT的平均性能開(kāi)銷(xiāo)只有2.31%, 最大不超過(guò)6%。GWT+CFI的平均性能開(kāi)銷(xiāo)為3.55%, 最大不超過(guò)9%, 因?yàn)镚WT+CFI不僅僅包含了GWT的性能開(kāi)銷(xiāo), 而且包括粗粒度CFI的開(kāi)銷(xiāo)。由于GWT和粗粒度CFI的實(shí)現(xiàn)具有可以復(fù)用的部分, 例如GWT和粗粒度CFI都需要監(jiān)控和追蹤間接跳轉(zhuǎn)指令的運(yùn)行,因此GWT+CFI的性能損耗要小于單獨(dú)GWT的性能損耗加上單獨(dú)粗粒度CFI的性能損耗。
圖13 不同方法的性能開(kāi)銷(xiāo)(歸一化為基礎(chǔ)環(huán)境)Figure 13 Performance Overheads of Different Methods(Normalized to the Baseline System)
本文把配件主要分為三種類(lèi)型: 普通代碼(無(wú)法被CRA利用的代碼片段)、NOP配件, 以及功能配件(包括調(diào)度配件和系統(tǒng)調(diào)用配件)。CRA使用功能配件完成穩(wěn)定且有用的操作, 使用NOP配件來(lái)繞過(guò)防御機(jī)制。配件的分類(lèi)雖然簡(jiǎn)單明了, 但準(zhǔn)確識(shí)別這些配件類(lèi)型并不容易。
我們使用基于Q的配件尋找算法來(lái)識(shí)別功能配件, 但Q識(shí)別配件的規(guī)則過(guò)于嚴(yán)格, 這使得攻擊者人工找到一些額外的功能配件成為可能。另外我們通過(guò)設(shè)置變量MaxRegMod來(lái)識(shí)別NOP配件, 但是攻擊者可能會(huì)構(gòu)造出只需要修改少量寄存器的特殊 NOP配件來(lái)繞過(guò)GWT。因此精確識(shí)別各種配件類(lèi)型并不是很容易, 僅僅使用Q或MaxRegMod還無(wú)法做到精確識(shí)別各種配件類(lèi)型。
我們未來(lái)的工作會(huì)尋找更準(zhǔn)確識(shí)別功能配件、NOP配件, 以及普通代碼的方法。例如我們可用把NOP配件再進(jìn)行細(xì)分, 分為短N(yùn)OP配件, 中等NOP配件和長(zhǎng)NOP配件。其中短N(yùn)OP配件幾乎沒(méi)有額外的副作用, 不會(huì)影響功能配件的操作, 而長(zhǎng) NOP配件可能會(huì)帶來(lái)更多的副作用, 很難被 CRA利用,因此可以分別分配短N(yùn)OP配件, 中等NOP配件和長(zhǎng)NOP配件的權(quán)值為0.5, 0和–0.5, 通過(guò)對(duì)配件權(quán)值的調(diào)整增加GWT的安全性。
GWT具有良好的靈活性和穩(wěn)定性, 因此未來(lái)我們可以對(duì)該框架進(jìn)一步優(yōu)化和完善。
1) 可擴(kuò)展的配件尋找模塊
隨著CRA技術(shù)的不斷發(fā)展, 新的攻擊方法和新的配件被研究者提出。例如, 最早的return-to-libc首先被提出, 接著新的方法 ROP[1], JOP[2]和基于函數(shù)的CRA[21]相繼被提出。配件也由基于ret指令的傳統(tǒng)配件發(fā)展為基于jmp指令, Call-Preceded指令和基于函數(shù)的新型配件。
因?yàn)槊刻岢鲆环N新的CRA方法或配件類(lèi)型都需要詳細(xì)描述如何使用或構(gòu)建它們, 所以我們能夠根據(jù)描述的細(xì)節(jié)在GWT中完善配件的尋找算法, 因此GWT能夠在程序運(yùn)行時(shí)監(jiān)控新的配件并檢測(cè)新的CRA。本文已經(jīng)在GWT和GWT+CFI中添加了基于ret和jmp指令的配件, 以及合法配件的尋找算法。未來(lái)我們可以添加更多的配件(例如基于函數(shù)的配件)尋找算法以提高GWT的安全性。
如今攻擊者廣泛使用自動(dòng)化工具去尋找配件,因此在 GWT中也能夠重用自動(dòng)化工具幫助我們尋找配件, 例如本文就是使用 Q的自動(dòng)化框架去識(shí)別功能配件。同時(shí)所有被自動(dòng)化工具生成的配件都可以通過(guò)GWT進(jìn)行標(biāo)記, 也就是說(shuō), 我們的方法理論上能夠防御所有使用自動(dòng)化工具生成配件鏈的CRAs。
2) 可配置的初始化參數(shù)
GWT使用到的參數(shù)例如MaxCOI,MaxRegMod以及配件對(duì)應(yīng)的權(quán)值, 都是可以重新配置的, 因此用戶能夠根據(jù)實(shí)際需求修改這些參數(shù)。參數(shù)配置對(duì)GWT的影響極大, 尋找合適的參數(shù)需要大量的實(shí)驗(yàn)數(shù)據(jù), 而且根據(jù)現(xiàn)實(shí)環(huán)境的不同, 攻擊特征也會(huì)改變, 參數(shù)也應(yīng)該隨之調(diào)整。例如本文根據(jù)GWT的基本原理、前人工作和實(shí)際經(jīng)驗(yàn), 給出了參數(shù)配置的參考值, 并通過(guò)實(shí)驗(yàn)驗(yàn)證了參數(shù)配置的實(shí)際效果, 探討了參數(shù)配置對(duì)漏報(bào)率和誤報(bào)率的影響。另外, 如果我們發(fā)現(xiàn)新的配件類(lèi)型, 可以在GWT中添加這些新配件, 并分配新的權(quán)值, 因此GWT能夠檢測(cè)多種CRAs使用的不同配件, 通過(guò)添加更多的配件類(lèi)型可以提高GWT的安全性。例如本文在Q的基礎(chǔ)上添加了調(diào)度配件和系統(tǒng)調(diào)用配件, 這是兩種特殊的新型功能配件, 并為這兩類(lèi)配件分配新的權(quán)值, GWT就能夠檢測(cè)和防御相應(yīng)的CRA。
總結(jié)相關(guān)研究工作, 防御CRA的方法主要有兩種[42]: 基于隨機(jī)化思想的防御機(jī)制和基于控制流的指令檢查機(jī)制。
基于隨機(jī)化的防御思想通過(guò)隨機(jī)化程序的代碼布局, 使得攻擊者無(wú)法找到配件, 也無(wú)法連接配件。地址空間布局重排(Address Space Layout Permutation,ASLP)[24]在函數(shù)級(jí)隨機(jī)化代碼布局, 指令布局隨機(jī)化(Instruction Layout Randomization, ISR)[25]在指令級(jí)隨機(jī)化代碼布局。但這些基于隨機(jī)化思想的防御方案都受到內(nèi)存泄露攻擊的威脅[26], 例如BlindROP[27]利用內(nèi)存泄露繞過(guò)細(xì)粒度的代碼隨機(jī)化。隨后, 也有文獻(xiàn)[28-29]進(jìn)一步提高隨機(jī)化的熵值和粒度來(lái)抵御內(nèi)存泄露攻擊。
Abadi等人[4,15]提出基于控制流完整性的防御思想, 即CFI。原始CFI具有較大的性能開(kāi)銷(xiāo), 因此研究者提出犧牲部分安全性來(lái)?yè)Q取良好性能的實(shí)際方案, 主要分為兩類(lèi): 基于策略的CFI和基于CFG的CFI。
相比原始CFI, 基于策略的CFI并沒(méi)有根據(jù)CFG驗(yàn)證控制流的完整性。文獻(xiàn)[6-7]通過(guò)二進(jìn)制重寫(xiě)技術(shù)標(biāo)記所有間接轉(zhuǎn)移指令的可能目標(biāo)地址, 其實(shí)這些可能的目標(biāo)地址就是本文介紹的函數(shù)入口指令或call-preceded指令, 控制流轉(zhuǎn)移只能跳轉(zhuǎn)到這些可能的目標(biāo)地址, 否則中斷程序執(zhí)行。kBouncer[9]和ROPecker[8]利用 x86處理器中最近分支記錄(Last Branch Record, LBR)寄存器檢測(cè)程序中異常的控制流轉(zhuǎn)移, 但是這些方案都僅僅根據(jù)代碼片段的長(zhǎng)度和控制流轉(zhuǎn)移策略去識(shí)別配件, 在GWT中, 我們同時(shí)使用配件類(lèi)型, 轉(zhuǎn)移策略, 以及代碼長(zhǎng)度來(lái)識(shí)別配件?;谂浼L(zhǎng)度的檢測(cè)[8- 9]方法的最大缺點(diǎn)是安全性不夠, 配件長(zhǎng)度和配件鏈的長(zhǎng)度特征過(guò)于簡(jiǎn)單, 攻擊者能夠比較容易地尋找特定配件來(lái)繞過(guò)防御。GWT增加配件類(lèi)型和配件內(nèi)容作為配件的判斷依據(jù), 利用已有工具(如 Q)來(lái)判斷是否為功能配件,利用MaxRegMod來(lái)區(qū)分NOP配件和普通代碼, 比上述粗粒度CFI識(shí)別配件更加精確, 安全性更高。例如,一個(gè)配件包含多條NOP指令、一條運(yùn)算指令和一條間接跳轉(zhuǎn)指令, 如果 NOP指令的數(shù)量較多, 則基于配件長(zhǎng)度的檢測(cè)方法認(rèn)為這不是一個(gè)配件。而GWT根據(jù)指令的具體內(nèi)容, 能夠判斷這是一個(gè)功能配件。粗粒度CFI的方案雖然容易實(shí)施, 但也容易繞過(guò)。先前的一些研究[10-13]通過(guò)使用合法配件的CRA對(duì)抗粗粒度 CFI, 但是在 GWT中, 我們已經(jīng)標(biāo)記了這些合法配件, 例如 call-preceded配件, entry-point配件和NOP配件, 所以GWT能夠檢測(cè)利用合法配件的攻擊手段。
細(xì)粒度CFI則強(qiáng)調(diào)CFG的重要性, 基于編譯器的 CFI方案[30-33]能夠解決間接控制轉(zhuǎn)移的問(wèn)題, 因?yàn)橛性创a信息的支持, 所以能夠生成精確的 CFGs。SafeDispatch[34]通過(guò)插樁所有虛函數(shù), 嚴(yán)格檢查調(diào)用目標(biāo)是否合法, 以此防御虛函數(shù)調(diào)用的劫持攻擊[21]。前向(Forward-edge)CFI[35]不僅僅保護(hù)虛函數(shù), 它通過(guò)函數(shù)指針?lè)治鼍S護(hù)了一個(gè)可信代碼指針的列表,如果間接轉(zhuǎn)移目標(biāo)不在這個(gè)表中, 則中斷程序執(zhí)行。
模塊化的CFI方案[36-37]則關(guān)注CFG的一部分。CCFI[38]利用消息認(rèn)證編碼(Message Authentication Codes, MACs)加密控制流相關(guān)的返回地址, 函數(shù)指針和虛表指針。Per-InputCFI[39]根據(jù)每次具體的輸入內(nèi)容來(lái)完善CFG。上下文敏感的CFI方案[40]提出在二進(jìn)制級(jí)別通過(guò)前向和后向的靜態(tài)分析加強(qiáng)上下文敏感的CFI策略。CFIMon[41]提出基于硬件支持的細(xì)粒度 CFI方案, 增加性能的同時(shí)也引出了高的檢測(cè)延遲。
細(xì)粒度 CFI的安全性就在于如何構(gòu)造出精確且完善的 CFG, 但是幾乎不可能生成包含所有有效控制流路徑的理想CFG。文獻(xiàn)[17]提出由于上述細(xì)粒度CFI的缺陷, 導(dǎo)致基于 CFG的防御機(jī)制出現(xiàn)漏洞。Control Jujustu[16]提出的新型 CRA攻擊便是利用細(xì)粒度CFI無(wú)法生成理想CFG的缺陷, 構(gòu)造基于中轉(zhuǎn)函數(shù)的 ACICS配件, 在不違背 CFG的前提下完成CRA。然而, 如果把ACICS配件添加到GWT框架中, 我們的方法理論上能夠防御這類(lèi)攻擊??刂屏鲝澢鶾18]表明理想的 CFI方案也存在一些問(wèn)題, 利用內(nèi)存泄露漏洞和非控制數(shù)據(jù)攻擊思想就能夠合法調(diào)用標(biāo)準(zhǔn)庫(kù)中的函數(shù), 完成圖靈完備的攻擊。如果把這種基于函數(shù)的特殊配件類(lèi)型添加到GWT框架中, 我們的方法理論上存在檢測(cè)控制流彎曲攻擊的可能。
為了防御各式各樣的CRAs, 我們提出GWT的方法, 它是一種靈活, 低開(kāi)銷(xiāo)且安全的防御框架。GWT通過(guò)靜態(tài)分析搜索并標(biāo)記程序中存在的所有可用配件, 然后在程序運(yùn)行時(shí)動(dòng)態(tài)監(jiān)控配件的權(quán)值標(biāo)記, 以此計(jì)算 CRA發(fā)生的概率。另外我們還提出GWT結(jié)合粗粒度 CFI的方法, 相比較基礎(chǔ)的 GWT而言, GWT+CFI能夠更精確發(fā)現(xiàn)代碼空間中存在的可用配件。我們基于軟件和硬件模擬的設(shè)計(jì)框架來(lái)實(shí)現(xiàn)GWT以及GWT+CFI系統(tǒng), 結(jié)果表明其平均性能開(kāi)銷(xiāo)分別為2.31%和3.55%。GWT理論上能夠抵御使用各種配件的CRAs, 特別是使用自動(dòng)化工具生成配件鏈的CRA。另外, GWT能夠添加更多的特殊配件類(lèi)型, 設(shè)計(jì)更好的配件識(shí)別算法, 來(lái)進(jìn)一步完善和優(yōu)化該防御框架。
GWT識(shí)別功能配件、NOP配件和普通代碼的方法并不是完美的, 因此攻擊者可能會(huì)精心構(gòu)造出被GWT識(shí)別為 NOP配件但實(shí)際具有一定功能的特殊配件, 或者識(shí)別為普通代碼但實(shí)際屬于NOP配件的情況, 從而繞過(guò)GWT的防御。因此, 我們未來(lái)會(huì)提高GWT識(shí)配件類(lèi)型的精準(zhǔn)性, 并且完善其它特殊配件(例如基于函數(shù)的配件)的尋找算法, 從這兩個(gè)方面進(jìn)一步提高GWT的安全性。此外, 本文在攻擊威脅中存在過(guò)多的假設(shè), 主要是因?yàn)榛诖至6?CFI的思想而不再考慮攻擊者使用非對(duì)齊配件的情況, 因此導(dǎo)致了完備性方面的不足。未來(lái)工作中, 我們會(huì)測(cè)試非對(duì)齊配件對(duì)GWT的威脅, 完善配件的尋找和識(shí)別算法。
致 謝 在此向?qū)Ρ疚墓ぷ魈岢鲋笇?dǎo)的各位同門(mén)以及提出建議的評(píng)審專(zhuān)家表示感謝。