前言
在之前關(guān)于AFL的程序執(zhí)行路徑在AFL第三節(jié)講過,首先是afl-gcc對每個基本塊隨機(jī)賦予一個隨機(jī)值,然后在執(zhí)行的時候,通過fork()后的“子進(jìn)程”去執(zhí)行插樁的部分代碼,把隨機(jī)值亦或后的字節(jié)加一,通過共享的bitmap存儲區(qū)域就可以知道執(zhí)行當(dāng)前種子的bitmap(執(zhí)行路徑)是多少了。但是存在幾點問題:1、bitmap利用率,bitmap大小為65536個字節(jié),有些程序的邊可能會超過(概率很?。?,但是也存在很多利用率不足的問題。2、可能存在碰撞,因為隨機(jī)分配的值就有可能相同,其次異或操作之后可能會相同,那么兩條不同的邊對應(yīng)的值卻相等了。
有一個解決方法就是使用Intel Processor Tracing,Intel研發(fā)的一個程序跟蹤功能,這個部件可以直接對二進(jìn)制程序進(jìn)行跟蹤。由于程序執(zhí)行的時候,它本身的代碼在CPU中的地址是固定的,PT可以返回CPU中的數(shù)據(jù)流操作,通過篩選程序的地址的包信息,就可以獲取程序的操作流從而獲得程序執(zhí)行路徑。舉個例子,hello world這個程序運行的時候,基本塊在CPU中的id是45-90,那么運行這個程序的時候使用PT就可以捕獲CPU中的執(zhí)行數(shù)據(jù),可能有很多包(包括鼠標(biāo)、顯示器、其他程序、終端等等),篩選id在45-90的PT包,這些數(shù)據(jù)包就是運行“hello world”產(chǎn)生的包信息,然后對包信息中的基本塊id就可以描繪出程序執(zhí)行的邊路徑了。因為一個程序載入內(nèi)存運行后地址是固定的,準(zhǔn)確無碰撞,且不依靠源碼的插樁,還比AFL自帶的QEMU模式快不少,成為一個不錯的方法。
我在這就介紹以下在fuzz中使用的一個PTFuzzer、NEUFuzz和Honggfuzz。
PTFuzz
這個工具是在AFL的基礎(chǔ)上做出了改進(jìn),把AFL的基礎(chǔ)上去除了插樁的依賴,把run_target里面的fork子進(jìn)程跑插樁代碼部分改成fork一個子進(jìn)程利用PT收集包信息、篩選包信息,根據(jù)包信息獲取當(dāng)前種子的執(zhí)行路徑。
簡單說一下他的創(chuàng)新點:
利用PT包信息
通過PT部件可以獲得兩個種類的包信息:基本執(zhí)行信息(時間戳計時器、包流邊界等)和控制流信息(時間、程序執(zhí)行流等)。PT提供了三類調(diào)用包:直接調(diào)用、間接調(diào)用和遠(yuǎn)轉(zhuǎn)換調(diào)用。當(dāng)捕獲了這樣的Change of Flow Instructions(COFI)包時,就可以獲取基本塊的跳轉(zhuǎn)信息,即邊信息。
不同于統(tǒng)一大小的bitmap
AFL中的bitmap時固定大?。?5536),而PTfuzz會在初始化載入二進(jìn)制程序的時候,就構(gòu)建了COFI map。利用python的CLE和capstone庫把程序中text部分的調(diào)用地址記錄下來并且存放在MSR寄存器,那么MSR寄存器就可以用來篩選PT的包信息。(MSR寄存器是PT指定可以實現(xiàn)篩選功能的寄存器)。
在實驗部分,分為對有源碼的代碼進(jìn)行測試比較和對二進(jìn)制程序進(jìn)行測試比較。
在有源碼可插樁的代碼比較中,PTfuzz比AFL稍慢(有python編寫的decoder的腳本收集PT包信息并處理得到運行路徑),但是可以測試出更多漏洞,并且在單位時間發(fā)現(xiàn)更多的邊。
在無源碼的二進(jìn)制程序比較中,PTfuzz優(yōu)于QEMU模式的AFL,QEMU需要使用虛擬化技術(shù),性能比AFL源碼插樁速度慢2到5倍,因此發(fā)現(xiàn)的邊信息也就比PTFuzz少了。
最后說一下PTFuzz文章中說的不足,需要使用包含PT功能的Intel芯片,內(nèi)核版本有限制,必須在linux使用,這些局限導(dǎo)致了PTFuzz不能廣泛使用。
NeuFuzz
這個fuzzer看名字是深度網(wǎng)絡(luò)訓(xùn)練,由兩部分組成,offline的深度學(xué)習(xí)模塊和正常的PTFuzz部分,在PTFuzz的種子選取部分,通過加入預(yù)測模型對種子進(jìn)行排序,預(yù)測模型認(rèn)為是1(vulnerable seed)的種子會優(yōu)先執(zhí)行,更快地發(fā)現(xiàn)crash。

訓(xùn)練模型
在模型訓(xùn)練方面,他選了NIST SARD項目(人工合成注入的漏洞)、Gtihub項目和Exploit-DB的項目。認(rèn)為存在漏洞或者有注入漏洞的為vulnerable 程序,打過補(bǔ)丁或者沒有注入漏洞的程序為non-vulnerable程序。一共收集了28475個vulnerable和27436個non-vulnerable。
然后通過使用POC(能觸發(fā)漏洞的輸入)跑上面這些程序,如果觸發(fā)漏洞,程序執(zhí)行路徑稱為vulnerable path,反之,為non-vulnerable path。同時用PT來獲取執(zhí)行路徑。
再把獲取到的執(zhí)行路徑轉(zhuǎn)換成向量形式。NEUFuzz選擇了Word2vec(這個機(jī)器學(xué)習(xí)對向量長度有一定限制,輸入一大就不行了)。每條指令的地址(如0x223344)就轉(zhuǎn)換成向量,路徑中指令數(shù)的上限為n,不足n的用0向量補(bǔ)齊。在Word2vec轉(zhuǎn)換后,使用LSTM(長短期記憶網(wǎng)絡(luò))這個深度學(xué)習(xí)網(wǎng)絡(luò)進(jìn)行學(xué)習(xí)。在后面的結(jié)果顯示他的模型準(zhǔn)確率高達(dá)92%。
online fuzz
之前提到過PT利用TNT(jnz,je這樣的直接調(diào)用)、TIP(call,jmp這樣的間接調(diào)用)和FUP(exception、interrupt這樣的遠(yuǎn)程調(diào)用)獲取hit的基本塊并記錄邊信息。NEUFuzz則繼續(xù)利用PT,在對種子重跑獲取執(zhí)行路徑后使用預(yù)測模型判斷種子是否是vulnerable。
結(jié)果
NEUFuzz使用和PTFuzz一樣的實驗程序——LAVA-M以及一些實際存在程序(libtiff、binutils等)。效果非常好,可能是因為有深度網(wǎng)絡(luò)的輔助,在PTFuzz基礎(chǔ)上更快找到crash。很明顯,因為PTFuzz是coverage-oriented,這是改善了覆蓋信息,NEUFuzz在此基礎(chǔ)上還做了crash-oriented。
個人覺得他這樣的實驗不是很好,雖然深度學(xué)習(xí)網(wǎng)絡(luò)的應(yīng)用增加了效率,但是他只跟PTFuzz比較,在a的基礎(chǔ)上加了優(yōu)點變成b,只跟a比卻不跟基礎(chǔ)AFL、AFL的變種進(jìn)行比較或者跟其他二進(jìn)制程序fuzz的fuzzer比較是有失公允的。
Honggfuzz
面向安全的Honggfuzz模糊測試器是多線程的,而且經(jīng)過了優(yōu)化,可以利用各種系統(tǒng)資源。很多模糊測試工具必須運行多個實例才能達(dá)到這種效果,但Honggfuzz自動使用所有可用CPU核心加速模糊測試過程。
Honggfuzz不僅僅適用于Windows,也可以測試在Linux、Mac,甚至Android環(huán)境中運行的應(yīng)用程序。由于其多平臺適用的特性,Honggfuzz有一系列例子和測試用例可供開發(fā)人員使用,或一字不改直接套用,或根據(jù)自身需求加以修改,或者僅做簡單參考以便設(shè)計自己的模糊測試規(guī)則。
可能是由于能在多平臺執(zhí)行模糊測試的能力,Honggfuzz用來展示開發(fā)人員捕獲漏洞的戰(zhàn)果頁面相當(dāng)龐大。開發(fā)者介紹,找出引發(fā)全球安全補(bǔ)丁的OpenSSL關(guān)鍵漏洞的模糊測試工具僅此一款。
關(guān)于honggfuzz的文章大家可以去看這篇https://bbs.pediy.com/thread-247954.htm
,講的非常到位。