Vuzzer自動漏洞挖掘工具簡單分析附使用介紹

Vuzzer 是由計算機科學機構  Vrije Universiteit Amsterdam、Amsterdam Department of Informatics 以及 International Institute of Information Technology, Hyderabad 共同開發的工具。css

項目來源 : https://github.com/vusec/vuzzerhtml

參考資料 :《VUzzer: Application-aware Evolutionary Fuzzing》python

VUzzer 是什麼?

爲什麼選擇 VUzzer

自動漏洞測試技術當前主要爲基於fuzzing的有結果反饋能力的AFL與使用符號執行的driller等。c++

​ 符號執行(symbolic execution)的一大優點在於發現儘量多的路徑,實現高覆蓋率,但其消耗大量運行空間的方式使其難以擴展,而vuzzer能在不使用符號執行的狀況下,對AFL效率進行大幅的提高。git

VUzzer使用應用感知的」智能「變異策略——基於數據流和控制流,使用輕量靜態分析與動態分析,經過結果反饋和優化輸入的生成過程以求產生更優秀更少的測試輸入,達到加快挖掘效率,增長挖掘深度的目的。github

案例

用如下簡單的狀況進行對比算法

...
read(fd,buf,size);
if(buf[5] == 0xD8 && buf[4] == 0xFF){ //在彙編代碼中以CMP形式出現,同時應注意其檢查順序 if(...) //if的嵌套 ...some useful code containg bug... }else{ ... EXIT_ERROR("Invalid file\n"); } 

 

輸入buf中的buf[4],buf[5]包含着被污染的數據(tained data)。編程

對於工具AFL—-對程序進行黑盒測試的fuzzer:ubuntu

1.必須經過變異輸入徹底猜對兩字節爲FFD8才能進入深層代碼 windows

2.必須找對該在buf[4],buf[5]的位置進行變異 

3.做爲一基於覆蓋率的fuzzer,AFL追求發現新路徑,當AFL沒能經過if而進入了else,對其來講仍然發現了新路徑,將會以這個進入else的輸入做爲新的反饋。可能導致AFL過度輕視if分支,這種狀況在嵌套判斷語句中會更加明顯。

這將會使fuzzer浪費大量時間與運算資源,在else和其下的錯誤處理中。

而對於VUzzer:

1.在靜態分析階段,vuzzer會經過在程序的彙編碼中尋找cmp指令集相關命令,將if語句中的判斷值提取出來存儲在Lcmp當中,找到這些magic bytes值是什麼(如 FFD8) 

2.而在動態分析中,經過不斷迭代,將Lcmp 與取地址值類操做Llea中信息與種子文件輸入和新生成輸入進行類型匹配等,找到這些magic bytes在輸入中的可能位置,更精準的進行變異 

3.而對於嵌套判斷語句引發的深度代碼不易發現的問題,VUzzer的基本塊(Basic Block)權重管理將會很好的解決這個問題

VUzzer 分析

 

對於應用反彙編後,彙編碼中的每個基本塊(Basic Block),都有一個權重值,因爲VUzzer追求更深層的代碼,因此對可能執行到機率越小的塊,他的權重值要更高,若從main到達塊A的機率爲P,其權重就爲1/p。

 

但如何作到這一點?

 

以上圖爲例若是說有main開始,那麼執行到main的機率就是1,main後有兩個可能方向,那麼就劃分二者機率均爲0.5,依次向下。

 

例如$H{機率}=E*0.5+P{外來}(0.5)*0.5=0.5$

 

則$H{權重}=1/H{機率}=2$

 

例圖中藍線所表示爲F塊觸發機率爲0.25,權重爲倒數4

 

特別的,對於很小可能含有bug的錯誤處理塊其權重爲1(經過動態分析才能發現錯誤處理塊)

 

由此有了,解決深層代碼被隱藏的方法。

 

VUzzer 概述

 

VUzzer 概述

 

vuzzer頂層圖(具體術語參見下表)

 

vuzzer頂層圖

靜態分析階段

1).在彙編碼中進行,找出基本塊,計算塊權重並將塊重量存入LBB

2).掃描編碼中的cmp指令相關的當即數,存入Limm(包含如上文中的0xFF,0xD8等)

動態分析階段—–每一loop爲一代

1).對種子文件(使用者提供的基礎輸入)進行DTA分析,捕獲輸入中的共同特徵,以期找到magic bytes的位置與錯誤處理塊,使新產生的孩子測試輸入,不會陷於外圍的判斷和出錯處理

2).對於發現了新的基本塊的輸入用例,進行DTA分析,追蹤輸入的值在程序中的運行,監測數據流特徵,以推斷輸入的結構

3).適應度計算

適應度是對每個輸入而言的,適應度越高,表明其可進入更多的塊,更深的塊(權重更大的塊),是更有價值的輸入。

動態分析階段-----每一loop爲一代

再結合此圖,對於每個輸入,運行中必會經過一條路徑,輸入A的適應度就是改路徑所通過塊的權重和

例如路徑1(紅色)2(藍色):

 

$p1=A-B-D-E-H-J=1+1+2+2+2-1=7$

$p2=A-B-D-E-F-J=1+1+2+2+4-1=9$

 

$適應度{P2}>適應度{P1}$

輸入2將更被看重,更多的參與到生成下一代去,具體作法是將輸入按適應度呈順序排列存入Lfit,再選取使用時,使用前n%的作法

4).生成下一代

其變異來源是被稱爲vuzzer下的ROOT set的輸入集合,其中包含種子文件,tainted input, Lfit中的前n%。

生成下一代

典型的子測試用例演化算法

vuzzer採用典型演化算法步驟並優化

INITIALIZE population with seed inputs repeat SELECT1 parents RECOMBINE parents to generate children MUTATE parents/children EVALUATE new candidates with FITNESS function SELECT2 fittest candidates for the next population until TERMINATION CONDITION is met //迭代次數超過限制 或 觸發crash return BEST Solution

| 變異策略 | 具體步驟 || —– | —————- || 交叉 | 取一個偏移量,然後使兩半互換 || 刪去 | 刪除字節 || 替換與插入 | 在特定的位置改變或插入特定的字節 |

特定的字節 ,是經過從程序的彙編碼中cmp指令集族的代碼中取出當即數置入Limm,並從Limm中取出。生成爲不一樣長度的新字節串獲得的

特定的位置 ,是經過從父測試用例集中,尋找其偏移量,並在此之上變異引發的

產生孩子測試用例後由此再進行一輪,在達到迭代上限或發現bug前,循環往復

 

vuzzer安裝

 

​ 這裏結合官方安裝說明 進行講解:

需求條件:

環境:

32位Linux系統,因vuzzer做者聲明僅在Ubuntu14.04版本中完成測試,因此建議使用該版本系統。

 vuzzer_github 在本地目錄準備源碼

​ $ git clone https://github.com/vusec/vuzzer

 C++11 編程以及 Unix 開發利用 (例如: GNU Make).

gcc4.8開始默認支持c++11

Ubuntu14.04當前自帶版本爲4.8.*的gcc,g++,支持c++11。

經過如下命令能夠檢查當前版本

 

$ gcc --version

$ g++ --version

 

若不合適可經過過如下命令安裝該版本

 

$ sudo apt-get install gcc-4.8

$ sudo apt-get install g++-4.8

 

準備Intel Pin:Intel Pin 的較新版本 (>=2.13) 。必須在 VUzzer 頂級目錄中的 pin 目錄中保存框架。

PIN的下載能夠經過如下兩個方法:

(1).(推薦)使用vuzzer自帶pin配置腳本,自動下載合適版本pin並配置,在vuzzer根目錄輸入如下命令,使用此方法pin會被下載至vuzzer/support/

make -C support -f makefile.pin

PIN的下載

(2) . 在官方網站 Pin – A Binary Instrumentation Tool 下載合適版本pin工具(查看release note尋找對應版本) 

後在vuzzer目錄下創建一個到pin的連接:

$ cd vuzzer

$ ln -s /path-to-pin-home pin 其中/path-to-pin-home是Pin的根目錄,不是可執行文件

在vuzzer目錄下創建一個到pin的連接

利用 Python 2.7 ,使用 Turtle 語法將源代碼轉換成 PROV 形式:

Ubuntu14.04 帶有 python2.7

經過如下命令檢查

$  python --version

若是未安裝執行如下命令安裝

$ sudo apt-get install python-2.7

安裝EWAGBoolArray:只需將 headers 文件 複製粘貼到 /usr/include 文件夾中便可安裝:

完成該步驟僅需將指定頭文件下載放置到/usr/include目錄下

具體爲下載headers file所指向連接下4個.h格式文件。

後經過如下命令拷貝頭文件,其中headers爲包含4個頭文件的文件夾

$  sudo cp   headers/*   /usr/include/

安裝 BitMagic

輸入如下命令安裝 BitMagic

$  sudo apt-get install bmagic

要求修改過的libdft,在當前vuzzer目錄的support下已有該版本,已準備好編譯,無需操做

BitVector module for python.點擊bitvector下載

官方網站:https://engineering.purdue.edu/kak/dist/BitVector-2.2.html

安裝經過如下命令:在解壓後的BitVector目錄下

$  sudo python setup.py install

安裝準備

環境準備結束

安裝

First do cd vuzzer and then

export PIN_ROOT=$(pwd)/pin

設置PIN_ROOT,因爲當前目錄(pwd)下的pin根目錄連接,該命令將使PIN_ROOT指向可執行文件pin

編譯libdft,在vuzzer/support/libdft/src目錄下

make clean清空make文件,再回到vuzzer目錄下執行

make support-libdft編譯libdft

make編譯vuzzer

make -f mymakefile

安裝

(截圖未作make clean,且已安裝過,僅供參考)

安裝完成

 

vuzzer基礎參數說明

 

位於根目錄下的

 

runfuzzer.py是啓動vuzzer的入口

 

config.py是包含vuzzer代數上限等設置的配置文件

$ python runfuzzer.py -h
usage: runfuzzer.py [-h] -s SUT -i INPUTD -w WEIGHT -n NAME [-l LIBNUM] -o OFFSETS [-b LIBNAME] 

 

這裏假定以tiff2pdf(圖片格式轉換工具)爲測試對象,同時監測其運行庫libtiff.so

 

-s (SUT commandline): 被測程序命令行

 

e.g. -s "./bin/tiff2pdf -d %s -o result.pdf"

 

​ 是要進行vuzzer的對象,具體爲將普通執行程序語句中傳入參數文件語句替換爲%s,使vuzzer以此處輸入爲基礎進行漏洞挖掘。若是有其餘參數與設置將保留在其原位置,

 

-i (seed input directory (relative path)): 種子文件目錄

 

e.g. -i "datatemp/tiff_seeds/" (該目錄下存有4個.tiff文件)

 

​ 種子文件是自動化漏洞挖掘的起始輸入,vuzzer將在此之上進行輸入變異。這裏指向種子文件所在文件夾,建議對每個被測程序,在vuzzer/datatemp/目錄下新建文件夾存放其種子,種子文件至少4個(實際上有的官方示例種子文件卻只有3個),大小被明確要求小於20kb。

-w (path of the pickle file(s) for BB wieghts (separated by comma in case there are two)

 

-n (Path of the pickle file(s) containing strings from CMP inst (separated by comma if there are two))

 

e.g.

-w "idafiles/tiff/tiff2pdf.pkl,idafiles/tiff/libtiff.so.pkl" -n "idafiles/tiff/tiff2pdf.names,idafiles/tiff/libtiff.so.names" 

 

這兩類文件分別爲 基本塊描述文件 和 被測程序彙編碼中用到cmp指令集的語句的有關信息。目前,這兩類文件須要經過裝有python擴展的IDA生成,將二進制可執行文件經過IDA打開,運行(Alt+F7)位於vuzzer目錄下的BB-weightv4.py,將在二進制文件目錄下生成.pkl,.names的文件。

 

若是要同時vuzzer一個該應用的庫文件,那麼也應對它的庫(如libtiff.so)作一樣的操做,並在使用參數時添上,再以「,」隔開。如上示例

 

vuzzer基礎參數說明

須要注意的是,若在windows下使用IDA生成.pkl,.names文件,要在vuzzer上使用時,須要對這兩個文件進行部分編碼的轉換,具體操做爲:

$ dos2unix tiff2pdf.pkl
$ dos2unix tiff2pdf.names

-l (Number of binaries to monitor) 須要監測的二進制文件數量

​ e.g.

-l 2 

默認爲1,當僅需對程序進行vuzzer時忽略此項,若同時要對庫文件進行vuzzer則該數=庫數量+1

如本例爲2

-o(base-address of application and library (if used))程序或庫的起始地址

e.g.

-o "0x00000000,0x00000000" 

默認」0×00000000″當僅檢測程序時可忽略此項,若同時檢測一個庫則如上設置,一次運行後會提示庫地址偏移已顯示。在根目錄下尋找到imageoffset.txt,取出其中的庫地址偏移並修改-o值,以下,從新執行該命令,則會正常啓動。(沒錯這確實是很奇怪的操做,做者說在下一版本會改正)

-o "0x00000000,0xba45760" 

-b (library name to monitor)要監測的庫名

e.g.

-b "libtiff" 

參數使用要檢測的庫的名字,通常去掉拓展名(.so等)

示例程序測試

Project vuzzer 自己帶有幾個可供試驗的程序,在bin目錄下,其pickle文件在idafiles下,種子文件在datatemp下。

在vuzzer目錄下,運行樣例的命令爲

peter@ubuntu:~/Desktop/vuzzer$ export PIN_ROOT=$(pwd)/pin ******設置pin根目錄****** peter@ubuntu:~/Desktop/vuzzer$ echo 0 |sudo tee /proc/sys/kernel/randomize_va_space [sudo] password for peter: ******關閉緩衝區隨機化****** 0 peter@ubuntu:~/Desktop/vuzzer$ echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope 0 peter@ubuntu:~/Desktop/vuzzer$ python runfuzzer.py -s './bin/who %s' -i 'datatemp/utmp/' -w 'idafiles/who.pkl' -n idafiles/who.names ******啓動vuzzer******

 運行一段時間後

​ ROOT集可能會保存在data中

 靜態分析結果limm存放在cmp.out中

示例程序測試

若是觸發程序crash會在error.log記錄

觸發bug的輸入存留在outd/crashInput/中​ 

能夠用該輸入測試該程序

示例程序測試

status.log中存有每一代的記錄

示例程序測試

同時監測程序與程序調用的庫的vuzzer命令腳本

例如:對 tiff2pdf 及其引用庫libtiff.so

#!/bin/bash cd /home/peter/Desktop/vuzzer/ export PIN_ROOT=/home/peter/Desktop/vuzzer/pin export LD_LIBRARY_PATH=/usr/lib/ echo 0 | sudo tee /proc/sys/kernel/randomize_va_space echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope echo "done" python runfuzzer.py -s './bin/tiff2pdf %s -o result.pdf' \ -i 'datatemp/tiff2pdftemp/' \ -w './idafiles/tiff2pdf.pkl,./idafiles/libtiff.so.pkl' \ -n './idafiles/tiff2pdf.names,./idafiles/libtiff.so.names' \ -l 2 \ -o '0x00000000, 0xb67a5000' \ -b 'tiff'#!/bin/bash cd /home/peter/Desktop/vuzzer/ export PIN_ROOT=/home/peter/Desktop/vuzzer/pin export LD_LIBRARY_PATH=/usr/lib/ echo 0 | sudo tee /proc/sys/kernel/randomize_va_space echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope echo "done" python runfuzzer.py -s './bin/tiff2pdf %s -o result.pdf' \ -i 'datatemp/tiff2pdftemp/' \ -w './idafiles/tiff2pdf.pkl,./idafiles/libtiff.so.pkl' \ -n './idafiles/tiff2pdf.names,./idafiles/libtiff.so.names' \ -l 2 \ -o '0x00000000, 0xb67a5000' \ -b 'tiff'

感謝實習期間,在北京奇虎360公司,網絡安全研究院對個人細緻指導

附錄

安裝使用如遇到問題可在vuzzer_Issues討論

相關文章
相關標籤/搜索