梅 瑞, 嚴(yán)寒冰, 沈 元, 韓志輝
1中國(guó)科學(xué)院信息工程研究所 北京 中國(guó) 100093
2中國(guó)科學(xué)院大學(xué)網(wǎng)絡(luò)空間安全學(xué)院 北京 中國(guó) 100049
3國(guó)家計(jì)算機(jī)網(wǎng)絡(luò)應(yīng)急技術(shù)處理協(xié)調(diào)中心 北京 中國(guó) 100029
4北京航空航天大學(xué)計(jì)算機(jī)學(xué)院 北京 中國(guó) 100191
隨著計(jì)算機(jī)軟件的規(guī)模越來(lái)越大、復(fù)雜度越來(lái)越高, 軟件內(nèi)部實(shí)體數(shù)量和交互次數(shù)也呈指數(shù)級(jí)增長(zhǎng), 這種軟件復(fù)雜性(Software Complexity)一方面增加了無(wú)意中干擾交互的風(fēng)險(xiǎn), 從而增加了在代碼變更時(shí)引入缺陷的可能性, 在極端的情況下甚至使修改軟件變得幾乎不可能。另一方面, 這意味著軟件更加難以理解, 使得對(duì)于軟件代碼的結(jié)構(gòu)、功能、行為和邏輯設(shè)計(jì)的認(rèn)識(shí)更加困難[1]。程序切片(Program Slicing)作為一種重要的程序理解(Program Understanding)技術(shù), 它的概念由M. Weiser于1979年首次提出, 并在其后來(lái)的論文中對(duì)程序切片理論進(jìn)行了形式化的論述。M. Weiser提出了一種基于控制流圖 (Control Flow Graph, CFG) 結(jié)合數(shù)據(jù)流方程的計(jì)算程序切片的算法, 以及基于程序切片的軟件度量 (Software Measurement) 的基本框架, 為程序切片技術(shù)的發(fā)展和應(yīng)用提供了基本的理論支持[2-3]。隨著的一些研究擴(kuò)展了M. Weiser的程序切片理論和方法, 提出了靜態(tài)切片和動(dòng)態(tài)切片、前向切片和后向切片、削片、砍片等不同的方法, 應(yīng)用于不同的與領(lǐng)域中[4]。
當(dāng)前網(wǎng)絡(luò)空間安全的主要威脅之一是惡意代碼的傳播, Malwarebytes發(fā)布的最新惡意代碼現(xiàn)狀報(bào)告中顯示[5], 2018年檢測(cè)到的后門(mén)、間諜軟件、木馬等類(lèi)型的惡意代碼同比增加20%以上, 惡意代碼通過(guò)系統(tǒng)漏洞或垃圾郵件等大規(guī)模傳播, 這對(duì)于惡意代碼檢測(cè)提出了挑戰(zhàn)。檢測(cè)和分析惡意代碼的首要工作是提取惡意代碼中的惡意特征, 而程序切片正是一種通過(guò)對(duì)程序進(jìn)行分解并提取特定代碼片段(Code Snippet)的重要方法。然而, 由于惡意代碼通常以二進(jìn)制代碼形式傳播, 因此許多針對(duì)惡意代碼檢測(cè)技術(shù)的研究都是基于二進(jìn)制代碼開(kāi)展的, 盡管有一些針對(duì)二進(jìn)制代碼切片的研究, 但是很少有將二進(jìn)制代碼切片應(yīng)用于惡意代碼檢測(cè)的方法。
本文提出的二進(jìn)制代碼切片在惡意代碼檢測(cè)中的應(yīng)用方法有2點(diǎn)貢獻(xiàn):
1)針對(duì)經(jīng)典程序切片算法對(duì)二進(jìn)制代碼執(zhí)行程序切片的問(wèn)題, 我們提出了改進(jìn)的面向二進(jìn)制代碼的過(guò)程間切片方法, 通過(guò)刪除二進(jìn)制代碼過(guò)程調(diào)用時(shí)參數(shù)傳遞依賴(lài)關(guān)系的冗余節(jié)點(diǎn), 降低了經(jīng)典程序切片算法對(duì)二進(jìn)制代碼生成系統(tǒng)依賴(lài)圖(System Dependence Graph, SDG)的復(fù)雜度。此外, 我們針對(duì)二進(jìn)制匯編代碼的多賦值(Multi-assignments)屬性, 分析了二進(jìn)制代碼切片的粒度問(wèn)題, 通過(guò)將二進(jìn)制代碼轉(zhuǎn)換為中間表示(Intermediate Representation, IR), 并提出一種帶有中間表示的系統(tǒng)依賴(lài)圖, 有效改善二進(jìn)制代碼切片的粒度問(wèn)題。
2)針對(duì)二進(jìn)制代碼切片如何有效提取惡意代碼關(guān)鍵惡意特征的問(wèn)題, 我們通過(guò)人工分析典型惡意代碼, 根據(jù)惡意代碼的基礎(chǔ)行為和反分析行為, 提出了10類(lèi)共42條有效表征惡意特征的切片準(zhǔn)則(Slicing Criterion), 并在實(shí)驗(yàn)中得到了驗(yàn)證。
本文余下部分按如下內(nèi)容組織: 第2章作為研究背景介紹了程序切片的主要概念和關(guān)鍵算法; 第3章針對(duì)經(jīng)典程序切片應(yīng)用于二進(jìn)制代碼切片引發(fā)的問(wèn)題, 提出了二進(jìn)制代碼切片的改進(jìn)方法; 第4章基于惡意代碼檢測(cè)技術(shù), 提出基于二進(jìn)制代碼切片的惡意代碼同源性檢測(cè)模型, 并闡述了模型中所選取的切片準(zhǔn)則; 第5章對(duì)本文提出方法進(jìn)行實(shí)驗(yàn)驗(yàn)證和評(píng)估; 第6章是本文的總結(jié)和進(jìn)一步研究展望。
程序切片是針對(duì)程序代碼(包括高級(jí)語(yǔ)言源代碼或者編譯后的二進(jìn)制代碼)進(jìn)行分析, 并依據(jù)分析人員的特定需求提取部分語(yǔ)句(指令)序列的過(guò)程[6-7]。程序切片基于指令的控制流和數(shù)據(jù)流, 分析指令的執(zhí)行序列和數(shù)據(jù)的產(chǎn)生、復(fù)制、傳遞和消失的過(guò)程, 最終生成所需的代碼片段[8]。
計(jì)算機(jī)程序的執(zhí)行包括2類(lèi)控制結(jié)果, 即順序結(jié)構(gòu)和非順序結(jié)構(gòu), 非順序結(jié)構(gòu)通過(guò)條件控制語(yǔ)句或挑戰(zhàn)指令將代碼分為若干區(qū)域, 稱(chēng)為基本塊(Basic Block)[9-10], 一個(gè)基本塊是滿(mǎn)足下列條件的一組連續(xù)指令代碼:
1)原子性: 基本塊是程序控制流的最小執(zhí)行單元, 基本塊中的指令僅存在全部執(zhí)行和全部不執(zhí)行兩種狀態(tài)。
2)完整性: 程序執(zhí)行時(shí)只能從該基本塊的第一條指令進(jìn)人該基本塊, 并且只能從該基本塊的最后一條指令結(jié)束。
3)序列性: 基本塊內(nèi)的指令執(zhí)行順序僅遵循指令序列在存儲(chǔ)器中的排列順序。
算法1描述了代碼基本塊識(shí)別的基本方法[11], 其中, 輸入?yún)?shù)I為待識(shí)別代碼基本塊的指令序列; LeaderSet是基本塊首條指令的集合, 初始為空集; EntryInsType是基本塊入口指令類(lèi)型枚舉, 包括程序入口指令、函數(shù)入口指令、跳轉(zhuǎn)指令的目的地址指令。算法的輸出結(jié)果BlockSet是以代碼塊入口指令為索引的代碼塊指令序列集合。
算法1. 代碼基本塊識(shí)別算法 輸入: I={insi,i∈{1, 2, 3, …, n}} LeaderSet→φ EntryInsType 輸出: BlockSet→φ 過(guò)程: 1: FOR insi IN I 2: IF insi IS EntryInsType 3: LeaderSet=LeaderSet∪{insi} 4: FOR x IN LeaderSet 5: BlockSet[x]=x 6: i=x+1 7: WHILE i≤n AND (NOT i∈LeaderSet) 8: BlockSet[x]=BlockSet[x]∪{i} 9: i=i+1
控制流圖: 將基本塊視為一個(gè)基本單元節(jié)點(diǎn), 基本塊之間在程序執(zhí)行流程上互為前趨和后繼關(guān)系視為兩個(gè)基本塊之間存在一條邊, 則整個(gè)程序能夠轉(zhuǎn)換為一個(gè)有向圖[12]。算法2描述了控制流圖的構(gòu)建算法。
算法2. 控制流圖構(gòu)建算法 輸入: BlockSet BranchInsSet BranchMap 輸出: CFG 過(guò)程: 1: FOR b IN BlockSet 2: x=b[len(b)-1] 3: IF x∈BranchInsSet 4: FOR b_target IN BranchMap[x] 5: CreateEdge(CFG,b,b_target) 5: ELSE 6: CreateEdge(CFG,b,Next(b))
控制流圖是一個(gè)有向圖, 可以表示為一個(gè)四元組, G={V, E, Entry, Exit}, 基于圖論的觀點(diǎn), 對(duì)控制流圖的關(guān)鍵屬性做如下定義:
定義1. 可執(zhí)行路徑: 在控制流圖中, 從任意節(jié)點(diǎn)開(kāi)始進(jìn)行節(jié)點(diǎn)遍歷會(huì)形成一條路徑, 路徑上的基本塊串聯(lián)后可以形成程序的一條執(zhí)行路徑, 該路徑稱(chēng)作控制流圖上的一個(gè)可執(zhí)行路徑。
定義2. 前必經(jīng)節(jié)點(diǎn): 對(duì)于控制流圖中的兩個(gè)節(jié)點(diǎn)a、b, 如果從開(kāi)始節(jié)點(diǎn)Entry到節(jié)點(diǎn)b 的所有路徑都經(jīng)過(guò)節(jié)點(diǎn)a, 則稱(chēng)節(jié)點(diǎn)a支配節(jié)點(diǎn)b, 并稱(chēng)節(jié)點(diǎn)a是節(jié)點(diǎn)b的前必經(jīng)節(jié)點(diǎn), 記為a→b。
定義3. 嚴(yán)格前必經(jīng)節(jié)點(diǎn): 如果節(jié)點(diǎn)a是節(jié)點(diǎn)b的前必經(jīng)節(jié)點(diǎn), 并且a≠b, 則稱(chēng)a是b 的嚴(yán)格前必經(jīng)節(jié)點(diǎn), 記為a→pb。
后必經(jīng)節(jié)點(diǎn)和嚴(yán)格后必經(jīng)節(jié)點(diǎn)也有類(lèi)似的定義, 上述定義中的節(jié)點(diǎn)均為代碼基本塊。
控制依賴(lài)分析以控制流圖為分析對(duì)象, 對(duì)基本塊之前的控制依賴(lài)關(guān)系進(jìn)行分析, 上文所述的前必經(jīng)和后必經(jīng)關(guān)系并不等價(jià)于控制依賴(lài)關(guān)系, 還需要依賴(lài)節(jié)點(diǎn)能夠決定被依賴(lài)節(jié)點(diǎn)是否執(zhí)行。
定義4. 控制依賴(lài)關(guān)系: 令G為程序P 的控制流圖, 其中a和b是G中的兩個(gè)節(jié)點(diǎn), 當(dāng)a和b滿(mǎn)足下列兩個(gè)條件時(shí), 則稱(chēng)b控制依賴(lài)于a, 記作b→cda: (1)從a到b有一條可執(zhí)行路徑, 并且對(duì)于該路徑上除a, b外的任意節(jié)點(diǎn)n, 節(jié)點(diǎn)b都是其后必經(jīng)節(jié)點(diǎn); (2)節(jié)點(diǎn)b不是a的后必經(jīng)節(jié)點(diǎn)。
由控制依賴(lài)關(guān)系可以定義控制依賴(lài)圖G=(V, C), 其中V是程序中所有語(yǔ)句(或基本塊)對(duì)應(yīng)節(jié)點(diǎn)的集合, C是控制依賴(lài)圖的邊集合。如果有節(jié)點(diǎn)u直接控制依賴(lài)于v, 即u→cdv, 則將u到v的邊添加到C中。于是利用控制依賴(lài)圖就可以完整的描述程序中每個(gè)基本塊的控制依賴(lài)關(guān)系。如果將每條語(yǔ)句作為圖的一個(gè)節(jié)點(diǎn), 也可以得到類(lèi)似的控制依賴(lài)圖。
數(shù)據(jù)流分析關(guān)注的是變量(在匯編語(yǔ)言中還包括內(nèi)存地址和寄存器的值)在程序執(zhí)行過(guò)程中的變化, 即跨越多條語(yǔ)句的同一變量定義、賦值和運(yùn)算操作[13]。數(shù)據(jù)依賴(lài)分析包括可到達(dá)定義分析(Reaching Definition Analysis)和活性分析(Liveness Analysis)。
可到達(dá)定義分析的目標(biāo)在于獲取操作指令或語(yǔ)句所引用變量的來(lái)源, 即引用的變量如何產(chǎn)生、復(fù)制和傳遞。為了準(zhǔn)確地刻畫(huà)程序狀態(tài), 我們將程序執(zhí)行路徑表示為程序中連續(xù)的語(yǔ)句執(zhí)行前后的狀態(tài)序列, 若程序包含n條語(yǔ)句, 則存在n+1個(gè)執(zhí)行狀態(tài), 記為P0, P1, P2, P3, …, Pn, 其中對(duì)于任意語(yǔ)句s∈{0, 1, 2, …, n}, 則s語(yǔ)句執(zhí)行前的狀態(tài)為Ps–1, 執(zhí)行后的狀態(tài)為Ps。
定義5. 可到達(dá)定義: 若語(yǔ)句s定義了變量x, 則該語(yǔ)句的定義到達(dá)狀態(tài)位置P, 當(dāng)且僅當(dāng)在程序控制流圖中存在從語(yǔ)句s對(duì)應(yīng)的狀態(tài)位置Ps到P的一條路徑, 并且該路徑上沒(méi)有變量x的其他定義, 同時(shí)稱(chēng)語(yǔ)句s是代碼位置P的一個(gè)可到達(dá)定義。
可到達(dá)定義相關(guān)概念的非形式化描述如下:
1)定義集Def(x): 定義變量x的所有語(yǔ)句的集合。
2)引用集Use(x): 任何使用變量x的語(yǔ)句的集合。
3)產(chǎn)生集Gen(s): 所有由語(yǔ)句s給出的變量定義所在的語(yǔ)句構(gòu)成的集合。
4)消滅集Kill(s): 若語(yǔ)句s重新定義變量x, 而x此前由語(yǔ)句s"定義, 則稱(chēng)s消滅定義s"。所有由s消滅的定義的集合稱(chēng)為s的消滅集。
5)入集In(s): 所有在語(yǔ)句s之前仍然有效(沒(méi)有被消滅)的定義語(yǔ)句的集合。
6)出集Out(s): 所有離開(kāi)語(yǔ)句s時(shí)的定義語(yǔ)句的集合, 添加s產(chǎn)生(Gen)的語(yǔ)句, 同時(shí)去掉語(yǔ)句s所消滅(Kill)的定義語(yǔ)句。
上述可到達(dá)定義的相關(guān)概念, 若將其中的分析對(duì)象由語(yǔ)句變換為代碼基本塊, 也存在相似的定義。
算法3. 可到達(dá)定義算法 輸入: CFG={V,E,Entry,Exit} 輸出: Out 過(guò)程: 1: FOR b IN V 2: In(b)=φ 3: Out(b)=Gen(b) 4: IsConvergence=false 5: WHILE IsConvergence==false 5: FOR b IN V 6: In(b)=∪{Out(p) | p∈Pred(b)} 7: OldOut=Out(b) 8: OldIn=In(b) 9: Out(b)=Gen(b)∪(In(b)-Kill(b)) 10: IF Out(b)==OldOut AND In(b)==OldIn 11: IsConvergence=true 12: ELSE 13: IsConvergence=false
算法3描述了可到達(dá)定義的計(jì)算方法, 其中輸入為程序的控制流圖, 輸出為指定語(yǔ)句或基本塊的出集Out(s)。在算法中, 使用變量IsConvergence作為是否繼續(xù)迭代的開(kāi)關(guān), 即經(jīng)過(guò)有限輪迭代后出集Out最終達(dá)到收斂。在最壞的情況下, 出集Out可能包括所有的語(yǔ)句或基本塊。
另一方面, 活性分析是對(duì)語(yǔ)句中定義的變量是否在后續(xù)語(yǔ)句中被引用以及被哪些語(yǔ)句引用的分析。對(duì)于任意語(yǔ)句s和s中的一個(gè)變量x, 如果x在s上的值在控制流圖中從s出發(fā)的某條路徑上使用, 就稱(chēng)x在s上活躍, 否則稱(chēng)x在s上消亡。此外, 活性分析還關(guān)注變量保持活躍的范圍稱(chēng)為活性范圍, 即分析任意語(yǔ)句s, 變量x在后續(xù)語(yǔ)句中繼續(xù)保持活躍的語(yǔ)句范圍。活性分析常用于編譯器的代碼生成階段對(duì)基本塊分配寄存器, 即依據(jù)變量的活性進(jìn)行寄存器分配的優(yōu)化。
數(shù)據(jù)依賴(lài)分析描述引用變量的語(yǔ)句或基本塊對(duì)定義該變量的語(yǔ)句或基本塊的依賴(lài), 是一種“定義—引用”的依賴(lài)關(guān)系。
定義6. 數(shù)據(jù)依賴(lài)關(guān)系: 設(shè)a和b分別為程序P的控制流圖G中的兩個(gè)節(jié)點(diǎn), x為P中的一個(gè)變量, 若a和b滿(mǎn)足下列條件, 則稱(chēng)b關(guān)于變量x數(shù)據(jù)依賴(lài)于a, 記為b→dda:
1)a對(duì)變量x進(jìn)行定義, 即a∈Def (x);
2)b中引用了變量x, 即b∈Use(x);
3)a到b有一條可執(zhí)行路徑, 且在此路徑上不存在語(yǔ)句對(duì)x進(jìn)行定義。
顯然, 如果b→dda, 則節(jié)點(diǎn)b是節(jié)點(diǎn)a的一個(gè)可到達(dá)定義。
由數(shù)據(jù)依賴(lài)關(guān)系可以定義數(shù)據(jù)依賴(lài)圖G=(V, D),其中V是程序中所有基本塊對(duì)應(yīng)節(jié)點(diǎn)的集合, D是數(shù)據(jù)依賴(lài)圖的邊集合。如果有節(jié)點(diǎn)b數(shù)據(jù)依賴(lài)于a, 即b→dda, 則將b到a的邊添加到D中。于是利用數(shù)據(jù)依賴(lài)圖就可以完整的描述程序中每個(gè)基本塊的數(shù)據(jù)依賴(lài)關(guān)系。如果將每條語(yǔ)句作為圖的一個(gè)節(jié)點(diǎn), 也可以得到類(lèi)似的控制依賴(lài)圖[6-7]。
控制依賴(lài)關(guān)系描述程序控制流的序列關(guān)系, 數(shù)據(jù)依賴(lài)關(guān)系描述程序中變量的影響和被影響的關(guān)系, 刻畫(huà)控制依賴(lài)關(guān)系和數(shù)據(jù)依賴(lài)關(guān)系的工具分別是控制依賴(lài)圖和數(shù)據(jù)依賴(lài)圖。為了從整體上統(tǒng)一分析控制依賴(lài)關(guān)系和數(shù)據(jù)依賴(lài)關(guān)系, 提出了基于控制依賴(lài)圖和數(shù)據(jù)依賴(lài)圖構(gòu)建程序依賴(lài)圖(Program Dependence Graph, PDG), 若Gc=(V, C)和Gd=(V, D)分別為程序P的控制依賴(lài)圖和數(shù)據(jù)依賴(lài)圖, 則程序依賴(lài)圖Gp=(V, E), 其中E=C∪D∪X, 其中X表示程序中的補(bǔ)充依賴(lài)關(guān)系[14-17]。
程序切片關(guān)注指令序列對(duì)特定語(yǔ)句和變量的影響, 因此基于特定語(yǔ)句和變量制定切片準(zhǔn)則, 用于執(zhí)行程序切片[18-19]。切片準(zhǔn)則包含兩個(gè)要素, 即切片目標(biāo)變量和切片初始代碼位置。程序P的切片準(zhǔn)則可以描述為一個(gè)二元組
執(zhí)行程序切片的一般步驟:
1)程序依賴(lài)關(guān)系提取: 包括控制依賴(lài)分析和數(shù)據(jù)依賴(lài)分析, 以及程序依賴(lài)圖的構(gòu)建。
2)切片準(zhǔn)則構(gòu)建: 基于程序分析需求設(shè)計(jì)一組切片準(zhǔn)則, 可以是程序中的變量定義、變量引用、過(guò)程調(diào)用的特定參數(shù)、常量、以及應(yīng)用程序接口(Application Programming Interface, API)。
3)程序切片生成: 選取合適的程序切片算法, 基于已構(gòu)建的切片準(zhǔn)則, 執(zhí)行程序切片算法, 提取程序的代碼片段。
算法4 基于圖可達(dá)性切片算法 輸入: CFG={V,E,Entry,Exit} PDG=(Vp,Ep) SlicingCriterion=(n,{variable}) 輸出: Slice→φ 過(guò)程: 1: ReachableGraphSlice(Node n) 2: IF n.visited==false 3: n.visited=true 4: Slice=∪{n} 5: FOR s IN n.children 6: Slice=∪ReachableGraphSlice(s) 7: RETURN Slice
算法4描述了基于圖可達(dá)性的程序切片算法, 其中, 輸入?yún)?shù)包括控制流圖CFG、程序依賴(lài)圖PDG以及切片準(zhǔn)則SlicingCriterion, 通過(guò)遞歸遍歷程序依賴(lài)圖, 生成程序依賴(lài)圖的一個(gè)子圖, 即為針對(duì)該切片準(zhǔn)則的一個(gè)程序切片。
由于程序切片技術(shù)最初用于軟件工程領(lǐng)域的程序調(diào)試和排錯(cuò), 因此經(jīng)典程序切片算法幾乎都是針對(duì)高級(jí)程序設(shè)計(jì)語(yǔ)言作為程序切片對(duì)象。然而在軟件安全分析領(lǐng)域, 如惡意代碼檢測(cè)和安全漏洞分析方面, 二進(jìn)制可執(zhí)行程序(Binary Executables)是主要的分析對(duì)象, 二進(jìn)制代碼與高級(jí)語(yǔ)言相比, 存在信息丟失(如變量的數(shù)據(jù)類(lèi)型信息丟失)和單語(yǔ)句/指令更復(fù)雜(如一條指令同時(shí)改變通用寄存器、狀態(tài)寄存器和內(nèi)存數(shù)據(jù))等差異, 因此已知的經(jīng)典程序切片算法對(duì)二進(jìn)制代碼的切片應(yīng)用仍存在很多挑戰(zhàn)[20]。盡管面向高級(jí)語(yǔ)言的程序切片技術(shù)得到了廣泛研究, 但是很少有面向二進(jìn)制代碼切片的深入研究[21-22]。本文基于二進(jìn)制代碼特性和惡意代碼檢測(cè)應(yīng)用場(chǎng)景, 改進(jìn)了靜態(tài)程序切片算法, 主要包括如下2個(gè)特性:
1)過(guò)程間切片(Interprocedural Slicing)改進(jìn): 對(duì)高級(jí)語(yǔ)言系統(tǒng)依賴(lài)圖進(jìn)行優(yōu)化, 識(shí)別過(guò)程間調(diào)用時(shí)形參和實(shí)參的輸入和輸出在系統(tǒng)依賴(lài)圖中的節(jié)點(diǎn), 減少圖中冗余的節(jié)點(diǎn)和邊, 降低圖計(jì)算復(fù)雜度。改進(jìn)過(guò)程將在3.1節(jié)中詳細(xì)描述。
2)切片粒度(Slicing Granularity)優(yōu)化: 針對(duì)二進(jìn)制代碼多賦值指令——一條指令中隱式包含多個(gè)輸入和輸出的情形, 將該指令轉(zhuǎn)換為單賦值的中間表示, 并對(duì)該指令對(duì)應(yīng)的系統(tǒng)依賴(lài)圖的節(jié)點(diǎn)進(jìn)行擴(kuò)展, 將該指令的中間表示作為一個(gè)子過(guò)程調(diào)用, 轉(zhuǎn)化為過(guò)程間調(diào)用的依賴(lài)關(guān)系分析問(wèn)題, 從而改善匯編代碼的多賦值特性帶來(lái)的切片粒度問(wèn)題。改進(jìn)過(guò)程將在3.2節(jié)中詳細(xì)描述。
本文第2章詳細(xì)描述了由M. Weiser提出的經(jīng)典程序切片算法以及一些擴(kuò)展算法研究, 這些算法的作用范圍通常是在一個(gè)過(guò)程或函數(shù)中的切片——過(guò)程內(nèi)切片(Intraprocedural Slicing)。隨著計(jì)算機(jī)程序越來(lái)越復(fù)雜, 許多應(yīng)用領(lǐng)域要求實(shí)現(xiàn)更為復(fù)雜的過(guò)程間切片輔助理解程序的結(jié)構(gòu)、功能、行為和邏輯設(shè)計(jì)。過(guò)程間切片與過(guò)程內(nèi)切片相比, 除了需要提取程序中每一個(gè)過(guò)程的控制依賴(lài)關(guān)系和數(shù)據(jù)依賴(lài)關(guān)系以外, 還需要提取過(guò)程調(diào)用關(guān)系和過(guò)程間參數(shù)傳遞依賴(lài)關(guān)系, 因此過(guò)程間切片的作用范圍是整個(gè)程序的依賴(lài)關(guān)系[23-26]。
S. Horwitz等提出了基于系統(tǒng)依賴(lài)圖的過(guò)程間程序切片方法, 該方法的核心思想是通過(guò)對(duì)程序依賴(lài)圖進(jìn)行擴(kuò)展, 添加用于刻畫(huà)過(guò)程調(diào)用以及參數(shù)傳遞的節(jié)點(diǎn)和邊, 并生成系統(tǒng)依賴(lài)圖, 最后應(yīng)用算法4描述的圖可達(dá)性算法實(shí)現(xiàn)過(guò)程間程序切片[27]。由于該方法是面向高級(jí)語(yǔ)言的程序切片, 因此基于高級(jí)語(yǔ)言的特點(diǎn), 需要在程序依賴(lài)圖中對(duì)每一個(gè)過(guò)程調(diào)用擴(kuò)展5類(lèi)節(jié)點(diǎn)和3類(lèi)邊用以描述過(guò)程間的依賴(lài)關(guān)系。表1中列出了高級(jí)語(yǔ)言過(guò)程間切片需要增加的節(jié)點(diǎn)和邊, 由于高級(jí)語(yǔ)言過(guò)程調(diào)用中的實(shí)參(Actual Parameter)和形參(Formal Parameter)允許不相同的變量名稱(chēng)表示, 因此在程序依賴(lài)圖中需要添加實(shí)參輸入和輸出、形參輸入和輸出節(jié)點(diǎn)用于在圖中描述參數(shù)傳遞過(guò)程, 而在二進(jìn)制代碼中, 如x64架構(gòu)下的過(guò)程調(diào)用, 前6個(gè)參數(shù)使用寄存器傳參, 第7個(gè)及更多的參數(shù)使用堆棧傳遞, 實(shí)參和形參實(shí)際上是同一個(gè)寄存器或堆棧地址, 因此二進(jìn)制代碼中不需要添加額外的參數(shù)傳遞節(jié)點(diǎn)即可以描述參數(shù)傳遞關(guān)系, 從本質(zhì)上看過(guò)程間的參數(shù)傳遞與2.2節(jié)中描述的“定義—引用”數(shù)據(jù)依賴(lài)關(guān)系相同, 可以保持與過(guò)程內(nèi)數(shù)據(jù)依賴(lài)分析相一致的處理過(guò)程。基于上述分析, 本文對(duì)基于高級(jí)語(yǔ)言的系統(tǒng)依賴(lài)圖生成方法進(jìn)行改進(jìn), 并在表1中進(jìn)行了對(duì)比, 本文提出的改進(jìn)方法減少了圖中頂點(diǎn)的數(shù)量, 降低了圖的復(fù)雜度, 并且使用數(shù)據(jù)依賴(lài)分析方法描述過(guò)程間參數(shù)傳遞關(guān)系。
圖1 改進(jìn)的二進(jìn)制代碼過(guò)程間切片示例 Figure 1 A sample of improved interprocedural slicing of binary executables
表1 二進(jìn)制程序系統(tǒng)依賴(lài)圖改進(jìn) Table 1 Improved binary executables’ SDG
圖1是本文提出的二進(jìn)制代碼過(guò)程間切片的一個(gè)示例, 圖中上方分別為C語(yǔ)言編寫(xiě)的示例代碼以及使用IDA Pro反匯編生成的對(duì)應(yīng)x64架構(gòu)匯編代碼, 在圖中的系統(tǒng)依賴(lài)圖中, main函數(shù)調(diào)用add函數(shù)時(shí)傳遞了2個(gè)參數(shù), 保存在EDI和ESI寄存器中, add函數(shù)中使用EDI和ESI寄存器中的值進(jìn)行運(yùn)算, 因此參數(shù)傳遞過(guò)程本質(zhì)上是寄存器ESI和EDI基于過(guò)程調(diào)用控制流的數(shù)據(jù)依賴(lài)關(guān)系, 從引用節(jié)點(diǎn)向定義節(jié)點(diǎn)引出一條邊就可以描述過(guò)程間調(diào)用的參數(shù)傳遞關(guān)系。
在二進(jìn)制代碼中, 如x86、x64、ARM等架構(gòu)的匯編語(yǔ)言代碼, 許多指令是多賦值的, 即一條指令中包括對(duì)多個(gè)變量的定義, 如在PUSH EAX指令中, 同時(shí)包含ESP=ESP-4和[ESP]=EAX兩條微指令(Microcode), 分別對(duì)ESP寄存器和[ESP]堆棧地址進(jìn)行賦值。由于二進(jìn)制代碼的多賦值屬性是一種隱式數(shù)據(jù)依賴(lài), 因此給二進(jìn)制代碼分析如程序切片、符號(hào)執(zhí)行和污點(diǎn)分析等帶來(lái)了巨大的挑戰(zhàn)[28]。
圖2和圖3的示例描述了二進(jìn)制代碼切片與高級(jí)語(yǔ)言程序切片的差異。在圖5的高級(jí)語(yǔ)言程序示例中, 我們以main函數(shù)的返回語(yǔ)句和返回值作為切片準(zhǔn)則執(zhí)行經(jīng)典的后向切片(在圖中以黑框標(biāo)示)。在程序中, multiply函數(shù)與main函數(shù)返回值不存在數(shù)據(jù)依賴(lài)關(guān)系, 因此程序切片不包含multiply函數(shù)(程序切片在圖中以陰影標(biāo)示)。同時(shí), 我們對(duì)圖2中的示例代碼使用IDA Pro反匯編生成圖3中的二進(jìn)制匯編代碼, 并使用相同的切片準(zhǔn)則執(zhí)行后向切片算法(包含在切片中的指令在圖中以陰影標(biāo)示), 我們發(fā)現(xiàn), 切片包含multiply函數(shù)中的全部指令, 而multiply函數(shù)在對(duì)應(yīng)的高級(jí)語(yǔ)言程序切片是不相關(guān)的代碼, 這使得程序切片包含了過(guò)多冗余代碼從而降低了切片的精度。為什么在二進(jìn)制切片中包含了multiply函數(shù)的代碼呢?原因在于切片準(zhǔn)則(第29行)中包括了EBP寄存器的引用, 而第8行指令LEAVE是一條多賦值指令, 語(yǔ)義上等價(jià)于MOV ESP, EBP和POP EBP兩條指令, 并且POP EBP指令也是一條多賦值指令, 語(yǔ)義上等價(jià)于EBP=[ESP]和ESP=ESP+4, 即EBP寄存器的定義依賴(lài)于ESP的值指向的堆棧地址, 因此當(dāng)把第8行LEAVE指令作為一個(gè)整體添加到切片時(shí), 由于多賦值指令無(wú)法拆分為更小單元, 因此當(dāng)LEAVE被添加到切片中時(shí), 會(huì)將更多的冗余指令序列引入到切片中, 這就是二進(jìn)制代碼的多賦值屬性在切片過(guò)程引發(fā)的粒度問(wèn)題, 即在某些情況下, 雖然我們希望切片只包含一條指令中若干微指令的一個(gè)子集, 但切片算法必須包含整個(gè)指令。此外切片粒度問(wèn)題還會(huì)引發(fā)級(jí)聯(lián)效應(yīng)(Cascade Effect), 不相關(guān)的指令將導(dǎo)致越來(lái)越多的不相關(guān)指令被切片準(zhǔn)則命中。
圖2 C語(yǔ)言后向靜態(tài)切片示例 Figure 2 A sample of backward static slicing for C
圖3 匯編語(yǔ)言后向靜態(tài)切片示例 Figure 3 A sample of backward static slicing for assembly
一些學(xué)者已開(kāi)始研究將二進(jìn)制匯編語(yǔ)言轉(zhuǎn)換成某種中間表示, 以應(yīng)對(duì)二進(jìn)制代碼切片引入的粒度問(wèn)題, 這種中間表示必須支持一個(gè)關(guān)鍵屬性即靜態(tài)單賦值(Static Single Assignment, SSA), 它要求在一條指令中僅為一個(gè)變量賦值一次, 并且在使用一個(gè)變量之前必須定義該變量[29-31]。由于靜態(tài)單賦值表示的“定義—引用”鏈?zhǔn)秋@式的, 因此轉(zhuǎn)換為中間表示的二進(jìn)制代碼可以和高級(jí)語(yǔ)言一樣運(yùn)用經(jīng)典的程序切片算法且不會(huì)包含過(guò)多不相關(guān)的冗余指令。
本文中, 我們選取VEX中間表示[32-33]作為二進(jìn)制代碼切片的切片表示, 并將“二進(jìn)制代碼—中間表示指令序列”的映射關(guān)系轉(zhuǎn)換看作過(guò)程間調(diào)用關(guān)系, 再應(yīng)用我們?cè)?.1節(jié)提出的過(guò)程間切片算法對(duì)包含中間表示的系統(tǒng)依賴(lài)圖執(zhí)行程序切片, 進(jìn)而盡可能消除切片中的不相關(guān)冗余代碼。圖4是x86架構(gòu)下LEAVE指令的VEX中間表示, 通過(guò)LEAVE指令轉(zhuǎn)換為6行中間表示代碼, 并且每行中間代碼都是靜態(tài)單賦值的, 因此滿(mǎn)足上述中間表示的要求。我們可將VEX微指令序列看作對(duì)應(yīng)二進(jìn)制匯編指令位置調(diào)用的子過(guò)程, 從更細(xì)的粒度上描述多賦值的二進(jìn)制指令。圖5是將二進(jìn)制代碼轉(zhuǎn)換成中間表示并生成改進(jìn)的系統(tǒng)依賴(lài)圖示例, 我們對(duì)圖3中multiply函數(shù)的系統(tǒng)依賴(lài)圖進(jìn)行擴(kuò)展, 將圖3第8行LEAVE指令轉(zhuǎn)換為中間表示, 并把中間表示看作LEAVE的子過(guò)程, 最后將二進(jìn)制代碼和局部中間表示作為一個(gè)整體生成EBP寄存器的數(shù)據(jù)依賴(lài)關(guān)系。由于中間表示顯式的描述了EBP寄存器的“定義—引用”鏈, 因此在multiply函數(shù)中對(duì)EBP寄存器執(zhí)行切片時(shí), 系統(tǒng)依賴(lài)圖可以準(zhǔn)確的描述EBP的依賴(lài)關(guān)系, 僅MOV EBP, ESP和LEAVE兩條指令包含在切片中。
根據(jù)以上分析, 對(duì)于任意給定的二進(jìn)制可執(zhí)行程序, 應(yīng)用中間表示生成的程序切片的非形式化過(guò)程如下:
圖4 LEAVE指令的VEX中間表示 Figure 4 VEX IR of LEAVE instruction
圖5 帶中間表示的改進(jìn)系統(tǒng)依賴(lài)圖 Figure 5 Improved SDG with IR
1)分析二進(jìn)制代碼的控制依賴(lài)關(guān)系和數(shù)據(jù)依賴(lài)關(guān)系, 應(yīng)用3.1節(jié)所述過(guò)程間切片方法生成系統(tǒng)依賴(lài)圖;
2)對(duì)二進(jìn)制指令中的多賦值指令, 如x86架構(gòu)下的ENTER、LEAVE、PUSH、POP等轉(zhuǎn)換為VEX中間表示, 將中間表示的指令序列看作子過(guò)程調(diào)用, 對(duì)系統(tǒng)依賴(lài)圖進(jìn)行局部擴(kuò)展, 重新生成局部控制依賴(lài)關(guān)系和數(shù)據(jù)依賴(lài)關(guān)系;
3)運(yùn)用基于圖的可達(dá)性程序切片算法, 對(duì)2)中改進(jìn)的系統(tǒng)依賴(lài)圖生成二進(jìn)制代碼切片。
惡意代碼檢測(cè)技術(shù)發(fā)展至今, 主要有兩種檢測(cè)方法:
1)規(guī)則式檢測(cè)(Rule-based Detection): 惡意代碼檢測(cè)引擎基于惡意代碼特征規(guī)則庫(kù)對(duì)樣本進(jìn)行檢測(cè), 規(guī)則庫(kù)主要包括針對(duì)惡意指令的指紋特征和針對(duì)惡意行為的模式特征。該檢測(cè)方法準(zhǔn)確率較高、檢測(cè)時(shí)間較短, 但需要預(yù)先定義規(guī)則, 因此對(duì)于已知樣本的檢測(cè)具有較好的效果, 對(duì)于未知樣本的檢測(cè)能力相對(duì)較弱。
2)啟發(fā)式檢測(cè)(Heuristic Detection): 通過(guò)監(jiān)視系統(tǒng)的活動(dòng)并將其分類(lèi)為正常或異常兩種狀態(tài)來(lái)檢測(cè)樣本是否具有惡意的企圖。當(dāng)前對(duì)異常狀態(tài)的判斷通?;跈C(jī)器學(xué)習(xí)算法, 這需要惡意代碼檢測(cè)引擎進(jìn)行一段時(shí)間的訓(xùn)練和建模。由于該檢測(cè)方法基于統(tǒng)計(jì)特征和概率決策模型, 因此通常具有一定的誤報(bào)率, 并且檢測(cè)性能較低, 但對(duì)于未知樣本檢測(cè)相對(duì)于規(guī)則式檢測(cè)具有較高的召回率。
圖6描述了惡意代碼檢測(cè)一般模型, 當(dāng)待檢測(cè)樣本文件投入到惡意代碼檢測(cè)引擎中, 檢測(cè)引擎首先提取樣本文件特征并與引擎內(nèi)置規(guī)則庫(kù)進(jìn)行比較, 進(jìn)而判斷樣本是否為惡意樣本。若基于規(guī)則式檢測(cè)無(wú)法判別結(jié)果, 引擎進(jìn)一步通過(guò)啟發(fā)式檢測(cè)對(duì)樣本多維度特征的狀態(tài)進(jìn)行分類(lèi), 并由專(zhuān)家基于分類(lèi)結(jié)果進(jìn)行決策, 最終輸出檢測(cè)報(bào)告。
圖6 惡意代碼檢測(cè)一般模型 Figure 6 General model of malware detection
隨著新型惡意代碼的出現(xiàn), 隱形惡意代碼(Stealth Malware)、多態(tài)惡意代碼(Polymorphic Malware)、加密惡意代碼(Encrypted Malware)和多歧惡意代碼(Multipartite Malware)使得基于規(guī)則的惡意代碼檢測(cè)方法難以有效檢測(cè), 因此惡意代碼檢測(cè)研究?jī)A向于對(duì)啟發(fā)式檢測(cè)能力進(jìn)行增強(qiáng)。其中, 惡意軟件同源性分析(Malware Homology Analysis)是一種借助于威脅情報(bào)和大數(shù)據(jù)分析方法的惡意代碼檢測(cè)和分析方法[34-35], 也是當(dāng)前的惡意代碼分析和溯源研究的熱點(diǎn)問(wèn)題之一。網(wǎng)絡(luò)攻擊組織通常利用系統(tǒng)漏洞或社會(huì)工程傳播惡意代碼, 獲得目標(biāo)主機(jī)權(quán)限或竊取敏感數(shù)據(jù)。由于同一網(wǎng)絡(luò)攻擊組織通常使用相同家族的惡意代碼, 或同一作者編寫(xiě)的惡意代碼, 因此惡意樣本間具有內(nèi)在相關(guān)性和相似性[36]。惡意代碼同源性分析采集威脅情報(bào)中網(wǎng)絡(luò)攻擊組織關(guān)聯(lián)的所有已知惡意樣本, 提取樣本關(guān)鍵特征并建模, 使用該模型對(duì)待檢測(cè)樣本進(jìn)行分類(lèi), 判斷是否與已知攻擊組織的惡意樣本具有同源性進(jìn)而判斷待檢測(cè)樣本是否為惡意樣本。
Jieran Liu等[37]學(xué)者提出了一種基于圖嵌入網(wǎng)絡(luò)(Graph Embedding Network)的惡意代碼同源性分析方法, 該方法提取程序控制流圖和代碼統(tǒng)計(jì)特征, 結(jié)合了圖嵌入特征表示算法和深度學(xué)習(xí)模型, 對(duì)來(lái)自于同一網(wǎng)絡(luò)攻擊組織的惡意代碼建立分類(lèi)模型, 并使用該模型對(duì)待檢測(cè)樣本進(jìn)行分類(lèi)預(yù)測(cè)。Jieran Liu等基于該方法實(shí)現(xiàn)了原型系統(tǒng)MCrab, 系統(tǒng)的工作流如下:
1)采集威脅情報(bào)中與網(wǎng)絡(luò)攻擊組織相關(guān)聯(lián)的惡意代碼樣本集。
2)提取惡意代碼樣本中對(duì)應(yīng)的原始特征, 包括匯編指令序列、函數(shù)(過(guò)程)入口點(diǎn)集合、和函數(shù)(過(guò)程)內(nèi)控制流圖等樣本代碼的基礎(chǔ)特征。
3)對(duì)惡意代碼樣本原始特征進(jìn)行處理和泛化, 包括2個(gè)部分: 一是對(duì)函數(shù)內(nèi)基本塊的特征進(jìn)行泛化, 包括字符串常量數(shù)、內(nèi)存操作指令數(shù)、轉(zhuǎn)移指令數(shù)、CALL指令數(shù)、總指令數(shù)和算術(shù)指令數(shù)共6類(lèi)特征; 二是對(duì)函數(shù)內(nèi)控制流圖執(zhí)行圖嵌入算法, 將圖結(jié)構(gòu)轉(zhuǎn)化為n維特征向量。
4)使用深度學(xué)習(xí)算法LSTM對(duì)第3步中經(jīng)過(guò)處理和泛化的多維惡意代碼特征向量進(jìn)行訓(xùn)練, 生成不同網(wǎng)絡(luò)攻擊組織的惡意代碼同源性檢測(cè)模型。
5)當(dāng)待檢測(cè)樣本輸入到檢測(cè)模型時(shí), 模型對(duì)樣本是否與某個(gè)網(wǎng)絡(luò)攻擊組織的關(guān)聯(lián)惡意代碼集做出相似性判斷, 供專(zhuān)家決策, 并將判別結(jié)果反饋到威脅情報(bào)中, 形成檢測(cè)模型持續(xù)優(yōu)化的閉環(huán)。
在上述MCrab原型系統(tǒng)的工作流中, 首先對(duì)二進(jìn)制可執(zhí)行文件的所有函數(shù)提取控制流圖以及基本塊的指令統(tǒng)計(jì)特征, 并對(duì)特征進(jìn)行清洗和預(yù)處理, 最后使用機(jī)器學(xué)模型進(jìn)行訓(xùn)練。盡管實(shí)驗(yàn)表明MCrab具有較高的準(zhǔn)確率, 然而, 對(duì)于二進(jìn)制可執(zhí)行程序而言, 程序從源代碼經(jīng)過(guò)編譯、鏈接生成可執(zhí)行程序, 并非所有的代碼片段都用于實(shí)現(xiàn)程序功能, 大多數(shù)編譯器會(huì)在插入一些代碼用于異常處理和執(zhí)行優(yōu)化, 而惡意代碼作者也可能插入無(wú)用代碼對(duì)抗安全分析。因此, 有必要在訓(xùn)練檢測(cè)模型之前從樣本原始特征中去除無(wú)用的代碼片段, 以提高惡意代碼檢測(cè)模型的準(zhǔn)確率和召回率?;诮?jīng)驗(yàn)的歸納, 二進(jìn)制可執(zhí)行程序中存在如下2種無(wú)用代碼片段:
1)代碼片段在控制依賴(lài)關(guān)系上不可達(dá): 在函數(shù)間調(diào)用圖和函數(shù)內(nèi)控制流圖上均不存在從入口點(diǎn)到該代碼片段的路徑;
2)代碼片段在數(shù)據(jù)依賴(lài)關(guān)系上不可達(dá): 代碼片段在函數(shù)調(diào)用參數(shù)和函數(shù)內(nèi)變量上均無(wú)定義-引用關(guān)系。
為了更有效提取惡意代碼特征, 本文改進(jìn)了Jieran Liu提出的惡意代碼同源性檢測(cè)方法, 在圖7中描述了基于MCrab原型系統(tǒng)改進(jìn)的檢測(cè)方法工作流, 我們進(jìn)一步對(duì)提取的惡意代碼樣本原始特征分 析二進(jìn)制代碼的控制依賴(lài)關(guān)系和數(shù)據(jù)依賴(lài)關(guān)系, 輸出系統(tǒng)依賴(lài)圖, 并根據(jù)預(yù)先設(shè)定的一組表征惡意行為的切片準(zhǔn)則執(zhí)行程序切片, 最后將每組程序切片輸入到圖嵌入網(wǎng)絡(luò)中生成多為特征向量, 最后訓(xùn)練檢測(cè)模型。本文對(duì)MCrab的優(yōu)化所使用的程序切片算法是對(duì)經(jīng)典程序切片算法面向二進(jìn)制代碼的改進(jìn), 并已在第3章中進(jìn)行了闡述。
圖7 惡意代碼同源性檢測(cè)工作流 Figure 7 Workflow of malware homology detection
為了對(duì)惡意代碼的原始特征進(jìn)行清洗和預(yù)處理, 提高分類(lèi)模型的準(zhǔn)確率和召回率, 我們通過(guò)人工分析10個(gè)網(wǎng)絡(luò)攻擊組織所使用的傳播范圍為T(mén)OP 100的惡意代碼樣本, 設(shè)計(jì)了一組被惡意代碼廣泛使用的切片準(zhǔn)則[38-39], 分別為基礎(chǔ)行為切片準(zhǔn)則和反分析行為切片準(zhǔn)則共兩類(lèi), 切片準(zhǔn)則清單在表2中列出。其中, 基礎(chǔ)行為切片準(zhǔn)則包括文件行為、注冊(cè)表行為、網(wǎng)絡(luò)行為、進(jìn)程/線(xiàn)程行為等共22條; 反分析行為切片準(zhǔn)則包括反虛擬機(jī)行為、反沙盒行為和反調(diào)試行為共20條, 合計(jì)提取42條關(guān)鍵切片準(zhǔn)則。
依據(jù)惡意代碼的惡意行為的共性特征, 本文對(duì)經(jīng)典切片準(zhǔn)則進(jìn)行擴(kuò)展, 將其描述為如下三元組: <{API, instructions}, {parameters}, {return values}>。其中, 第一個(gè)元素{API, instructions}用于定位程序切片的起始位置, 包括關(guān)鍵API調(diào)用或關(guān)鍵匯編指令; 第二個(gè)元素{parameters}是API的參數(shù), 描述程序切片起始位置的后向(Backward)數(shù)據(jù)依賴(lài)關(guān)系; 第三個(gè)元素{return values}是API的返回值(在IA架構(gòu)下由EAX或RAX寄存器保存)以及通過(guò)指針?lè)绞絺魅氲膮?shù)返回值, 該元素描述程序切片起始位置的前向(Forward)數(shù)據(jù)依賴(lài)關(guān)系。表3以反沙盒行為切片準(zhǔn)則為示例, 列出了本文所提取的惡意代碼用于檢測(cè)沙盒行為的8條切片準(zhǔn)則, 其余切片準(zhǔn)則均遵循上述的三元組進(jìn)行定義, 并提取能夠表示惡意代碼關(guān)鍵行為的特征。
表2 切片準(zhǔn)則清單 Table 2 Slicing criterion list
表3 反沙盒行為切片準(zhǔn)則列表 Table 3 Slicing criterion list of anti-sandbox behaviors
為驗(yàn)證第4章中所描述的基于二進(jìn)制代碼切片的惡意代碼同源性分析方法的效果, 本文以MCrab數(shù)據(jù)集為實(shí)驗(yàn)對(duì)象, 并以MCrab作為評(píng)估基線(xiàn), 對(duì)本文提出的方法進(jìn)行評(píng)估。
本實(shí)驗(yàn)使用的數(shù)據(jù)集包括從公開(kāi)威脅情報(bào)中獲取的10個(gè)具有廣泛影響的網(wǎng)絡(luò)攻擊組織或安全事件所使用的惡意代碼樣本集合計(jì)4053個(gè), 使用二進(jìn)制代碼分析工具IDA Pro對(duì)所有樣本進(jìn)行分析, 提取樣本原始特征, 包括每個(gè)惡意代碼樣本的自定義函數(shù)清單, 輸出每個(gè)函數(shù)的匯編指令序列和控制流圖。我們的實(shí)驗(yàn)首先使用MCrab對(duì)數(shù)據(jù)集提取原始特征, 共獲取自定義函數(shù)364626個(gè)。作為對(duì)比, 我們基于4.2節(jié)中定義的切片準(zhǔn)則, 執(zhí)行程序切片算法對(duì)樣本的原始特征進(jìn)一步預(yù)處理, 提取與惡意行為關(guān)鍵代碼片段存在依賴(lài)關(guān)系的自定義函數(shù), 獲取304675個(gè)自定義函數(shù)(占原始特征中全部自定義函數(shù)的83.6%)。表4列出了數(shù)據(jù)集中10個(gè)網(wǎng)絡(luò)攻擊組織或安全事件的惡意代碼樣本數(shù)和自定義函數(shù)對(duì)比情況。
表4 數(shù)據(jù)集預(yù)處理結(jié)果列表 Table 4 List of dataset preprocessing result
在數(shù)據(jù)集預(yù)處理過(guò)程中, 程序切片算法基于Triton[40]二進(jìn)制分析框架開(kāi)發(fā), 使用Triton內(nèi)置的抽象語(yǔ)法樹(shù)(AbstractSyntax Tree)實(shí)現(xiàn)中間層語(yǔ)義表示, 并通過(guò)調(diào)用Microsoft Z3 約束求解器接口實(shí)現(xiàn)靜態(tài)符號(hào)執(zhí)行, 獲取系統(tǒng)依賴(lài)圖, 最后基于圖的可達(dá)性提取程序切片。此外, 我們使用Valgrind工具將多賦值的二進(jìn)制指令轉(zhuǎn)換為VEX中間表示。由于本實(shí)驗(yàn)采用靜態(tài)程序切片, 因此在不確定程序?qū)嶋H執(zhí)行路徑的情況下, 我們選擇了相對(duì)保守的程序切片參數(shù), 從表4中看出, 10個(gè)網(wǎng)絡(luò)攻擊組織或安全事件中, 除了stuxnet“震網(wǎng)病毒”事件以外, 執(zhí)行程序切片后的自定義函數(shù)個(gè)數(shù)約占全部函數(shù)個(gè)數(shù)的83%~88%, 通過(guò)人工選取數(shù)據(jù)集中的典型樣本驗(yàn)證, 未包含在程序切片中的函數(shù)主要是編譯器自動(dòng)添加的輔助代碼和無(wú)交叉引用關(guān)系的函數(shù)。其中, stuxnet事件樣本的程序切片后函數(shù)個(gè)數(shù)占全部函數(shù)個(gè)數(shù)的比例為71%, 通過(guò)人工分析597個(gè)stuxnet樣本中的10個(gè)典型樣本, 我們發(fā)現(xiàn)stuxnet中的許多樣本僅包括由匯編語(yǔ)言編寫(xiě)的漏洞利用代碼, 而不包括惡意代碼中常見(jiàn)的遠(yuǎn)程控制、數(shù)據(jù)竊取、逃逸檢測(cè)、持久化等通用惡意功能, 因此依據(jù)4.2節(jié)中設(shè)置的切片準(zhǔn)則, 獲取的程序切片較小??偟膩?lái)看, 程序切片后的代碼集最大的保留了惡意代碼中的關(guān)鍵惡意行為特征。
我們以MCrab實(shí)驗(yàn)結(jié)果作為基準(zhǔn), 與本文提出的使用程序切片處理后的樣本特征訓(xùn)練的模型進(jìn)行比較。同時(shí), 我們也選取了典型機(jī)器學(xué)習(xí)算法對(duì)樣本原始特征進(jìn)行訓(xùn)練, 并與本文方法進(jìn)行對(duì)比。實(shí)驗(yàn)步驟描述如下:
1)代碼塊內(nèi)統(tǒng)計(jì)特征提取: 采用卷積神經(jīng)網(wǎng)絡(luò)(Convolutional Neural Networks, CNN)算法, 將代碼塊內(nèi)的匯編指令序列作為文本進(jìn)行處理, 輸出代碼塊內(nèi)多維特征向量;
2)函數(shù)內(nèi)(基本塊間)控制流圖提取: 采用Ribeiro等提出的Struc2Vec圖嵌入網(wǎng)絡(luò)算法[41], 將控制流圖結(jié)構(gòu)轉(zhuǎn)換為多維特征向量;
3)樣本預(yù)測(cè)分析模型: 采用MCrab中提出的改進(jìn)的長(zhǎng)短期記憶時(shí)間循環(huán)神經(jīng)網(wǎng)絡(luò)(Long Short-Term Memory, LSTM), 通過(guò)該模型預(yù)測(cè)待檢測(cè)樣本所屬的網(wǎng)絡(luò)攻擊組織或安全事件分類(lèi)。
實(shí)驗(yàn)將數(shù)據(jù)集按照8∶2的比例隨機(jī)分割為訓(xùn)練集和測(cè)試集, 分別應(yīng)用不同的模型進(jìn)行訓(xùn)練和驗(yàn)證。表5顯示了文本方法與多種經(jīng)典模型的對(duì)比, 其中, 除LSTM模型外其他模型的準(zhǔn)確率均低于90%, 本文在MCrab模型的基礎(chǔ)上對(duì)樣本原始特征執(zhí)行程序切片后, 準(zhǔn)確率達(dá)到94.7%, 極大的改進(jìn)了惡意代碼樣本分類(lèi)的準(zhǔn)確程度。
作為基線(xiàn), 我們同時(shí)詳細(xì)比較了Mcrab與本文方法, 圖8描述了epoch取值1~160之間的準(zhǔn)確率和損失函數(shù)值對(duì)比。其中, 圖8(a)所示, 本文的方法當(dāng)?shù)螖?shù)為30即epoch=30時(shí)的模型準(zhǔn)確率即達(dá)到90%, 而MCrab當(dāng)?shù)螖?shù)為epoch=48時(shí)準(zhǔn)確率達(dá)到90%, 經(jīng)過(guò)160輪迭代后, 本文方法的準(zhǔn)確率為94.7%, 而MCrab的結(jié)果為94.2%。另一方面, 在圖8(b)所示的損失函數(shù)值對(duì)比中, 本文方法比MCrab生成了具有更低損失函數(shù)的模型。
表5 經(jīng)典模型實(shí)驗(yàn)結(jié)果對(duì)比 Table 5 Compare with state-of-art models
圖8 Mcrab實(shí)驗(yàn)結(jié)果對(duì)比 Figure 8 Comparison with experiment result of Mcrab
本文的方法由于對(duì)原始特征執(zhí)行了基于程序切片的預(yù)處理, 因此無(wú)論與經(jīng)典機(jī)器學(xué)習(xí)模型對(duì)比, 還是與參考基線(xiàn)Mcrab比較, 在模型訓(xùn)練效率和分類(lèi)準(zhǔn)確率上均有不同程度改善。然而, 通過(guò)對(duì)分類(lèi)錯(cuò)誤的惡意代碼樣本進(jìn)行了人工分析, 本方法仍存在如下局限性:
1)面向內(nèi)存數(shù)據(jù)的數(shù)據(jù)依賴(lài)分析: 與許多高級(jí)語(yǔ)言不同, 匯編語(yǔ)言不是強(qiáng)類(lèi)型語(yǔ)言, 操作碼僅可以表示操作數(shù)寬度, 并且在同一個(gè)作用域內(nèi)可以通過(guò)寄存器、立即數(shù)和內(nèi)存地址引用等多種方式定義或引用指定內(nèi)存地址的數(shù)據(jù), 因此這對(duì)于數(shù)據(jù)依賴(lài)分析帶來(lái)了挑戰(zhàn)。如REP STOSB指令, 從ESI寄存器指向的源地址向EDI寄存器指向的目的地址拷貝數(shù)據(jù), 數(shù)據(jù)長(zhǎng)度由ECX寄存器指定, 該指令的操作完成后使得[EDI]至[EDI+ECX]的內(nèi)存區(qū)域被重新定義, 但對(duì)于該區(qū)域的數(shù)據(jù)依賴(lài)分析難以通過(guò)匯編代碼語(yǔ)義的靜態(tài)分析實(shí)現(xiàn)。其他如MOVS、LODS等指令亦存在類(lèi)似的情形, 這降低了切片分析的準(zhǔn)確度, 從而影響本文方法的樣本原始特征的處理。
2)間接函數(shù)調(diào)用: 由于本文提出的方法僅針對(duì)樣本原始特征執(zhí)行程序切片, 而樣本的原始特征是基于IDA Pro工具靜態(tài)分析得到的匯編指令序列和函數(shù)調(diào)用圖, 因此對(duì)于類(lèi)似CALL DWORD PTR [EAX]的指令無(wú)法通過(guò)靜態(tài)分析函數(shù)調(diào)用關(guān)系。此外, 許多惡意代碼中包含了直接使用匯編語(yǔ)言編寫(xiě)的Shellcode, 導(dǎo)致IDA Pro無(wú)法解析, 使得程序切片算法無(wú)法構(gòu)建系統(tǒng)調(diào)用圖。圖9中的示例中, 位于.text:00402235的call $+5指令是Shellcode中常見(jiàn)的獲取當(dāng)前地址的方法, 但I(xiàn)DA Pro無(wú)法正確解析; 位于.text:0040223E處的JMP EDX指令在靜態(tài)分析時(shí)也無(wú)法確定跳轉(zhuǎn)目的地址。
3)漏洞利用樣本: 對(duì)于通過(guò)漏洞傳播的惡意代碼, 樣本中包括特定的漏洞利用代碼片段, 由于不同類(lèi)型的漏洞利用方式各不相同, 因此在文本提出的42條切片準(zhǔn)則中無(wú)法枚舉所有的漏洞利用方式。值得說(shuō)明的是, 如果惡意代碼在漏洞利用后實(shí)現(xiàn)了遠(yuǎn)程控制、數(shù)據(jù)竊取、逃逸檢測(cè)等惡意功能, 仍可通過(guò)4.2節(jié)中定義的切片準(zhǔn)則提起關(guān)鍵特征。對(duì)于數(shù)據(jù)集中的極少數(shù)僅包括漏洞利用代碼片段的惡意代碼, 應(yīng)用本文的程序切片后將導(dǎo)致漏洞利用代碼的特征被裁剪, 因此無(wú)法正確檢測(cè)和分類(lèi)。
圖9 間接調(diào)用示例 Figure 9 A sample of indirect invocation
程序理解是一種從計(jì)算機(jī)程序中獲取知識(shí)信息的過(guò)程。這些知識(shí)信息可以應(yīng)用于軟件測(cè)試、軟件安全分析、軟件二次開(kāi)發(fā)等方面。程序理解是軟件工程領(lǐng)域里的一個(gè)重要部分, 運(yùn)用程序理解方法可以從不同的抽象級(jí)別上建立軟件的概念模型, 包括從代碼本身的模型到基本應(yīng)用領(lǐng)域的模型。依據(jù)不同的抽象層次, 可以將程序理解分為三類(lèi): 設(shè)計(jì)模型、代碼模型和二進(jìn)制模型。二進(jìn)制模型的研究對(duì)象是二進(jìn)制代碼, 在信息安全領(lǐng)域, 分析人員常需要提取二進(jìn)制形式的軟件內(nèi)部算法、分析安全漏洞、解密隱蔽信息等, 同時(shí)也需要對(duì)惡意代碼的惡意功能和行為進(jìn)行分析和理解, 從而確定二進(jìn)制代碼的安全屬性[42-43]。
本文討論的程序切片技術(shù)是程序理解方法之一, 是一種通過(guò)對(duì)程序進(jìn)行分解進(jìn)而對(duì)程序關(guān)鍵代碼進(jìn)行深入分析的方法。此外, 學(xué)者們還針對(duì)不同的應(yīng)用場(chǎng)景提出了4種程序理解方法。
方法一: 模式匹配方法, 一種在不同的抽象層次上對(duì)程序的各種模式進(jìn)行匹配的過(guò)程。該方法按照從低到高的抽象層次建立文本模式、語(yǔ)法樹(shù)模式、控制流/數(shù)據(jù)流圖模式、概念模式等, 并對(duì)于不同的應(yīng)用領(lǐng)域分別實(shí)現(xiàn)上述一個(gè)或多個(gè)抽象層次的模式匹配, 理解目標(biāo)程序的結(jié)構(gòu)、功能和行為。
方法二: 概念賦值和分析方法, 一種通過(guò)將物理世界中概念與計(jì)算機(jī)邏輯程序進(jìn)行映射, 進(jìn)而實(shí)現(xiàn)程序理解的方法。概念賦值(Concept Assignment)是一種基于語(yǔ)義的模式匹配, 并將可識(shí)別的概念與計(jì)算機(jī)程序建立映射的一種理解的過(guò)程。概念分析(Concept Analysis)把任何對(duì)象和內(nèi)部屬性之問(wèn)的關(guān)系轉(zhuǎn)換成代數(shù)格, 然后運(yùn)用數(shù)學(xué)形式化方法來(lái)研究物理概念和邏輯程序間關(guān)系。
方法三: 程序分析方法, 從是否執(zhí)行程序的角度看, 程序分析包括靜態(tài)分析和動(dòng)態(tài)分析兩種方式。靜態(tài)程序分析是在不執(zhí)行目標(biāo)程序的狀態(tài)下, 僅根據(jù)選取的模型推斷程序功能和行為的過(guò)程。靜態(tài)程序分析包括語(yǔ)法分析、控制流和數(shù)據(jù)流分析、交叉引用分析等過(guò)程; 動(dòng)態(tài)程序分析是在目標(biāo)程序中發(fā)現(xiàn)運(yùn)行時(shí)(Runtime)依賴(lài)的過(guò)程。它包括對(duì)象實(shí)例依賴(lài)、多態(tài)性、函數(shù)調(diào)用圖、并發(fā)等分析過(guò)程。
方法四: 智能理解方法, 運(yùn)用人工智能和專(zhuān)家系統(tǒng)技術(shù), 提取程序內(nèi)部的結(jié)構(gòu)、功能、行為和邏輯設(shè)計(jì)等特征, 通過(guò)訓(xùn)練機(jī)器學(xué)習(xí)模型, 對(duì)程序進(jìn)行分類(lèi)預(yù)測(cè)或聚類(lèi), 輔助進(jìn)行軟件理解。
一些學(xué)者已經(jīng)對(duì)方法三和方法四開(kāi)展了廣泛而深入的研究, 以應(yīng)對(duì)網(wǎng)絡(luò)空間中日益嚴(yán)峻的軟件安全漏洞和惡意代碼傳播, 特別是DARPA于2016年舉辦的網(wǎng)絡(luò)安全挑戰(zhàn)賽Cyber Grand Challenge(CGC)中, 二進(jìn)制程序分析方法在安全漏洞自動(dòng)化發(fā)現(xiàn)和修復(fù)等方面取得了極大的成功。許多研究已開(kāi)始瞄準(zhǔn)如何自動(dòng)化、體系化、規(guī)模化開(kāi)展二進(jìn)制程序分析。
B. David等[28,44]學(xué)者提出了一個(gè)二進(jìn)制代碼分析框架BAP, 用于對(duì)二進(jìn)制代碼進(jìn)行逆向工程和程序分析, BAP將任何輸入的二進(jìn)制匯編代碼轉(zhuǎn)換成一種中間表示BIL, BIL顯式表示了匯編指令的所有隱式特性, 這使得所有的二進(jìn)制分析都可以基于BIL的語(yǔ)法實(shí)現(xiàn)自動(dòng)化處理。BAP內(nèi)置了常見(jiàn)的代碼表示形式, 包括控制流圖、程序依賴(lài)圖、帶有常量合并的數(shù)據(jù)流框架、死代碼消除(Dead Code Elimination)、值集分析(Value Set Analysis, VSA)等。此外, BAP還支持ARM, x86, x86-64, PowerPC, MIPS多種指令架構(gòu)。
S. Nick等[45-46]學(xué)者提出了一種選擇性動(dòng)態(tài)符號(hào)執(zhí)行的模糊測(cè)試方法, 并實(shí)現(xiàn)了基于模糊測(cè)試框架AFL[47]和二進(jìn)制代碼分析框架angr[48]的工具Driller。與其他許多利用符號(hào)執(zhí)行生成輸入用例以獲得更高代碼覆蓋率的模糊測(cè)試方法不同[49-50], Driller通過(guò)監(jiān)測(cè)模糊器Fuzzer的執(zhí)行過(guò)程, 當(dāng)一輪輸入執(zhí)行完成后未發(fā)生基本塊轉(zhuǎn)換時(shí)(即沒(méi)有新的控制流圖的邊被執(zhí)行), 則對(duì)一個(gè)具體的輸入用例執(zhí)行動(dòng)態(tài)符號(hào)執(zhí)行, 這種選擇性符號(hào)執(zhí)行極大的改善了路徑爆炸的問(wèn)題。其中, Driller的動(dòng)態(tài)符號(hào)執(zhí)行所依賴(lài)的angr二進(jìn)制分析框架, 將二進(jìn)制代碼轉(zhuǎn)換為中間表示VEX, 基于動(dòng)態(tài)二進(jìn)制分析框架Valgrind[32], 實(shí)現(xiàn)內(nèi)存異常檢測(cè)、線(xiàn)程異常檢測(cè)、緩存和分支預(yù)測(cè)、以及堆分析器等二進(jìn)制代碼動(dòng)態(tài)分析能力。
J. Minkyu等學(xué)者通過(guò)分析和評(píng)估二進(jìn)制代碼分析框架的前端組件(反編匯、中間表示)和后端組件(控制流分析、數(shù)據(jù)流分析)的依賴(lài)關(guān)系, 將注意力從大量研究后端組價(jià)如何執(zhí)行二進(jìn)制分析轉(zhuǎn)移到前端組件中, 關(guān)注前端組件如何為后端組件提供支撐, 并實(shí)現(xiàn)了一個(gè)二進(jìn)制帶分析框架B2R2[51]。文章提出了一種新的中間表示轉(zhuǎn)換技術(shù), 并利用多核并行計(jì)算技術(shù)極大的提高了性能, 通過(guò)與現(xiàn)有許多二進(jìn)制分析框架的比較, B2R2改善了中間表示轉(zhuǎn)換的性能, 并具備良好的后端分析如代碼可視化和動(dòng)態(tài)符號(hào)執(zhí)行的能力。
另一方面, 隨著人工智能技術(shù)的發(fā)展, 一些學(xué)者已開(kāi)始將數(shù)據(jù)挖掘和機(jī)器學(xué)習(xí)算法應(yīng)用到惡意代碼檢測(cè)中。K. Rajesh等學(xué)者將惡意代碼文件的比特流轉(zhuǎn)換為灰度圖像, 并運(yùn)用圖像相似性算法, 結(jié)合卷積神經(jīng)網(wǎng)絡(luò)對(duì)惡意代碼樣本進(jìn)行預(yù)測(cè)和分類(lèi)[52]。F. Xiao等學(xué)者針對(duì)IoT設(shè)備傳播的惡意代碼, 提取惡意代碼API調(diào)用圖特征(而不是傳統(tǒng)方法中的API調(diào)用序列特征), 并利用自編碼器網(wǎng)絡(luò)訓(xùn)練惡意代碼檢測(cè)模型, 并實(shí)現(xiàn)了原型工具BDLF[53]。J. Li等學(xué)者將關(guān)注點(diǎn)瞄準(zhǔn)了移動(dòng)APP惡意代碼, 通過(guò)有選擇的提取APP權(quán)限特征, 結(jié)合多種機(jī)器學(xué)習(xí)算法實(shí)現(xiàn)惡意代碼預(yù)測(cè)和分析, 文章實(shí)現(xiàn)了原型工具SigPID, 并在實(shí)驗(yàn)中展示了其對(duì)于大規(guī)模惡意代碼的快速檢測(cè)的良好效果[54]。
本文通過(guò)總結(jié)程序理解領(lǐng)域中的一種重要方法——程序切片的發(fā)展和研究現(xiàn)狀, 并針對(duì)惡意代碼檢測(cè)的實(shí)際應(yīng)用場(chǎng)景, 基于經(jīng)典程序切片技術(shù)提出了面向二進(jìn)制代碼切片的改進(jìn)方法, 結(jié)合人工分析不同類(lèi)型的惡意代碼樣本提取了表示惡意行為特征的42條切片準(zhǔn)則, 最后, 我們?cè)趯?shí)驗(yàn)中通過(guò)本文方法對(duì)惡意代碼樣本的原始特征進(jìn)行預(yù)處理, 并運(yùn)用機(jī)器學(xué)習(xí)算法訓(xùn)練模型, 用于惡意代碼同源性檢測(cè)。實(shí)驗(yàn)結(jié)果表明, 本文提出的方法在惡意代碼同源性檢測(cè)方面改善了檢測(cè)準(zhǔn)確率, 并且降低了檢測(cè)模型訓(xùn)練時(shí)間和迭代次數(shù)。
然而, 在本文的實(shí)驗(yàn)中, 我們也看到本文提出的方法在檢測(cè)間接函數(shù)調(diào)用和特定惡意代碼樣本(如漏洞利用樣本)時(shí)仍存在一定的局限性, 未來(lái)需要在如下兩個(gè)方面開(kāi)展進(jìn)一步的研究: (1)應(yīng)用動(dòng)態(tài)程序切片技術(shù)改進(jìn)二進(jìn)制匯編代碼級(jí)別上的間接函數(shù)調(diào)用場(chǎng)景的控制流/數(shù)據(jù)流分析; (2)進(jìn)一步完善表征惡意代碼行為的切片準(zhǔn)則庫(kù), 更準(zhǔn)確全面地提取惡意代碼中的關(guān)鍵惡意行為的程序切片。
致 謝 本文的研究得到了國(guó)家自然科學(xué)基金重點(diǎn)項(xiàng)目(U1736218)和科技部重大專(zhuān)項(xiàng)(2018YFB0804704)的資助, 本文的基礎(chǔ)研究平臺(tái)得到了國(guó)家互聯(lián)網(wǎng)應(yīng)急中心(CNCERT/CC)運(yùn)行部的支持, 本文的實(shí)驗(yàn)數(shù)據(jù)集和對(duì)照基準(zhǔn)參考了CNCERT/CC運(yùn)行部網(wǎng)絡(luò)安全研究組的科研成果MCrab原型系統(tǒng), 在此表示衷心的感謝。