摘 要:控制流圖(CFG)是二進制程序分析的基礎。傳統(tǒng)靜態(tài)分析方法構(gòu)建控制流圖速度快,代碼覆蓋率高,但不能解決間接跳轉(zhuǎn)問題;動態(tài)分析方法能夠分析間接跳轉(zhuǎn),但代碼覆蓋率低、性能開銷大。為更加高效構(gòu)建完備的控制流圖,提出靜態(tài)動態(tài)結(jié)合的混合分析方案。首先使用靜態(tài)分析獲取程序的初始控制流圖,采用模糊測試的方法獲取目標程序不同執(zhí)行流的輸入數(shù)據(jù),誘導重寫后的目標程序執(zhí)行獲取間接跳轉(zhuǎn)地址;融合靜態(tài)分析和動態(tài)分析結(jié)果,從而高效構(gòu)建完備的控制流圖。通過實驗驗證,該混合分析方案相比于現(xiàn)有的混合分析方案,能夠構(gòu)建更加完整的控制流圖,相比于基于動態(tài)二進制插樁的混合分析方案效率更高。
關鍵詞: 控制流圖; 二進制程序; 混合分析; 二進制重寫
中圖分類號: TP311 文獻標志碼: A 文章編號: 1001-3695(2025)02-032-0555-05
doi:10.19734/j.issn.1001-3695.2024.06.0281
Hybrid analysis based on binary rewriting to build control flow graph solution
Li Ziyou1, Huang Xiaofang1’, Yin Mingyong2
(1.School of Computer Science amp; Technology, Southwest University of Science amp; Technology, Mianyang Sichuan 621000, China; 2.Institute of Computer Application, Mianyang Sichuan 621000, China)
Abstract:CFG forms the foundation of binary program analysis.Traditional static analysis methods construct CFGs quickly with high code coverage but cannot resolve indirect jumps.Dynamic analysis methods,while capable of handling indirect jumps,suffer from low code coverage and high performance overhead.To efficiently construct a complete CFG,this paper proposed a hybrid analysis approach combining static and dynamic methods.This approach first used static analysis to generate the program’s initial CFG,then applied fuzz testing to obtain input data for different execution paths of the target program,inducing the modified program to execute and retrieve indirect jump addresses.By integrating the results of both static and dynamic analyses,the complete CFG was efficiently constructed.Experimental results confirm that this hybrid analysis approach constructs a more complete CFG compared to existing hybrid analysis methods,and is more efficient than hybrid analysis approaches based on dynamic binary instrumentation.
Key words:control flow graph(CFG); binary program; hybrid analysis; binary rewrite
在對軟件產(chǎn)品進行安全性分析時,許多軟件并未開源,目前大部分采用控制流圖(CFG)[1]對無源碼的軟件進行二進制代碼安全性分析。CFG用于描述程序在執(zhí)行過程中的控制流轉(zhuǎn)移關系,包括函數(shù)調(diào)用、條件分支和循環(huán)等,在代碼相似性檢測[2,3]、漏洞檢測[4~7]和惡意代碼變種[8,9]等多個領域都起著重要作用,也是二進制程序的基礎結(jié)構(gòu)。同時,許多二進制程序分析技術,如污點分析(taint analysis)[10,11]、符號執(zhí)行(symbolic execution)[12]等都要依賴程序的控制流圖。因此,構(gòu)建完整的控制流圖對軟件進行二進制代碼安全性分析具有重要意義。
1 相關工作
為構(gòu)建目標二進制程序的控制流圖,目前主要分為動態(tài)、靜態(tài)和混合分析。動態(tài)分析方法[13]使用輸入數(shù)據(jù)促使二進制程序執(zhí)行,通過監(jiān)控程序執(zhí)行過程,構(gòu)建每個輸入產(chǎn)生執(zhí)行流。程序動態(tài)執(zhí)行時能夠獲取執(zhí)行流某一時刻的上下文狀態(tài),從而構(gòu)建的控制流圖也是精確的,該方法缺點是代碼覆蓋率低,若要實現(xiàn)代碼高覆蓋率,需要大量有效的輸入。在使用靜態(tài)分析[14]方法時,不需要大量有效輸入,只需要通過解析對應平臺的文件結(jié)構(gòu),將解析到的指令和數(shù)據(jù)構(gòu)建控制流圖即可實現(xiàn),該方法的優(yōu)點是速度快,但是無法解決間接跳轉(zhuǎn)[15]問題。
Rimsa等人[16]使用了純動態(tài)分析方法,能夠更加準確捕捉程序的執(zhí)行行為,但純動態(tài)控制流圖重建的質(zhì)量依賴于輸入的覆蓋率。如果輸入不能觸發(fā)某些代碼路徑,控制流圖構(gòu)建便不完善。葉志斌等人[17]提出靜態(tài)符號執(zhí)行的混合分析控制流圖構(gòu)建方案,使用符號執(zhí)行和程序切片技術對目標程序進行動態(tài)分析,該方案需要采用求解器[18]求解路徑執(zhí)行流,導致對于復雜的程序路徑會造成約束求解開銷大、效率低等問題。對于靜態(tài)符號執(zhí)行產(chǎn)生的問題,Xie等人[19]采用動態(tài)符號執(zhí)行的方法構(gòu)建二進制程序的控制流圖,提高路徑覆蓋率,但仍存在路徑爆炸、約束求解復雜的問題。朱凱龍等人[20]在混合方法恢復控制流的方法中,采用動態(tài)二進制插樁的方式分析二進制程序,該方法相比符號執(zhí)行能夠較快地分析程序的間接跳轉(zhuǎn)地址,但動態(tài)二進制插樁在運行時對二進制代碼進行修改和監(jiān)視,這需要額外計算和內(nèi)存訪問開銷,會導致程序運行速度變慢,因此,該方法不適合包含有較復雜控制流的程序。
針對以上問題,本文提出了基于二進制重寫[21]的控制流圖構(gòu)建方法,采用模糊測試方法[22]生成大量有效的測試用例,輸入給重寫后的二進制文件執(zhí)行,從而獲取間接跳轉(zhuǎn)地址,然后,將間接跳轉(zhuǎn)目標地址與靜態(tài)分析得到的控制流圖相融合得到完整的控制流圖。相較于靜態(tài)符號執(zhí)行和動態(tài)二進制插樁技術,該方法避免使用求解器進行約束求解和動態(tài)執(zhí)行時監(jiān)控每條執(zhí)行的語句帶來的巨大開銷,高效地構(gòu)建了二進制程序完整的控制流圖。
2 混合分析控制流圖構(gòu)建
本文提出基于二進制重寫的混合分析控制流圖構(gòu)建方案,并設計實現(xiàn)了控制流圖構(gòu)建工具HBRCFG,該工具的具體架構(gòu)如圖1所示。HBRCFG通過靜態(tài)分析初步提取目標二進制文件的控制流圖。首先,采用模糊測試的方法獲取程序的輸入測試用例。其次,在動態(tài)分析階段,使用測試用例誘導重寫后的二進制程序執(zhí)行,獲取間接跳轉(zhuǎn)的目的地址。最后,使用融合算法將動態(tài)分析結(jié)果融合到靜態(tài)分析的控制流圖中,從而高效地構(gòu)建更加完整的控制流圖。
2.1 控制流圖構(gòu)建原理
2.1.1 控制流圖的定義
控制流圖可以抽象出程序的執(zhí)行路徑,用有向圖表示,記為G=(B,E),其中B是基本塊節(jié)點的集合,E是有向邊的集合。每個基本塊是程序指令的一個線性序列,具有單一的入口點和單一的出口點?;緣K可以有多個前驅(qū)和多個后繼。
在控制流圖中,每個節(jié)點bi代表一個基本塊,每條有向邊(bi,bj)表示程序控制從基本塊bi轉(zhuǎn)移到基本塊bj。存在一個后繼函數(shù)F將節(jié)點映射到直接后繼的集合F(bi)={bi|(bi,bj)∈E}。同樣,可以定義一個前驅(qū)函數(shù)F-1獲取一個節(jié)點的直接前驅(qū)集合??刂屏鲌D是連通的,從圖中的任何節(jié)點都可以通過連續(xù)應用F或F-1到任何其他節(jié)點,如圖2所示。
通過控制流圖,可以識別程序中的循環(huán)、條件分支、程序的入口和出口點等關鍵結(jié)構(gòu)。
2.1.2 間接跳轉(zhuǎn)原理
當程序中發(fā)生的調(diào)用不是顯式指定的,而是在程序執(zhí)行過程中動態(tài)值決定的,此時便會產(chǎn)生間接跳轉(zhuǎn)現(xiàn)象,在C/C++語言中,若使用函數(shù)指針、多態(tài)或動態(tài)鏈接庫等方式調(diào)用指定功能便會發(fā)生間接跳轉(zhuǎn)。在匯編語言語言層面便是以寄存器為調(diào)用對象,寄存器的值在程序運行時動態(tài)生成,靜態(tài)分析構(gòu)建控制流圖無法獲取寄存器中的值,導致構(gòu)建控制流圖不完備。
2.1.3 動態(tài)鏈接庫調(diào)用
動態(tài)鏈接庫屬于位置無關代碼,其可以被加載到內(nèi)存的各個位置執(zhí)行,所以使用動態(tài)鏈接庫函數(shù)時,編譯后函數(shù)地址不會顯式指定,而是通過寄存器間接調(diào)用,如示例代碼1所示,在API動態(tài)鏈接庫中實現(xiàn)Plus函數(shù),在main函數(shù)中加載動態(tài)鏈接庫并調(diào)用Plus函數(shù),匯編代碼顯示call rax,靜態(tài)分析獲取不到rax的值,無法構(gòu)建函數(shù)間的跳轉(zhuǎn)關系。
示例代碼1 動態(tài)鏈接庫調(diào)用
int main(){
typedef int(*lpPlus)(int,int);
lpPlus myPlus;
HMODULE hMod=LoadLibrary(\"api.dll\"); //加載動態(tài)鏈接庫
plus=(lpPlus)GetProcAddress(hMod,\"?Plus@@YAHHH@Z\");
int a=plus(10,2); //call rax
return 0;}
//動態(tài)鏈接庫api.dll:
#include \"apidll.h\"
int Plus(int x,int y){
return x+y;}
2.2 靜態(tài)分析構(gòu)建控制流圖
2.2.1 靜態(tài)反匯編
對于沒有源碼的二進制程序,需要將二進制結(jié)構(gòu)文件的指令部分進行反匯編,將對應的機器指令轉(zhuǎn)換成對應匯編指令,按照代碼結(jié)構(gòu)形成基本塊,依據(jù)跳轉(zhuǎn)關系構(gòu)建出靜態(tài)的控制流圖。其中線性反匯編是一種常用的反匯編方法,從程序入口開始對二進制代碼進行逐字節(jié)反匯編,該方法不能區(qū)分代碼和數(shù)據(jù),若出現(xiàn)滿足指令格式的數(shù)據(jù)時,也會被反匯編成指令,導致結(jié)果不準確。
本文采用遞歸反匯編方法,遞歸反匯編可以在遇到跳轉(zhuǎn)指令時,轉(zhuǎn)到跳轉(zhuǎn)的目的地址繼續(xù)進行反匯編,根據(jù)控制流進行反匯編的方式能夠清晰地區(qū)分代碼和數(shù)據(jù),反匯編工具IDA Pro[23]使用的就是采用遞歸反匯編的方法。
2.2.2 確定基本塊和邊
在控制流圖中,基本塊屬于原子節(jié)點,其中包含一組二進制代碼,該代碼順序執(zhí)行,從控制流開始進入,只有一個出口,其中沒有其他分支跳轉(zhuǎn)和調(diào)用,如果出現(xiàn)其他分支,其后續(xù)代碼應該劃分到下一個基本塊當中。因此基本塊的定義如下:
入口指令:函數(shù)的第一條指令、跳轉(zhuǎn)指令的下一條指令、匯編代碼緊鄰的下一條指令。出口指令:跳轉(zhuǎn)指令、返回指令、目標基本塊的上一條指令,其中跳轉(zhuǎn)指令包括間接跳轉(zhuǎn)和非間接跳轉(zhuǎn),CALL指令是無條件有返回的跳轉(zhuǎn)指令。
如果當前基本塊的最后一條指令是間接跳轉(zhuǎn)指令,無法獲得間接跳轉(zhuǎn)的目的地址,當前基本塊與后續(xù)基本塊的連接按照順序反匯編的結(jié)果進行連接,如圖3(a)所示。在靜態(tài)分析時如果兩個基本塊存在直接跳轉(zhuǎn)關系,這兩個基本塊之間存在一條邊,如圖3(b)所示。
2.3 動態(tài)分析獲取間接跳轉(zhuǎn)地址
在靜態(tài)分析結(jié)果中,并不能夠發(fā)現(xiàn)間接跳轉(zhuǎn)的地址,針對這個問題,本文使用二進制重寫技術對間接跳轉(zhuǎn)地址插樁,獲取間接跳轉(zhuǎn)地址。為了獲取更多的控制流,需要在對二進制重寫之前先進行模糊測試,使用模糊測試[23]生成的測試用例誘導重寫后的二進制程序執(zhí)行,并記錄執(zhí)行過程中的間接跳轉(zhuǎn)。
2.3.1 提高代碼覆蓋率
針對不同輸入數(shù)據(jù),程序可能會產(chǎn)生不同的執(zhí)行路徑,為提高程序代碼覆蓋率,使最終生成的控制流圖更加完整,本文采用模糊測試方法,獲取更多的有效輸入讓程序執(zhí)行不同路徑。文獻[17]中使用符號執(zhí)行的技術方法,對大規(guī)模的程序存在著復雜的約束,使用求解器求解,耗時嚴重,甚至無法求解。本文方案用模糊測試的方法能夠很好地避免該問題。
本文在模糊測試中采用基于覆蓋的灰盒模糊測試(CGF),輸入隨機生成的種子,并利用AFL++[24]遺傳算法的變異策略對輸入的種子進行評估、變異,若該輸入能發(fā)現(xiàn)新的執(zhí)行路徑,則對該輸入繼續(xù)變異。為避免變異產(chǎn)生的大量測試用例讓二進制程序重復執(zhí)行相同路徑,方案只收集能夠讓二進制程序執(zhí)行不同路徑的測試用例,并標記為該二進制程序的測試用例。
2.3.2 獲取間接跳轉(zhuǎn)地址
將模糊測試生成的測試用例依次輸入給指定的二進制程序,程序在執(zhí)行過程中記錄間接跳轉(zhuǎn)地址。HBRCFG使用二進制重寫[12]的方式,提前對需要提取CFG的二進制程序進行重寫,重寫增加的代碼用來監(jiān)控程序執(zhí)行過程中遇到的間接跳轉(zhuǎn)。如果遇到間接跳轉(zhuǎn)便記錄下間接跳轉(zhuǎn)的目的地址。朱凱龍等人[20]使用動態(tài)插樁的方式對程序中會發(fā)生間接跳轉(zhuǎn)的指令進行監(jiān)控,該方法會在程序執(zhí)行時對每條執(zhí)行指令進行插樁,隨后再判斷指令是否符合要求,該方法損失了執(zhí)行效率。二進制重寫技術直接在原二進制文件中寫入新增的代碼,當使用測試用例誘導執(zhí)行時,直接順序執(zhí)行二進制指令,相比動態(tài)二級制插樁的方法效率更高。
2.4 控制流圖構(gòu)建優(yōu)化算法
本文將靜態(tài)分析得到的控制流圖與動態(tài)分析得到的間接跳轉(zhuǎn)地址融合,從而完善控制流圖。在進行靜態(tài)分析時,只能把靜態(tài)的二進制文件解析后,根據(jù)機器碼翻譯成對應的匯編指令,但無法執(zhí)行指令。若分析的二進制程序中存在函數(shù)遞歸調(diào)用,靜態(tài)分析過程中并不能理解何時結(jié)束遞歸調(diào)用,所以要在靜態(tài)分析控制流圖時加上限制條件,從而避免靜態(tài)分析時產(chǎn)生無限循環(huán)。
2.4.1 避免靜態(tài)分析遞歸循環(huán)算法
在二進制程序中若存在遞歸調(diào)用,靜態(tài)遞歸反匯編時無法判斷程序的出口,若通過call指令的操作數(shù)來構(gòu)建后續(xù)的控制流圖,將會導致構(gòu)建程序陷入無限循環(huán)當中,所以需要破除遞歸調(diào)用導致的循環(huán),避免遞歸循環(huán)的方法如算法1所示。該算法遍歷每個函數(shù)的基本塊,如果不是間接跳轉(zhuǎn)分支便獲取跳轉(zhuǎn)目標地址,如果目標地址指向本函數(shù)地址,便不再分析該分支的后續(xù)控制流。
算法1 避免遞歸循環(huán)
輸入:函數(shù)控制流圖。
輸出:非間接跳轉(zhuǎn)目標基本塊。
a) fbbs=function.bbs()
b) for bb in fbbs //遍歷函數(shù)基本塊
c) if bb.endins not INDIRECT //基本塊最后不是間接跳轉(zhuǎn)指令
d) target=getTarget(bb) //獲取跳轉(zhuǎn)目標
e)
if target!=function.addr //目標不是自身
f)
targets.append(target) //加入后續(xù)構(gòu)建隊列
g) return targets
2.4.2 融合控制流圖算法
本文提出融合算法,將動態(tài)分析的間接跳轉(zhuǎn)地址融合到靜態(tài)分析得到的控制流圖當中,從而完善目標程序的控制流圖,具體如算法2所示,動態(tài)分析時將獲取間接跳轉(zhuǎn)的指令地址和間接跳轉(zhuǎn)的目的地址,循環(huán)篩選出間接跳轉(zhuǎn)指令所在的基本塊,將該基本塊的目標基本塊融合到控制流圖當中。
算法2 融合控制流圖
輸入:靜態(tài)分析控制流圖;間接跳轉(zhuǎn)指令地址和間接跳轉(zhuǎn)目標。
輸出:融合間接跳轉(zhuǎn)的控制流圖。
a) for bb in sCFG.blocks:
b)
if ins_address in bb.addrscope:
c) if bb.endins is INDIRECT_ins: //判斷結(jié)尾指令是跳轉(zhuǎn)指令
d) targets=getTargetAddress(bb.endins) //獲取所有目標
e) for t in targets:
f)
connect bb to t
g)connect t to bb.successors //t繼承bb的所有后繼
h)disconnect bb to bb.successors //斷開bb之前的后繼
i) return sCFG
如圖4所示,因為在靜態(tài)分析時,已經(jīng)將間接調(diào)轉(zhuǎn)指令作為基本塊的出口指令,所以在融合時,便只需要檢查基本塊的出口指令是否是間接跳轉(zhuǎn)指令,若滿足則獲取該間接跳轉(zhuǎn)的目標地址的基本塊。隨后將該基本塊的后繼連接關系繼承給間接跳轉(zhuǎn)的目標基本塊,并在該基本塊與目標基本塊之間添加一條邊,實現(xiàn)與目標基本塊的鏈接。這里的間接跳轉(zhuǎn)的目標可能有多個,所以需要依次處理該基本塊與目標基本塊之間的關系,完善靜態(tài)分析的結(jié)果,從而制備出更加精確的控制流圖。
3 實驗
3.1 實驗環(huán)境
Kali2022 64 bit操作系統(tǒng),CPU使用Intel Core i3-4170HQ @3.70 GHz,內(nèi)存為DDR3 8 GB。先使用手工構(gòu)造的包含間接跳轉(zhuǎn)地址的程序驗證HBRCFG的有效性;實驗數(shù)據(jù)使用網(wǎng)絡安全挑戰(zhàn)賽[25](CGC)中部分二進制程序。
3.2 實驗結(jié)果分析
3.2.1 有效性分析
手工構(gòu)造包含的間接跳轉(zhuǎn)的程序源碼如示例代碼2所示,該程序通過輸入的值來判斷需要調(diào)用的函數(shù),其中函數(shù)指針變量的值可能是func1函數(shù)地址值或者是func2函數(shù)地址值,通過編譯之后,使用函數(shù)指針變量indirect對func1和func2的函數(shù)調(diào)用時,在匯編層面調(diào)用指令為CALL RCX,調(diào)用的目的地址是程序運行時寄存器RCX中的值,寄存器的名稱并不能指導靜態(tài)分析構(gòu)建后續(xù)的控制流圖,在程序安全性分析時,間接跳轉(zhuǎn)函數(shù)中的問題就無法被分析。
示例代碼2 程序pointer_call源代碼
int func1();int func2();void func(int a,int b);
int main(){
int a,b;
scanf(\"%d%d\",amp;a,amp;b);
func(a,b);
return 0;}
int func1(){return 1;}
int func2(){return 0;}
void func(int a,int b){
int(*indirect)(); //定義函數(shù)指針
if (a gt; b) indirect=func1; //根據(jù)條件給指針賦值
else indirect=func2;
indirect(); //CALL RCX}
在對pointer_call源代碼編譯鏈接之后,通過靜態(tài)反匯編的方式構(gòu)建出程序的控制流圖。圖5是其中func函數(shù)的控制流圖,可以發(fā)現(xiàn)基本塊和邊都滿足定義的規(guī)則。因為間接跳轉(zhuǎn)關系發(fā)生在func函數(shù)當中,所以func函數(shù)中出現(xiàn)了call rdx形式的間接函數(shù)調(diào)用。
如圖6所示是程序pointer_call融合后的控制流圖,為了方便說明問題,這里展示了發(fā)生間接跳轉(zhuǎn)的func函數(shù)部分,虛線的邊是發(fā)現(xiàn)間接跳轉(zhuǎn)。在圖中0x40116a是func通過函數(shù)指針調(diào)用函數(shù)的基本塊,指令是call rdx,rdx取值不同將會調(diào)用不同的函數(shù),本文通過動態(tài)分析得到rdx可能的取值。當a>b時,函數(shù)指針indirect賦值為func2函數(shù)地址,此時rdx的值為0x401126。當a<b時,函數(shù)指針indirect賦值為func2函數(shù)地址,此時rdx的值為0x401131。使用二進制重寫的混合分析方法能夠分析出間接調(diào)轉(zhuǎn)關系,并且對于同一基本塊的多個間接跳轉(zhuǎn)關系同樣能夠識別,HBRCFG能夠構(gòu)建包含間接跳轉(zhuǎn)的完整的控制流圖。
本文從二進制程序的入口開始分析,由入口代碼開始構(gòu)建程序的控制流圖。統(tǒng)計分析靜態(tài)分析工具IDA和HBRCFG對示例程序的執(zhí)行情況,結(jié)果如表1所示,pointer_callh、pointer_calli分別表示HBRCFG和IDA的分析結(jié)果。表中F表示由程序入口開始分析得到的函數(shù)數(shù)量,V表示構(gòu)建控制流圖中基本塊數(shù)量,E表示連接關系的數(shù)量,I表示HBRCFG發(fā)現(xiàn)的間接跳轉(zhuǎn)的數(shù)量。從統(tǒng)計結(jié)果中可以觀察出,HBRCFG能夠發(fā)現(xiàn)目標程序中的間接跳轉(zhuǎn),相比于靜態(tài)分析能夠發(fā)現(xiàn)更多的函數(shù)體。所以HBRCFG能夠有效地識別間接跳轉(zhuǎn)關系,構(gòu)建更加完整的控制流圖。
3.2.2 性能分析
在大規(guī)模程序分析時,需要考慮程序分析效率,實驗將進一步驗證本文算法的性能。將采用實驗環(huán)境中的數(shù)據(jù)(CGC),使用CFGConstructor[20]進行混合分析構(gòu)建控制流圖的結(jié)果如表2所示,本文算法的分析結(jié)果如表3所示。其中S是每個測試程序的大小,I是發(fā)現(xiàn)間接跳轉(zhuǎn)的數(shù)量,相比于CFGConstructor,HBRCFG能夠構(gòu)建Rn間接跳轉(zhuǎn)函數(shù)中的后續(xù)函數(shù)調(diào)用控制流,進一步構(gòu)建完備的控制流圖。并且統(tǒng)計了Ru后續(xù)調(diào)用中不重復的函數(shù)數(shù)量。Fh-c、Vh-c、Eh-c、Ih-c表示HBRCFG比CFGConstructor多發(fā)現(xiàn)的函數(shù)、基本塊、邊和間接跳轉(zhuǎn)關系的百分比。由表中的結(jié)果可以看出,CFGConstructor能夠發(fā)現(xiàn)大部分的函數(shù)和間接跳轉(zhuǎn)關系,對于間接跳轉(zhuǎn)函數(shù)中產(chǎn)生的跳轉(zhuǎn)關系仍不能構(gòu)建。HBRCFG能夠在動態(tài)執(zhí)行后發(fā)現(xiàn)間接跳轉(zhuǎn)關系,并將對應的跳轉(zhuǎn)關系融合到靜態(tài)分析的控制流圖當中,且能夠從發(fā)現(xiàn)的間接跳轉(zhuǎn)的可達函數(shù)中繼續(xù)構(gòu)建其發(fā)生的調(diào)用關系Rn。實驗結(jié)果中,netstorage和CableGrind程序HBRCFG能夠分析出大量間接跳轉(zhuǎn)的后續(xù)函數(shù)調(diào)用,完善控制流圖邊的構(gòu)建,進一步制備更加完備控制流圖。就兩個工具分析出的函數(shù)、節(jié)點、邊和間接跳轉(zhuǎn)函數(shù)的數(shù)量來說,本文算法比CFGConstructor混合分析的效果更好。本文算法平均能夠比CFGConstructor多發(fā)現(xiàn)35.9%的函數(shù),60.7%的基本塊,60%的邊和38%的間接跳轉(zhuǎn)。
對HBRCFG的分析效率進行評估,實驗選擇使用AFL++對目標程序進行模糊測試生成測試用例。為生成更多有效的測試用例集,模糊測試停止時間根據(jù)afl-fuzz的狀態(tài)決定,若在半小時后仍不能發(fā)現(xiàn)新的執(zhí)行路徑就停止模糊測試。使用測試用例誘導重寫后的程序執(zhí)行,記錄程序開始執(zhí)行到完成控制流圖融合所需的時間,如表4所示,記錄HBRCFG每次分析的時間t單位秒,以及每次使用測試用例數(shù)量T??梢钥闯?,體積越大、執(zhí)行路徑更復雜的程序,需要的測試用例的數(shù)量也會越多。為了更高效地進行動態(tài)分析,實驗只保存能夠讓程序執(zhí)行不同路徑的測試用例。
表4的th結(jié)果中可以看出,HBRCFG更夠更加高效地構(gòu)建程序的完整控制流圖,實驗程序Grit體積186 KB大小,HBRCFG能夠在11.38 s完成完整的控制流圖的構(gòu)建,該程序使用的測試用例有2 029個,構(gòu)建的控制流圖中包含81個函數(shù),函數(shù)中包含1 270個基本塊和1 950條連接。CFGConstructor使用動態(tài)插樁的方式動態(tài)分析表4中tp所示,同樣條件下將耗時1 022.36 s,時間效率將提升89倍。如果采用靜態(tài)符號執(zhí)行的方法恢復目標程序的控制流圖,將產(chǎn)生約束復雜,求解路徑爆炸,甚至無解的問題;使用動態(tài)二進制插樁的方法時,誘導程序動態(tài)執(zhí)行時,監(jiān)控程序執(zhí)行的指令,開銷太大。所以,HBRCFG能夠在開銷更小的情況下構(gòu)建出目標程序完成的控制流圖。
4 結(jié)束語
本文提出使用基于二進制重寫的混合分析構(gòu)建二進制程序的控制流圖方案,設計并實現(xiàn)了控制流圖構(gòu)建工具HBRCFG。相較于以往的控制流圖構(gòu)建方案,使用二進制重寫技術提高了動態(tài)執(zhí)行效率,改進了靜態(tài)分析時構(gòu)建控制流圖基本塊的規(guī)則,使其能夠在融合分析結(jié)果時更加高效。最終實驗表明,相比于CFGConstructor,HBRCFG能夠在目標程序中平均多發(fā)現(xiàn)35.9%的函數(shù),60.7%的基本塊,60%的邊和38%的間接跳轉(zhuǎn)。并且在保證控制流圖完整性的情況下,相較于動態(tài)二進制插樁的動態(tài)分析方案,本方案時間提升了38倍,更能應對大規(guī)模的程序分析。下一步研究方向,將針對影響代碼覆蓋率的字節(jié)進行變異,減少無效輸入,通過較少的輸入數(shù)據(jù)發(fā)現(xiàn)更多的執(zhí)行路徑,提高模糊測試效率,從而更加高效地構(gòu)建更加完整的控制流圖。
參考文獻:
[1]Xu Liang,Sun Fangqi,Su Zhendong.Constructing precise control flow graphs from binaries[D].Davis,CA:University of California,Davis,2009:14-23.
[2]孫祥杰,魏強,王奕森,等.代碼相似性檢測技術綜述[J].計算機應用,2024,44(4):1248-1258.(Sun Xiangjie,Wei Qiang,Wang Yisen,et al.Survey of code similarity detection technology[J].Journal of Computer Applications,2024,44(4):1248-1258.)
[3]Yu Zeping,Cao Rui,Tang Qiyi,et al.Order matters:semantic-aware neural networks for binary code similarity detection[C]//Proc of AAAI Conference on Artificial Intelligence.Palo Alto,CA:AAAI Press,2020:1145-1152.
[4]Wang Yan,Jia Peng,Peng Xi,et al.BinVulDet:detecting vulnerability in binary program via decompiled pseudo code and BiLSTM-attention[J].Computers amp; Security,2023,125:103023.
[5]Hin D,Kan A,Chen Huaming,et al.LineVD:statement-level vulnerability detection using graph neural networks[C]//Proc of the 19th International Conference on Mining Software Repositories.New York:ACM Press,2022:596-607.
[6]Li Litao,Ding S H H,Tian Yuan,et al.VulANalyzeR:explainable binary vulnerability detection with multi-task learning and attentional graph convolution[J].ACM Trans on Privacy and Security,2023,26(3):1-25.
[7]Luo Zhenhao,Wang Pengfei,Wang Baosheng,et al.VulHawk:cross-architecture vulnerability detection with entropy-based binary code search[C]//Proc of NDSS.2023.
[8]Seneviratne S,Shariffdeen R,Rasnayaka S,et al.Self-supervised vision Transformers for malware detection[J].IEEE Access,2022,10:103121-103135.
[9]Lucas K,Pai S,Lin Weiran,et al.Adversarial training for Raw-Binary malware classifiers[C]//Proc of the 32nd USENIX Security Sympo-sium.Berkeley,CA:USENIX Association,2023:1163-1180.
[10]Chen Sanchuan,Lin Zhiqiang,Zhang Yinqian.SelectiveTaint:efficient data flow tracking with static binary rewriting[C]//Proc of the 30th USENIX Security Symposium.Berkeley,CA:USENIX Association,2021:1665-1682.
[11]Hough K,Bell J.A practical approach for dynamic taint tracking with control-flow relationships[J].ACM Trans on Software Enginee-ring and Methodology,2021,31(2):1-43.
[12]Van Bertrand O C H,Legay A.Malware analysis with symbolic execution and graph kernel[C]//Proc of Nordic Conference on Secure IT Systems.Cham:Springer International Publishing,2022:292-310.
[13]Wu Qingyang,Huo Quanrui,Ning Yuqiao,et al.A survey of binary code security analysis[C]//Proc of the 6th International Conference on Data Science and Information Technology.Piscataway,NJ:IEEE Press,2023:42-49.
[14]Zhou Anshunkang,Ye Chengfeng,Huang Heqing,et al.Plankton:re-conciling binary code and debug information[C]//Proc of the 29th ACM International Conference on Architectural Support for Programming Languages and Operating Systems.New York:ACM Press,2024:912-928.
[15]Wang Hao,Qu Wenjie,Katz G,et al.jTrans:jump-aware Transformer for binary code similarity detection[C]//Proc of the 31st ACM SIGSOFT International Symposium on Software Testing and Analysis.New York:ACM Press,2022:1-13.
[16]Rimsa A,Amaral J N,Quint?o F M.Efficient and precise dynamic construction of control flow graphs[C]//Proc of XXIII Brazilian Symposium on Programming Languages.New York:ACM Press,2019:19-26.
[17]葉志斌,姜鑫,史大偉.一種面向二進制的控制流圖混合恢復方法[J].計算機應用研究,2018,35(7):2168-2171.(Ye Zhibin,Jiangxin,Shi Dawei.Combined method of constructing binary-oriented control flow graph[J].Application Research of Computers,2018,35(7):2168-2171.)
[18]Microsoft Research.Z3:an efficient SMT solver[EB/OL].[2024-04-26].https://github.com/Z3Prover/z3.
[19]Xie Bailin,Li Qi,Luo Jiabin.Program vulnerability mining system based on symbolic execution[C]//Proc of the 7th International Conference on Intelligent Information Technology.New York:ACM Press,2022:83-89.
[20]朱凱龍,陸余良,黃暉,等.基于混合分析的二進制程序控制流圖構(gòu)建方法[J].浙江大學學報:工學版,2019,53(5):829-836.(Zhu Kailong,Lu Yuliang,Huang Hui,et al.Construction approach for control flow graph from binaries using hybrid analysis[J].Journal of Zhejiang University:Engineering Science,2019,53(5):829-836.)
[21]Duck G J,Gao Xiang,Roychoudhury A.Binary rewriting without control flow recovery[C]//Proc of the 41st ACM SIGPLAN Conference on Programming Language Design and Implementation.New York:ACM Press,2020:151-163.
[22]Dutra R,Gopinath R,Zeller A.FormatFuzzer:effective fuzzing of binary file formats[J].ACM Trans on Software Engineering and Methodology,2023,33(2):1-29.
[23]Hex-Rays.IDAPro disassembler[EB/OL].[2024-04-20].https://www.hex-rays.com/.
[24]Fioraldi A,Maier D,Eiβfeldt H,et al.AFL++:combining incremental steps of fuzzing research[C]//Proc of the 14th USENIX Workshop on Offensive Technologies.Berkeley,CA:USENIX Association,2020:10.
[25]DARPA.DARPA cyber grand challenge[EB/OL].[2024-05-01].https://github.com/CyberGrandChallenge.