肖 瑋,周安民,賈 鵬
(四川大學(xué)網(wǎng)絡(luò)空間安全學(xué)院,成都 610065)
軟件技術(shù)在給人們帶來(lái)便利生活的同時(shí),也帶來(lái)了潛在的信息安全問題。作為計(jì)算機(jī)安全重要的一部分,軟件安全指在受到惡意攻擊的情況下軟件依然能夠正確運(yùn)行,以及確保軟件能在授權(quán)范圍內(nèi)被合法使用的思想。與之相對(duì)的則是軟件中存在的漏洞。
通常在一般情況下漏洞不會(huì)影響程序功能,但如果攻擊者加以利用,就有可能使之執(zhí)行攻擊者編寫的惡意代碼進(jìn)而危害用戶的信息安全。因此漏洞檢測(cè)在軟件和系統(tǒng)安全中起著至關(guān)重要的作用,模糊測(cè)試技術(shù)作為一種有效的漏洞挖掘技術(shù),得到了廣泛的研究和應(yīng)用。自1990年Miller 等提出了第一個(gè)模糊測(cè)試工具后,逐漸發(fā)展出了許多有效的方法和框架。近年來(lái)的研究通過引入污點(diǎn)分析和符號(hào)執(zhí)行等一些新技術(shù),提高了模糊測(cè)試的效率,并且在軟件程序中發(fā)現(xiàn)了許多漏洞。
目前最流行的灰盒模糊測(cè)試工具AFL 根據(jù)二元組(跳轉(zhuǎn)的源地址,目標(biāo)地址)來(lái)記錄執(zhí)行分支信息,從而獲取目標(biāo)程序的執(zhí)行流程和代碼覆蓋情況。AFL 首先從初始種子隊(duì)列中選擇種子進(jìn)行一系列變異,將變異后的測(cè)試用例作為輸入文件執(zhí)行目標(biāo)程序。如果程序發(fā)生崩潰則將測(cè)試用例收集到觸發(fā)crash 的文件集合中,否則根據(jù)記錄的分支覆蓋信息判斷該測(cè)試用例是否探索到新的路徑分支,執(zhí)行到新路徑的測(cè)試用例將被加入種子隊(duì)列等待變異。其策略基于代碼覆蓋率反饋擴(kuò)充種子隊(duì)列,隨著覆蓋率的提升種子隊(duì)列越來(lái)越長(zhǎng)。如果對(duì)每一個(gè)種子都進(jìn)行充分的變異,將會(huì)耗費(fèi)大量的時(shí)間并且效率很低。因此AFL 在種子隊(duì)列中動(dòng)態(tài)維護(hù)了一個(gè)能覆蓋當(dāng)前探索路徑的最小集合,選擇執(zhí)行快且體積小的種子并標(biāo)記為favored。這個(gè)集合大大縮小了AFL 需要重點(diǎn)變異的種子范圍,同時(shí)標(biāo)記了種子的優(yōu)先級(jí),保證AFL 優(yōu)先選擇執(zhí)行更快和規(guī)模更小的種子進(jìn)行變異。
這種策略使AFL 可以在有限時(shí)間內(nèi)執(zhí)行更多的輸入文件,但實(shí)驗(yàn)表明AFL 的測(cè)試通過率不足30%。AFL 只是考慮了種子的一些局部特征,但種子的質(zhì)量與許多特征有關(guān),如關(guān)鍵字段校驗(yàn)值、種子的信息熵以及種子的特定長(zhǎng)度等。目前的策略對(duì)種子的結(jié)構(gòu)特征考慮不足,如何有效地利用這些特征判定種子的質(zhì)量是一個(gè)關(guān)鍵問題。
為了聚合種子中各維度的結(jié)構(gòu)特征并對(duì)種子質(zhì)量進(jìn)行一個(gè)綜合判定,本文提出了一種基于深度學(xué)習(xí)的模糊測(cè)試策略。該方法通過學(xué)習(xí)模糊測(cè)試前期的輸入文件和執(zhí)行效果來(lái)預(yù)測(cè)種子的優(yōu)劣,使具有更多有利于提升覆蓋率特征的種子有更大的概率被選中變異。
本文的主要貢獻(xiàn)是提出了一種基于深度學(xué)習(xí)的輸入文件分類方法,學(xué)習(xí)輸入文件結(jié)構(gòu)中的高層特征,預(yù)測(cè)輸入文件的覆蓋率提升情況?;谶@種分類方法本文改進(jìn)了AFL 的模糊策略。在模糊測(cè)試中使用深度神經(jīng)網(wǎng)絡(luò)模型判斷種子價(jià)值,選擇高價(jià)值種子優(yōu)先進(jìn)行變異,結(jié)果表明,該方法提升覆蓋率和發(fā)現(xiàn)崩潰的能力均優(yōu)于AFL。
根據(jù)深度學(xué)習(xí)在模糊測(cè)試中解決的問題,目前的研究主要集中在:種子文件生成、測(cè)試用例生成、測(cè)試用例過濾、變異算子選擇和可利用性分析。其中在測(cè)試用例生成方面的研究較多,而在種子選擇中使用深度學(xué)習(xí)的研究較少。
Wang 等利用深度神經(jīng)網(wǎng)絡(luò)LSTM 從大量有漏洞和沒有漏洞的程序路徑中學(xué)習(xí)隱藏的易受攻擊特征,訓(xùn)練一個(gè)預(yù)測(cè)模型來(lái)分類路徑是否存在漏洞。然后對(duì)能夠覆蓋易受攻擊的程序路徑的測(cè)試用例進(jìn)行優(yōu)先執(zhí)行,并為這些測(cè)試用例分配更多的能量,產(chǎn)生更多的變異輸入。Chen 等使用監(jiān)督學(xué)習(xí)用于自適應(yīng)和種子調(diào)度,根據(jù)在相同或相似程序上做出的種子調(diào)度決策中學(xué)到的知識(shí),確定哪些新種子將產(chǎn)生更好的效果。Lyu 等收集觸發(fā)唯一崩潰或新路徑的輸入文件作為訓(xùn)練數(shù)據(jù),生成有效的文件作為種子。Godefroid 等基于神經(jīng)網(wǎng)絡(luò)使用樣本輸入訓(xùn)練適合模糊測(cè)試生成輸入的語(yǔ)法。Wang等利用從大量現(xiàn)有輸入中學(xué)習(xí)到的知識(shí)來(lái)生成新的輸入。B?ttinger 等使用強(qiáng)化學(xué)習(xí)產(chǎn)生高價(jià)值的新輸入Rajpal 等設(shè)計(jì)了基于AFL 的靜態(tài)模型,利用LSTM 模型來(lái)預(yù)測(cè)輸入中關(guān)鍵的字節(jié),并根據(jù)以前的模糊經(jīng)驗(yàn)變異這些字節(jié)以最大化邊緣覆蓋。文獻(xiàn)[9]通過訓(xùn)練過的神經(jīng)網(wǎng)絡(luò)預(yù)測(cè)測(cè)試用例是否會(huì)觸發(fā)新狀態(tài)的轉(zhuǎn)換,如果不能觸發(fā)狀態(tài)轉(zhuǎn)換則會(huì)丟棄該測(cè)試用例,只執(zhí)行能觸發(fā)狀態(tài)轉(zhuǎn)換的測(cè)試用例;文獻(xiàn)[10]訓(xùn)練神經(jīng)網(wǎng)絡(luò)預(yù)測(cè)輸入在執(zhí)行路徑分布上的熵,優(yōu)先執(zhí)行模型不能確定其執(zhí)行路徑的輸入。Zong 等基于定向模糊測(cè)試框架AFLGo 設(shè)計(jì),通過不斷更新模型并且使用更新后的模型對(duì)被過濾的測(cè)試用例進(jìn)行再過濾,保證了模型的精確度和低假陰性率。在非定向模糊測(cè)試中,使用深度學(xué)習(xí)進(jìn)行測(cè)試用例過濾的時(shí)間開銷和訓(xùn)練模型在長(zhǎng)期模糊測(cè)試中的表現(xiàn)并不匹配。
基于深度學(xué)習(xí)的模糊測(cè)試框架的結(jié)構(gòu)如圖1所示,包括訓(xùn)練數(shù)據(jù)準(zhǔn)備、模型訓(xùn)練和模型預(yù)測(cè)。在訓(xùn)練數(shù)據(jù)準(zhǔn)備階段,通過模糊測(cè)試目標(biāo)程序收集大量的測(cè)試用例。同時(shí)獲取每個(gè)測(cè)試用例的覆蓋率狀態(tài),并對(duì)比初始覆蓋位圖記錄該測(cè)試用例的覆蓋率提升情況。預(yù)處理以上數(shù)據(jù)生成向量化的訓(xùn)練數(shù)據(jù),然后訓(xùn)練一個(gè)深度神經(jīng)網(wǎng)絡(luò)模型。在模型預(yù)測(cè)部分利用模型預(yù)測(cè)種子隊(duì)列中的種子文件,選擇預(yù)測(cè)效果好的種子優(yōu)先進(jìn)行變異測(cè)試。
圖1 基于深度學(xué)習(xí)的模糊測(cè)試框架的結(jié)構(gòu)
由于不同的目標(biāo)程序接受的輸入文件類型各不相同,本文對(duì)輸入文件進(jìn)行統(tǒng)一編碼,可以直接想到的方案是按字節(jié)編碼,即向量元素為范圍[0,255]之間的數(shù)據(jù),長(zhǎng)度為輸入文件的字節(jié)長(zhǎng)度。在fuzzguard 中就采用了這種方案,將每個(gè)字節(jié)的值看作一個(gè)量值,這樣就忽略了目標(biāo)程序?qū)⑤斎胛募挠行┍忍匚蛔鳛闋顟B(tài)值處理的情況。因此本文對(duì)輸入文件的二進(jìn)制表示進(jìn)行處理,即將文件的每個(gè)比特位映射到輸入向量的每個(gè)元素上,這樣對(duì)不同程序的多種格式輸入可以使用統(tǒng)一的方法進(jìn)行處理。輸入文件被編碼為序列=<,,…,>,其中是輸入的字節(jié)長(zhǎng)度,x= bit,x∈{0,1}。每個(gè)輸入的標(biāo)簽使用一個(gè)二維向量表示,提升覆蓋率的輸入標(biāo)簽為<0,1 >,未提升覆蓋率的輸入標(biāo)簽為<1,0 >,即=<,>,y∈{0,1} 。
AFL 將程序發(fā)生跳轉(zhuǎn)時(shí)的基本塊二元組進(jìn)行計(jì)算,作為一條邊的索引值。有兩種情況的測(cè)試用例會(huì)被保留到種子隊(duì)列中,一種是發(fā)現(xiàn)未探索到的邊,另一種是已探索到的邊執(zhí)行次數(shù)量級(jí)增加。種子隊(duì)列只保存首次觸發(fā)以上兩種情況的輸入,這些輸入數(shù)目很少,通常與程序的復(fù)雜程度(邊數(shù)量)成正比。在模糊測(cè)試到一定階段后,程序很難發(fā)現(xiàn)新的邊,種子隊(duì)列數(shù)目也會(huì)停止增長(zhǎng)。這會(huì)造成訓(xùn)練數(shù)據(jù)不平衡的問題,影響到最終模型的預(yù)測(cè)效果。為了解決這個(gè)問題,將所有與已收集種子覆蓋邊相同的輸入標(biāo)簽設(shè)為<0,1 >,即使用所有提升了初始覆蓋率的輸入作為正樣本數(shù)據(jù)。
由于變異的隨機(jī)性,AFL 會(huì)產(chǎn)生一部分重復(fù)的輸入文件(約10%~20%),輸入模型將會(huì)影響訓(xùn)練的效果,因此本文對(duì)收集到的原始數(shù)據(jù)進(jìn)行了去重操作。
設(shè)計(jì)了數(shù)據(jù)和標(biāo)簽的表示后,需要選擇一個(gè)深度學(xué)習(xí)網(wǎng)絡(luò)。通常情況下測(cè)試用例是大小不定的文件,這意味著輸入網(wǎng)絡(luò)的向量是一個(gè)長(zhǎng)度不確定的序列,并且目標(biāo)程序可能會(huì)依次處理這些數(shù)據(jù)。循環(huán)神經(jīng)網(wǎng)絡(luò)(Recurrent Neural Network,RNN)可以處理變長(zhǎng)序列數(shù)據(jù),目前已經(jīng)成功應(yīng)用在自然語(yǔ)言處理領(lǐng)域。輸入的二進(jìn)制格式也可以近似成一種語(yǔ)言來(lái)用RNN處理,但RNN 在處理較長(zhǎng)序列時(shí)會(huì)出現(xiàn)梯度消失和梯度爆炸問題。長(zhǎng)短期記憶(long short-term memory,LSTM)是一種特殊的RNN,較RNN 更高效穩(wěn)定,能夠在長(zhǎng)序列中有更好的表現(xiàn)。LSTM結(jié)構(gòu)的主要輸入輸出如圖2所示。
圖2 LSTM結(jié)構(gòu)的主要輸入輸出
在LSTM 內(nèi)部結(jié)構(gòu)中,由當(dāng)前輸入x和上一個(gè)狀態(tài)傳遞的h獲得一個(gè)拼接向量,通過訓(xùn)練得到四個(gè)狀態(tài)、z、z、z,拼接向量乘以權(quán)重矩陣后,由Sigmoid 激活函數(shù)得到0 到1 之間的數(shù)值,作為門控狀態(tài)z、z、z,由tanh激活函數(shù)得到-1到1之間的數(shù)值,作為輸入。
在實(shí)際的訓(xùn)練中,細(xì)胞節(jié)點(diǎn)有很多個(gè),需要訓(xùn)練的參數(shù)隨著神經(jīng)網(wǎng)絡(luò)層次的不斷加深也越來(lái)越多??紤]到復(fù)雜的神經(jīng)網(wǎng)絡(luò)訓(xùn)練時(shí)間成本過高的問題,本文采用一層LSTM 網(wǎng)絡(luò)結(jié)構(gòu),將輸入序列切分為128位的數(shù)據(jù)塊輸入網(wǎng)絡(luò)。
深度學(xué)習(xí)與傳統(tǒng)機(jī)器學(xué)習(xí)方法的不同在于它能夠自動(dòng)學(xué)習(xí)特征,深度神經(jīng)網(wǎng)絡(luò)的訓(xùn)練就是在進(jìn)行特征學(xué)習(xí)和尋找最優(yōu)參數(shù)。在訓(xùn)練過程中模型不斷地更新參數(shù),使損失函數(shù)趨于收斂。本文訓(xùn)練的模型執(zhí)行的是一個(gè)二分類任務(wù),因此選擇損失函數(shù)為二分類交叉熵,其定義為:
其中,?是模型預(yù)測(cè)樣本是正例的概率,是樣本標(biāo)簽,如果樣本屬于正例,取值為1,否則取值為0。 為了使模型更好地收斂,本文使用Adam優(yōu)化算法。
輸入序列經(jīng)過LSTM 層和線性層后輸出兩個(gè)節(jié)點(diǎn),通過激活函數(shù)得到該輸入屬于標(biāo)簽中某一類的概率。在多次訓(xùn)練之后得到能夠準(zhǔn)確預(yù)測(cè)輸入類別的模型,使用該模型來(lái)指導(dǎo)種子選擇。
具體算法流程如算法1 所示,本文在AFL的模糊測(cè)試策略上做出了改進(jìn)。AFL 從維護(hù)的種子隊(duì)列中選擇種子大小和執(zhí)行時(shí)間乘積最小的種子優(yōu)先測(cè)試,種子隊(duì)列中其余種子有很小的概率被隨機(jī)選中變異測(cè)試。這是出于提升模糊測(cè)試速度的考慮,但種子提升覆蓋率的效果與種子大小和執(zhí)行時(shí)間并沒有直接的關(guān)系。本文提出的模糊測(cè)試策略本質(zhì)上是基于種子的結(jié)構(gòu)特征決定種子的優(yōu)先級(jí),種子的關(guān)鍵結(jié)構(gòu)特征能直接影響是否通過重要分支執(zhí)行到更深的路徑。
本文基于AFL2.57b 實(shí)現(xiàn),加入數(shù)據(jù)集獲取模塊和種子選擇模塊實(shí)現(xiàn)了本文提出的方法,選取了真實(shí)的目標(biāo)程序和LAVA-M 測(cè)試集中的程序進(jìn)行實(shí)驗(yàn)評(píng)估。
在深度神經(jīng)網(wǎng)絡(luò)層的構(gòu)建中,本文選擇了PyTorch,它是2017年Facebook 人工智能研究院(FAIR)團(tuán)隊(duì)在GitHub 上開源的深度學(xué)習(xí)框架。PyTorch 具有簡(jiǎn)潔高效的優(yōu)點(diǎn),同時(shí)PyTorch 具有的易用性和社區(qū)活躍度使它在各類場(chǎng)景中都有豐富的應(yīng)用。
模糊測(cè)試實(shí)驗(yàn)在64 位ubuntu16.04 系統(tǒng)中完成,內(nèi)存為8 G。模型訓(xùn)練在Nvidia 2080Ti GPU上進(jìn)行,內(nèi)存為12 G,超參數(shù)設(shè)置如表1所示。
表1 超參數(shù)設(shè)置
實(shí)驗(yàn)首先選取地目標(biāo)程序bmp2tiff、tiff2 pdf、gif2png、readelf 分別進(jìn)行數(shù)據(jù)集收集、預(yù)處理和訓(xùn)練得到模型,對(duì)應(yīng)的損失曲線和模型在測(cè)試集上的準(zhǔn)確度如圖3所示。
圖3 深度學(xué)習(xí)模型的損失曲線和準(zhǔn)確度(續(xù))
圖3 深度學(xué)習(xí)模型的損失曲線和準(zhǔn)確度
模型準(zhǔn)確度和損失在訓(xùn)練20 輪后趨于穩(wěn)定, 并且預(yù)測(cè)準(zhǔn)確度在95%以上。訓(xùn)練模型得到最終穩(wěn)定的準(zhǔn)確率如表2。對(duì)比文獻(xiàn)[9]中的實(shí)驗(yàn)結(jié)果,本文在預(yù)測(cè)準(zhǔn)確率上有一定的提高,這對(duì)模型的應(yīng)用效果有至關(guān)重要的影響。
表2 模型得到最終穩(wěn)定的準(zhǔn)確率
為了評(píng)估本方法的有效性,在選取的目標(biāo)程序gif2png、base64、who、size 中進(jìn)行了12 個(gè)小時(shí)的模糊測(cè)試,記錄了代碼覆蓋率和發(fā)現(xiàn)crash 數(shù)量,代碼覆蓋率即AFL 中測(cè)量的邊覆蓋率。在相同的實(shí)驗(yàn)環(huán)境和時(shí)長(zhǎng)下對(duì)AFL 進(jìn)行了測(cè)試,實(shí)驗(yàn)結(jié)果見表3。
表3 代碼覆蓋率和發(fā)現(xiàn)crash數(shù)量
在這4 個(gè)目標(biāo)程序中,gif2png、tiff2ps、mupdf 和size 的測(cè)試覆蓋率均有提升, gif2png、base64、who 和size 發(fā)現(xiàn)的crash 數(shù)量有提升,gif2png 的覆蓋率和發(fā)現(xiàn)crash 數(shù)目提升最為明顯。
以上分析表明,使用輸入的二進(jìn)制結(jié)構(gòu)和覆蓋率變化狀態(tài)進(jìn)行訓(xùn)練的模型指導(dǎo)種子選擇能夠較好地提高模糊測(cè)試的效果,增加探索到的新路徑,并為發(fā)現(xiàn)更多的crash提供可能性。
本文簡(jiǎn)述了基于深度學(xué)習(xí)進(jìn)行模糊測(cè)試的基本原理和構(gòu)架,以真實(shí)的目標(biāo)程序作為實(shí)驗(yàn)對(duì)象,進(jìn)行了訓(xùn)練數(shù)據(jù)收集、模型訓(xùn)練、模型預(yù)測(cè)、策略改進(jìn)和實(shí)驗(yàn)評(píng)估,結(jié)果分析驗(yàn)證了模型的可行性和實(shí)用性。未來(lái)將會(huì)進(jìn)一步研究深度學(xué)習(xí)理論, 提高模型對(duì)種子效果的預(yù)測(cè)能力,從而進(jìn)一步提高代碼覆蓋率與發(fā)現(xiàn)漏洞的可能性。