羅治祥,向 棲,李樂言,3
(1.工業(yè)和信息化部電子第五研究所,廣東 廣州 511370;2.東北大學(xué) 軟件學(xué)院,遼寧 沈陽 110819;3.智能產(chǎn)品質(zhì)量評價與可靠性保障技術(shù)工業(yè)和信息化部重點實驗室,廣東 廣州 511370)
近年來,隨著計算機技術(shù)的不斷發(fā)展,軟件行業(yè)迅速發(fā)展,軟件的體量、種類不斷增大。同時,由于程序代碼編寫不規(guī)范,編寫過程存在疏忽,或者缺乏軟件安全方面的意識等,導(dǎo)致軟件的安全性承受巨大威脅。針對這一現(xiàn)狀,構(gòu)建漏洞檢測系統(tǒng)對軟件進行安全檢測是最行之有效的辦法之一,可在一定程度上發(fā)現(xiàn)并且及時消除潛在的漏洞。
軟件的安全檢測方法通??梢苑譃閯討B(tài)測試[1]和靜態(tài)分析[2]兩大類,靜態(tài)分析這一方法相較于動態(tài)測試具有更高的覆蓋率以及性能效率?,F(xiàn)有的靜態(tài)分析方案大多都基于源碼級別[3]進行分析,雖然可以在比較高的程度上滿足軟件安全需要,但是在許多真實的安全測試場景中,需要分析對象大多屬于常見的二進制文件,比如商業(yè)軟件、車機固件、嵌入式系統(tǒng)固件等。此時安全研究人員難以獲得相應(yīng)的源代碼,源碼級靜態(tài)分析方案不再適用。現(xiàn)今商業(yè)化的二進制程序漏洞分析系統(tǒng)基本不具備可二次開發(fā)的擴展性,而開源的二進制程序漏洞分析系統(tǒng),比如 angr[4]、 BAP[5]、 BinAbsInspector等優(yōu)秀的靜態(tài)分析工具存在一些適用性問題。其中,angr 和 BAP 正逐步發(fā)展為通用分析框架,而不僅僅專注于二進制漏洞掃描,這使得內(nèi)部分析算法變得復(fù)雜,不便于后續(xù)的擴展和優(yōu)化。BinAbsInspector是基于Ghidra的插件,使用Java編寫開發(fā),提供的API比較有限,在可擴展性上有所欠缺,普通的二進制安全研究員無法有效地基于該工具進行自定義開發(fā)。因此,構(gòu)建一款在性能和可擴展性上較為突出,同時也滿足于真實場景需要的二進制程序漏洞檢測系統(tǒng)刻不容緩。
針對上述問題,Tan[6]等基于Java提出了一種較為簡易的指針分析[7]算法,該算法在使用Datalog[8]引擎支撐之后,在構(gòu)建好的程序抽象數(shù)據(jù)上進行分析,使得性能得到較大的提升。對于獲取二進制程序抽象數(shù)據(jù)而言,普遍的做法是反編譯[9]二進制程序生成IR中間表示,進一步對其進行優(yōu)化和轉(zhuǎn)換得到其AST語法樹,最后依據(jù)AST語法樹得到程序抽象數(shù)據(jù),比較好的工具有IDA Pro、Ghidra、Binary Ninja等。本文設(shè)計系統(tǒng)選取了IDA Pro進行程序抽象數(shù)據(jù)獲取,使用IDA Pro特有的IDAPython,從原生角度適配了IDA Pro提供各項API接口,從可擴展性上兼具了Python腳本跨平臺、易擴展等優(yōu)點;從性能方面,Python庫中的pyDatalog可以替代常見的Datalog引擎,且性能方面相差無幾。
本文將以污點分析為基礎(chǔ),對IDA Pro中插件Hex-Rays反編譯時的語法樹AST中相關(guān)的變量賦值、函數(shù)調(diào)用等進行抽象解析,使之成為特定的數(shù)據(jù)結(jié)構(gòu)。隨后使用Datalog對抽象之后的數(shù)據(jù)進行指針分析,在此基礎(chǔ)上加入污點分析,通過Datalog得到相關(guān)指針結(jié)果,依據(jù)用戶提供的污點source和定義的sink,結(jié)合緩沖區(qū)溢出[10]、格式化字符串[11]、堆內(nèi)存使用不當(dāng)?shù)嚷┒吹奶卣鳎M一步檢測出二進制程序中的漏洞。由于依賴的底層數(shù)據(jù)是基于Hex-Rays反編譯出的語法樹,因此是否支持不同架構(gòu)的二進制程序只會取決于Hex-Rays是否能夠?qū)υ摷軜?gòu)程序進行反編譯。此外由于使用Datalog進行污點分析,其效率和準(zhǔn)確度也會得到相應(yīng)提高。綜上所述,本論文基于污點分析,結(jié)合Hex-Rays反編譯的語法樹以及Datalog對二進制程序進行漏洞檢測,更加具有應(yīng)用價值和研究意義。
依據(jù)上述的程序語言以及邏輯構(gòu)思,本系統(tǒng)構(gòu)建的整體數(shù)據(jù)流程業(yè)務(wù)如圖1所示。
圖1 系統(tǒng)架構(gòu)圖
本系統(tǒng)采用C/S架構(gòu),并且以MVC設(shè)計模式進行設(shè)計,設(shè)計的系統(tǒng)架構(gòu)如圖2所示,由上至下系統(tǒng)主要分為用戶交互層、數(shù)據(jù)處理層、指針/污點分析層、業(yè)務(wù)處理層四個主要層次。
圖2 系統(tǒng)架構(gòu)圖
在用戶交互層中,依據(jù)IDA Pro提供的各種接口,利用IDAPython結(jié)合PyQt進行界面開發(fā),旨在提供一個對用戶友好的界面處理。該視圖控制層中的主要功能有漏洞模式配置,用來選取漏洞分析模式以及管理污點數(shù)據(jù)庫。還有審閱界面,當(dāng)分析完成時,可以在此界面對漏洞報告進行查看、導(dǎo)出,以及污點路徑的相關(guān)審閱工作。
在數(shù)據(jù)處理層中,將對程序進行一些預(yù)處理工作,獲取程序?qū)?yīng)的語法樹方便后續(xù)進行分析。然后還需要對程序代碼進行數(shù)據(jù)抽象處理,分為New/Assign等多種數(shù)據(jù),將程序解析成能夠使得數(shù)據(jù)分析引擎進行分析的各項數(shù)據(jù)。最后需要對這些程序代碼抽象出來的數(shù)據(jù)進行存儲。
指針/污點分析層是主要的漏洞分析模塊,獲取上述得到的程序代碼抽象數(shù)據(jù),然后依據(jù)編寫的Datalog程序?qū)Τ绦虺橄蠛蟮母黝悢?shù)據(jù)進行指針/污點分析,最終輸出相關(guān)的分析結(jié)果。
業(yè)務(wù)處理層主要依據(jù)指針/污點分析層得到的相關(guān)分析結(jié)果,建立相關(guān)的漏洞模式,依據(jù)漏洞模式的相關(guān)規(guī)則,嘗試檢測出漏洞,最后導(dǎo)出相關(guān)漏洞報告。針對污點數(shù)據(jù)Sources/Sinks處理,該層提供顯示污點路徑以及污點路徑表格化展示功能。
1.3.1 功能模塊設(shè)計
本系統(tǒng)的功能模塊設(shè)計如圖3所示,主要包括程序輸入模塊、程序預(yù)處理模塊、污點分析模塊、漏洞檢測模塊四個部分。
圖3 功能模塊設(shè)計圖
1.3.2 詳細設(shè)計
(1)程序輸入模塊
在該模塊中,主要的功能為在IDA Pro中導(dǎo)入二進制程序文件,選取漏洞分析模式,配置污點數(shù)據(jù)庫Sources/Sinks。其中漏洞分析模式主要有如下三種:
① 漏洞分析模式
該模式將會自動分析當(dāng)前二進制程序文件,依據(jù)指針分析結(jié)果和相關(guān)的漏洞模式來尋找漏洞,并且提供漏洞分析報告析。
② 僅Source分析
用戶可以在污點數(shù)據(jù)Sources/Sinks的管理界面使用下拉框選取污點數(shù)據(jù)。比如選取main函數(shù)中變量v1作為Source,均以數(shù)據(jù)下列框、按鈕等形式來選取。隨后即可進行污點分析,依據(jù)用戶給出的污點數(shù)據(jù)集合和指針分析結(jié)果,分析出污點數(shù)據(jù)可能的流向,并且提供相關(guān)的數(shù)據(jù)流報告。
③ Source/Sinks分析
用戶創(chuàng)建了對應(yīng)的污點數(shù)據(jù)集合后,還可以選取用戶特定感興趣的函數(shù)放入Sinks集合中,比如選取main函數(shù)中的read函數(shù)作為Sink等。隨后開始進行污點分析,判斷在Sinks集合是否被污點數(shù)據(jù)污染,并且提供相關(guān)的污染報告。
(2)預(yù)處理模塊
該模塊的主要功能為獲取程序語法樹、程序數(shù)據(jù)抽象、抽象數(shù)據(jù)存儲?;赥an[6]等提出指針分析算法改進的Datalog抽象數(shù)據(jù)規(guī)則算法如算法1所示。
算法1: Datalog抽象數(shù)據(jù)規(guī)則算法 1 New(x:V, o:O, m:M, c_x:C)2 Assign(x:V, y:V, c_x:C, c_y:C)3 Store(x:V, f:F, y:V, c_y:C)4 Load(y:V, x:V, f:F, c_y:C, c_x:C)5 Argument(l:S,i:N,ai:V,thisM:M)6 Parameter(m:M,i:N,pi:V)7 MethodReturn(m:M,ret:V)8 CallReturn(l:S,r:V,thisM:M)9 Methods(l:C,mName:M)10 VCall(l:S,x:V,k:M,thisM:M)
由于需要確定各個函數(shù)中對應(yīng)的變量所指向?qū)ο?,因此加入了thisM屬性來進行區(qū)分。
依據(jù)上述的數(shù)據(jù)抽象規(guī)則,使用IDAPython與IDA Pro提供的API進行交互,遍歷語法樹中所有可達函數(shù),將對應(yīng)的變量聲明、存儲、賦值、上下文等信息進行抽象,以csv格式保存在文件中。
(3)污點分析模塊
污點分析模塊中主要包含抽象數(shù)據(jù)存儲、指針分析、污點分析、指針分析結(jié)果存儲幾個功能。從文件中獲取到存儲的抽象數(shù)據(jù)之后,就可以按如下步驟進行分析。
① 指針分析
基于Tan[6]提出指針分析算法改進的Datalog指針分析規(guī)則算法如算法2所示。
算法2: Datalog指針分析規(guī)則算法 1 VarPointsTo( v:V,o:obj,c_var:C,c_obj:C,m:method).2 FieldPointsTo(Oi:obj,f:field,Oj:obj,c_Oi:C,c_Oj:C).3 Reachable(m:method).4 CallGraph(l:stmt,m:method,thisM:method).5 Reachable(m),CallGraph(l,m,thisM) <- VCall(l,m,thisM),Reachable(thisM).6 VarPointsTo(x,o,c_xo,c_xo,m) <- Reach-able(m),New(x,o,m,c_xo).7 VarPointsTo(x,o,c_x,c_o,m) <- Assign(x,y,c_x,c_y), VarPointsTo(y,o,c_y,c_o,m).8 VarPointsTo(y,Oj,c_y,c_Oj,m) <- Load(y,x,f,c_y,c_x), VarPointsTo(x,Oi,c_x,c_Oi,m), FieldPointsTo(Oi,f,Oj,c_Oi,c_Oj).9 FieldPointsTo(Oi,f,Oj,c_Oi,c_Oj) <- Store(x,f,y,c_y), VarPointsTo(x,Oi,c_x,c_Oi,m), VarPointsTo(y,Oj,c_y,c_Oj,m).10 VCall(l:stmt,m:method,thisM:method)11 Argument(l:stmt,i:number,ai:V,thisM:meth-od).12 Parameter(m:method,i:number,pi:V).13 Methods(label:C,mName:method).14 VarPointsTo(pi,o,label,c_o,m) <- Methods(label,m), CallGraph(l,m,thisM), Argument(l,i,ai,thisM), Parameter(m,i,pi), VarPointsTo(ai,o,c_ai,c_o,thisM).15 CallReturn(l:stmt,r:V,thisM:method).
將不再需要Tan[6]等提出的指針分析算法中的Dispatch/ThisVar變量,因為在反編譯得到的語法樹中,其函數(shù)名是唯一標(biāo)識的,不存在相同的函數(shù)名稱。
由于Hex-Rays反編譯得到的語法樹較為復(fù)雜,所提供的API種類繁多,實際進行數(shù)據(jù)抽象的流程較為復(fù)雜,因此圖4展示的僅為數(shù)據(jù)抽象時的流程簡圖。
圖4 程序數(shù)據(jù)抽象流程簡圖
② 污點分析
同樣也是基于Tan[6]等提出指針分析算法改進的Datalog污點分析規(guī)則,對應(yīng)有數(shù)據(jù)污染源Source(m:M),程序代碼關(guān)鍵關(guān)注點Sink(m:M,i:N),污染數(shù)據(jù)點Taint(l:S,t:T)。即把所有的污點數(shù)據(jù)產(chǎn)生點上下文`l:S′關(guān)聯(lián)到產(chǎn)生的污點數(shù)據(jù)tainted data,即t:T中。傳遞污點數(shù)據(jù)算法如算法3所示。
算法3: Datalog污點傳遞規(guī)則算法 1 VarPointsTo(r,t) <- CallGraph(l,m),Source(m),CallReturn(l,r),Taint(l,r).2 TaintFlow(j,l,i) <- CallGraph(l,m),Sink(m,i),Argument(l,i,ai),VarPointsTo(ai,t),Taint(j,t).
TaintFlow代表j點產(chǎn)生的污點數(shù)據(jù)在流向l點調(diào)用的函數(shù),其參數(shù)位置為i。但是由于JAVA中一切即對象的思想,因此所有的函數(shù)過程傳遞都會用上污點傳遞,而在C中并不是很適合。所以,當(dāng)指針分析結(jié)果中相關(guān)對象是被污染的對象,就將其加入到污點流動集合中。進而設(shè)計定義TaintVar(m:M,v:V),TaintVar依據(jù)用戶選定的污點數(shù)據(jù)集合進行構(gòu)造,代表用戶選中函數(shù)m中的v變量作為污點Source。隨后依據(jù)污點數(shù)據(jù)集合,將對應(yīng)變量指向的對象進行污染,方便后續(xù)進行指針分析時傳遞污點對象,具體設(shè)計如算法4所示。
算法4: Datalog污點對象流動算法 1 TaintObj(o:obj,c_obj:context,m:method)2 TaintObj(o,c_xo,m) <- Reachable(m),New(x,o,m,c_xo),TaintVar(m,x).3 TaintTranslate(v:var,c_v:context,o:obj,m:method)4 TaintTranslate(x,c_x,o,m) <- VarPointsTo(x,o,c_x,c_xo,m),TaintObj(o,c_xo,m).
通過TaintObj將對象進行污染,當(dāng)指針分析結(jié)果中存在污點對象,則標(biāo)注出對應(yīng)指向污點對象的變量。在對應(yīng)的IDAPython腳本中獲取到Sinks集合,判斷集合中調(diào)用的函數(shù)參數(shù)是否包含指向污點對象的變量即可。最后完成分析結(jié)果存儲工作,方便進行下一步的漏洞分析或者污點分析報告。
(4)漏洞檢測模塊
針對漏洞分析模塊通常需要設(shè)定一些常見漏洞模式,比如從IDA Pro提供的語法樹中獲取read函數(shù)列表,判斷調(diào)用read函數(shù)讀取字符時讀取數(shù)量是否大于當(dāng)前緩沖區(qū)的大小,或者strcpy中的源字符串長度是否大于目標(biāo)字符串長度等。
一旦緩沖區(qū)溢出、格式化字符串漏洞、堆內(nèi)存使用不當(dāng)?shù)嚷┒吹哪J揭?guī)則被滿足,即生成對應(yīng)格式的報告,以csv的格式展示,設(shè)計如表1所示。
表1 漏洞報告
在污點路徑顯示功能設(shè)計中,依據(jù)污點分析結(jié)果,以特定的格式生成對應(yīng)的污點路徑表格,以便后續(xù)給用戶展示,設(shè)計如表2所示。
表2 污點路徑報告
如表2所示,能看出選中的污點對象Obj2在main函數(shù)中流經(jīng)了b、c兩個變量,更加便于用戶著重分析污點數(shù)據(jù)的相關(guān)變更。最后將相關(guān)報告導(dǎo)出顯示完成所有的污點/漏洞分析。
本文進行系統(tǒng)測試的測試環(huán)境如表3所示。
表3 系統(tǒng)測試環(huán)境
本節(jié)將使用二進制程序漏洞檢測系統(tǒng)針對常見漏洞進行功能測試。在ubuntu20.04_x64平臺使用gcc_v9.4.0編譯代碼,使用命令為gcc ./test.c -o stackOverflow,得到程序stackOverflow,放入IDA Pro進行分析。
分析過程中在IDA Pro的輸出窗口會輸出過程數(shù)據(jù),如圖5所示。點擊查看報告,如圖6所示。
圖5 分析過程輸出圖
圖6 棧溢出污點報告圖
其中v4-localObj污點對象流經(jīng)了main.v4和vul.a1,符合程序的邏輯。切換分析模式,漏洞分析結(jié)果如圖7所示。
圖7 棧溢出漏洞報告圖
此外針對格式化字符串、二次釋放漏洞也進行了相關(guān)的測試,得到結(jié)果和棧溢出漏洞測試類似。
綜上所述,本節(jié)涉及的污點路徑探索測試、漏洞檢測測試,從整體上來說大致符合預(yù)期,能夠檢測出較為簡單的漏洞以及污點路徑。
本文選取Juliet測試集,就x86、x64兩種架構(gòu)與cwe_checker的測試結(jié)構(gòu)進行比較對照。此外,由于本文實現(xiàn)的系統(tǒng)是漏洞檢測原型系統(tǒng),在漏洞模式檢測上僅實現(xiàn)CWE-787、CWE-415、CWE-134三種CWE中指定函數(shù)造成的漏洞檢測,因此,本文從Juliet中隨機篩選了CWE-134中125個關(guān)于printf的格式化字符串漏洞,CWE-415中151個關(guān)于malloc-free的二次釋放漏洞,CWE-787中135個關(guān)于read函數(shù)的溢出寫漏洞測試用例進行測試。表4和表5展示的是x86和x64架構(gòu)下的三種CWE的檢測能力與cwe_checker的對比結(jié)果,其中縮寫英文對應(yīng)為VDT。本文實現(xiàn)的原型系統(tǒng)為vulDector,統(tǒng)計得到如圖8所示漏報率誤報率檢測對比統(tǒng)計圖。結(jié)果表明,本文設(shè)計的原型系統(tǒng)的性能測試結(jié)果在目前所支持的CWE類型上取得一定優(yōu)勢。
表4 x86架構(gòu)CWE檢測能力對比
表5 x64架構(gòu)CWE檢測能力對比
圖8 ds x86/x64架構(gòu)下的漏洞檢測漏報率/誤報率對比圖
本文主要研究了基于污點分析的二進制程序漏洞檢測系統(tǒng)設(shè)計與實現(xiàn),嘗試通過基于Hex-Rays反編譯的語法樹來進行指針分析,尋找漏洞以及實現(xiàn)污點路徑探索功能。
本文根據(jù)對目前二進制程序漏洞檢測系統(tǒng)的研究現(xiàn)狀的參考,首先確定了本系統(tǒng)的總體架構(gòu)、數(shù)據(jù)業(yè)務(wù)流程,根據(jù)系統(tǒng)分析設(shè)計,對基于污點分析的二進制程序漏洞檢測系統(tǒng)進行實現(xiàn)。在實現(xiàn)過程中,采用IDAPython語言進行程序編寫,使用了Hex-Rays提供的相關(guān)接口,以及用于指針/污點分析的Datalog引擎pyDatalog。在系統(tǒng)實現(xiàn)之后,依據(jù)系統(tǒng)測試相關(guān)原理,使用簡單的漏洞代碼編寫的二進制程序?qū)ο到y(tǒng)的各個功能模塊進行了測試。測試過程中,本系統(tǒng)實現(xiàn)的各個功能模塊能夠穩(wěn)定運行并投入使用,檢測出較為簡單的棧溢出、格式化字符串、二次釋放等漏洞。
本文具有以下創(chuàng)新點:
(1)在Hex-Rays反編譯結(jié)果的基礎(chǔ)上進行指針/污點分析的相關(guān)研究還不是很多,在此基礎(chǔ)上實現(xiàn)完整可用的基于污點分析的二進制程序漏洞檢測系統(tǒng)。
(2)不同于使用Datalog進行C源代碼形式的指針/污點分析,本文使用Datalog對二進制源程序的語法樹形式進行指針/污點分析研究。
(3)本系統(tǒng)實現(xiàn)的編程語言全部為Python腳本,具有高度的可擴展性、兼容性、可移植性等。
系統(tǒng)實用性方面仍舊存在的不足:
(1)本系統(tǒng)的測試用例都是在Linux平臺下使用GCC進行編譯生成的,對于其他平臺是否適用還有待進一步檢驗。
(2)由于本系統(tǒng)只是依據(jù)程序中的一些數(shù)據(jù)結(jié)構(gòu)以及函數(shù)調(diào)用等關(guān)系進行數(shù)據(jù)抽象,因此具備諸如循環(huán)、遞歸等復(fù)雜邏輯時的適用性有待檢驗。
(3)本系統(tǒng)暫時只實現(xiàn)了棧溢出漏洞、格式化字符串漏洞、二次釋放漏洞模式建立,適用范圍較小。后續(xù)將對基于污點分析的二進制程序漏洞檢測系統(tǒng)進行完善。