專利名稱:一種動態(tài)的二進制代碼測試用例生成方法
技術(shù)領(lǐng)域:
本發(fā)明涉及到一種動態(tài)的二進制代碼測試用例生成方法,可直接運行于Windows平臺,且不需要被測試程序的源碼,可在運行時生成新的輸入以探測新的路徑,適用于軟件測試、漏洞挖掘、逆向工程等領(lǐng)域。
背景技術(shù):
傳統(tǒng)軟件測試方法一般使用黑盒Fuzz測試,通過構(gòu)造一組隨機輸入傳遞給程序,直到程序崩潰。這種方法較盲目,既無法獲知哪些程序路徑已經(jīng)被執(zhí)行,也無法有導(dǎo)向性地構(gòu)造輸入,使程序可執(zhí)行到未被遍歷過的路徑。測試過程中的大部分時間都在重復(fù)執(zhí)行著同樣的路徑,使測試時間成本過高。源碼級的測試可以幫助程序員發(fā)現(xiàn)很多由于代碼風(fēng)格或錯誤的語法語義引起的BUG,但存在幾個缺點1)無法發(fā)現(xiàn)程序運行時的BUG ;2)在很多情況下,源碼并不是可及的;3)需對每一類程序設(shè)計語言分別考慮。 對于軟件測試、漏洞挖掘等領(lǐng)域,往往需要考慮代碼覆蓋問題,盡可能多地覆蓋二進制代碼的執(zhí)行路徑,可以提高發(fā)現(xiàn)程序代碼中BUG的可能性。然而,由于二進制代碼中的分支數(shù)量非常多,使獲取某一執(zhí)行路徑所對應(yīng)的輸入成為最難的研究問題之一。為解決這個問題,學(xué)術(shù)界提出了一種新的概念,符號執(zhí)行,即把輸入作為符號,然后通過靜態(tài)解釋源碼的形式來收集約束,遇到分支時,同時展開兩條路徑,繼續(xù)向下進行。符號執(zhí)行的誤報率極低,但是也存在一些弊端需要對未解釋的函數(shù)進行建模,狀態(tài)空間過大,效率較低。近年來,國外出現(xiàn)了一些基于動態(tài)執(zhí)行路徑,符號與具體執(zhí)行混合的方法所實現(xiàn)的工具,如 DART、CUTE、Sage、Catchconv、Fuzzgrind 等。其中,DART 與 CUTE 同宗,它們使用同樣的中間語言、插裝方式及求解方法。Catchconv與Fuzzgrind為開源工具,都使用Valgrind作為其插裝框架,只有微軟的Sage是運行在Windows上,但未發(fā)布出來。在Linux下,大多數(shù)軟件都為開源軟件,可以使用很多源代碼分析工具來檢查源碼中的錯誤,且在普通用戶操作系統(tǒng)中,Windows系統(tǒng)占絕大比例,且大多程序都是源碼無法獲取,因此,Windows平臺下的二進制代碼路徑探測的意義更為重大。本發(fā)明沿用這些工具的基本思想,即符號執(zhí)行與具體執(zhí)行結(jié)合的思路,采用了一種新的實現(xiàn)方案,實現(xiàn)動態(tài)的二進制代碼插裝工具收集二進制代碼的運行時信息,使用VEX中間語言描述路徑約束,使用STP定理證明器作為求解器,把這幾種現(xiàn)有的工具有機結(jié)合起來,再輔助以提出的路徑約束變異算法及同級分支路徑變異策略,實現(xiàn)了 Windows下動態(tài)的二進制代碼測試用例自動生成工具。
發(fā)明內(nèi)容
有鑒于此,本發(fā)明的目的就是提供一種動態(tài)的二進制代碼測試用例生成方法,它是在Windows平臺構(gòu)建一種可以自動化地探測二進制代碼執(zhí)行路徑的方案,通過對二進制代碼執(zhí)行過程的觀察,獲得其執(zhí)行的路徑約束。再使用求解器計算執(zhí)行其它路徑的輸入,從而達到提高路徑覆蓋率的目的。
為達到上述目的,本發(fā)明的技術(shù)方案是這樣實現(xiàn)的一種動態(tài)的二進制代碼測試用例生成方法,該方法的步驟包括步驟A.實現(xiàn)二進制代碼運行時的動態(tài)插裝框架??梢杂^察二進制的執(zhí)行過程;步驟B.根據(jù)動態(tài)插裝框架收集到的動態(tài)運行時信息,如指令、寄存器、內(nèi)存訪問等信息,把二進制代碼翻譯成中間語言。步驟C.根據(jù)動態(tài)插裝框架中記錄的輸入點信息,將輸入點作為符號,傳播與輸入點相關(guān)的執(zhí)行過程,在每個分支處收集路徑約束。步驟D.將收集到的路徑約束,通過變異路徑算法得到新的路徑約束,將該路徑約束轉(zhuǎn)化為求解器可識別的查詢語句。
步驟E.使用求解器計算新路徑約束中,輸入需滿足的條件,再借助動態(tài)插裝框架把新產(chǎn)生的輸入交給二進制代碼再次執(zhí)行。其中,步驟A中所述的二進制代碼為Windows平臺下的x86機器代碼;所述的二進制代碼的動態(tài)插裝框架,包括Al 在每條指令執(zhí)行完成后插裝;A2.在每個線程開始時插裝;A3.在每個動態(tài)鏈接庫被加載時插裝;A4.記錄每條指令的執(zhí)行上下文;A5.記錄每次內(nèi)存訪問信息;A6.記錄分支指令是否被執(zhí)行;其中,步驟B所述的中間語言中,包括三種存儲介質(zhì)Bll.臨時變量,在每個基本塊中臨時申請,用于實現(xiàn)靜態(tài)單賦值,為寄存器與內(nèi)存間的媒介;B12.寄存器,與機器指令中的寄存器相同,讀寫寄存器使用中間語言中的Get和Put操作完成;B13.內(nèi)存,內(nèi)存地址由常量或臨時變量表示,讀寫內(nèi)存使用中間語言中的LDle和STle操作完成;其中,步驟B中所述的中間語言由語句IRStmt組成,語句IRStmt包括B21. IMark語句,表示每個基本塊的入口標(biāo)志,其中包括該基本塊對應(yīng)機器指令的開始地址及該指令的字節(jié)數(shù);B22. Put語句,表示把臨時變量的值寫入寄存器;B23. Store語句,表示把臨時變量的值寫入內(nèi)存;B24. IRDirty語句,表示調(diào)用有副作用的函數(shù);B25. Exit語句,表示基本塊的出口;其中,步驟B中所述的中間語言由語句IRStmt組成,語句IRStmt由表達式IRExpr組成,表達式IRExpr包括B31. Get表達式,表示從寄存器中讀取值;B32. Tmp表達式,表示臨時變量;B33. Binop表達式,表示二元操作;B34. Unop表達式,表不一兀操作;
B35. Load表達式,表示從內(nèi)存中讀取值;B36. Const表達式,表示常量;B37. MuxOX 表達式,表不 if-then-else 語句;其中,步驟C所述的輸入點包括三種情況命令行參數(shù)。程序運行時傳遞的參數(shù),如控制臺程序啟動時傳遞的參數(shù)。文件類輸入。表示通過ReadFile讀取文件內(nèi)容,作為輸入。網(wǎng)絡(luò)輸入。表示通過Recv、RecvFrom讀取網(wǎng)絡(luò)中的內(nèi)容,作為輸入。其中,步驟C所述的將輸入點作為符號,即傳播符號方法是在中間語言上進行,需要考慮以下幾種情況
Cl. Put操作,檢查賦值給寄存器的臨時變量是否依賴于輸入;C2.賦值給臨時變量時,左值需要考慮以下幾種情況C21.從臨時變量中讀,檢查該臨時變量是否依賴于輸入;C22.從內(nèi)存中讀,檢查該內(nèi)存中的值是否依賴于輸入;C23.從寄存器中讀,檢查該寄存器是否依賴于輸入;C24. 一元操作與二元操作,檢查操作數(shù)是否依賴于輸入;C3. Store操作,檢查寫入內(nèi)存的臨時變量是否依賴于輸入;其中,步驟D所述將收集到的路徑約束,通過變異路徑算法得到新的路徑約束,包括二元操作,一元操作、位移操作,有符號擴展、無符號擴展,比較操作以及是否跳轉(zhuǎn)標(biāo)志。其中,步驟D所述求解器可識別的查詢語句包括以下幾種元素Dl.BITVECTOR(X)類型的變量聲明,表示X個布爾變量的數(shù)組。聲明需混合以ASSERT語句,每個ASSERT接收包括已聲明的變量的表達式作為參數(shù);D2.算術(shù)謂詞和比較操作的變型。如BVLT是一個無符號的小于比較謂詞,而BVSLT是有符號的小于比較;D3.比特向量索引的比特向量的數(shù)組。為使用這樣的數(shù)組,需聲明一個新的ARRAYBITVECTOR (X) OF BITVECTOR (Y)類型的變量,X表示數(shù)組地址的大小和每個項是Y位的比特向量。STP允許數(shù)組變量索引,如某長度的比特向量或長比特向量的子集。這樣可簡單地表示從一個符號內(nèi)存地址讀取值;優(yōu)點及功效本發(fā)明一種動態(tài)的二進制代碼測試用例生成方法,它是在Windows平臺構(gòu)建一種可以自動化地探測二進制代碼執(zhí)行路徑的方案,通過對二進制代碼執(zhí)行過程的觀察,獲得其執(zhí)行的路徑約束。再使用求解器計算執(zhí)行其它路徑的輸入,從而實現(xiàn)了Windows下動態(tài)的二進制代碼測試用例自動生成工具,達到提高路徑覆蓋率的目的。
圖I為二進制代碼動態(tài)生成測試用例流程示意2為二進制代碼中同級分支示意圖
具體實施例方式下面結(jié)合附圖及本發(fā)明的實施例對本發(fā)明的方法作進一步詳細的說明。本發(fā)明的基本思想為實現(xiàn)二進制代碼動態(tài)插裝工具,收集二進制代碼執(zhí)行的動態(tài)信息,將這些動態(tài)信息轉(zhuǎn)化為VEX中間語言,從輸入點引入符號,傳播符號到達每個分支,提取出每個分支的路徑約束。使用路徑變異算法生成新的路徑約束,使用求解器計算出滿足該路徑約束的輸入向量,然后把輸入向量傳遞給二進制程序進行下一輪執(zhí)行,直到不再產(chǎn)生新的路徑為止。圖I為本發(fā)明一種動態(tài)的二進制代碼測試用例生成方法流程示意圖;如圖I所示,該方法包括如下步驟步驟A :使用動態(tài)二進制代碼插裝工具插裝二進制代碼的執(zhí)行,收集二進制代碼執(zhí)行中產(chǎn)生的動態(tài)信息;這里的動態(tài)信息包括寄存器的值、內(nèi)存讀寫地址、分支是否被執(zhí)行等信息,通過動態(tài)二進制代碼插裝工具可以實現(xiàn)對以上信息的監(jiān)控。步驟B :把二進制代碼執(zhí)行的指令蹤跡翻譯成中間語言;
這里的中間語言與靜態(tài)產(chǎn)生的中間語言并不相同,靜態(tài)下翻譯的中間語言遇到分支指令時轉(zhuǎn)化為一條x86 Calculate Condition語句,表示不能確定是否跳轉(zhuǎn)。而動態(tài)生成的中間語言,跳轉(zhuǎn)指令已經(jīng)得到確定,或者跳轉(zhuǎn)、或者順序執(zhí)行。步驟C :把輸入點作為符號,在中間語言上傳播符號,在分支指令處收集依賴于輸入的路徑約束;根據(jù)前面所述,這里考慮了三種輸入,分別的命令行參數(shù),文件和網(wǎng)絡(luò)接口。命令行參數(shù)的地址可以直接獲得,文件和網(wǎng)絡(luò)接口需要攔截系統(tǒng)調(diào)用,這一過程在插裝框架里完成。步驟D :根據(jù)收集的路徑約束,使用變異路徑算法生成新的路徑約束,把新的路徑約束轉(zhuǎn)化為求解器可識別的查詢語句;這里,收集的路徑約束中包括路徑字符串,(Oll)*,其中0表示在分支指令處未跳轉(zhuǎn),I表示在分支指令處已跳轉(zhuǎn)。為描述變異路徑算法,引入以下符號Exec ():表示執(zhí)行程序過程,參數(shù)為程序執(zhí)行的輸入,返回當(dāng)前程序執(zhí)行路徑約束的集合;SolveO 表示求解過程,參數(shù)為路徑約束的集合,返回滿足該路徑約束的輸入集合;Vari ():表示路徑變異過程,參數(shù)為上一次程序執(zhí)行收集的路徑約束,返回一條新的路徑約束;變異路徑的過程如下111. .々# /(/;,…,/;,) B /f,/)2,/.;, ■”/V,其中 Pi (I ^ i ^n)表示第 i 個
分支上的路徑約束,Pn’表示將Pn取反;112. .S7m’e(/HG,…,/:)1.4/!,/2,/.;, ,&,其中 id 彡 i 彡 p)表示根據(jù)變異
后的路徑約束計算出的新的輸入;113. J^xeciIlJ2J3,...,Ip) I], IW.」)"'> 0),表示基于
新輸入的程序執(zhí)行,得到新的路徑約束,再繼續(xù)步驟ill ;為使一次符號執(zhí)行中可以得到更多的新路徑約束,從而減少符號執(zhí)行的次數(shù),本方法中使用一種同級分支路徑變異策略,如圖2所示,BRl與BR4為一級分支,BR2與BR3為二級分支,對同級分支的路徑,可以直接取反生成新的路徑,如BRl與BR4的路徑可以生成(11、10、01、00)四條新路徑約束,而不必進行四次符號執(zhí)行。步驟E:使用求解器計算滿足新路徑的輸入,將該輸入交給程序再次執(zhí)行,進入一輪輪迭代過程,直到不再產(chǎn)生新路徑為止;綜上所述,自動化地收集二進制代碼的路徑約束,并有導(dǎo)向性地生成可以探測新 路徑的輸入用例為本發(fā)明的核心,給定二進制代碼后,根據(jù)不斷地迭代執(zhí)行、收集、處理過程,可以生成不同路徑所對應(yīng)的輸入用例,能達到提高代碼覆蓋率的目的,可用于Windows平臺二進制代碼的測試和漏洞檢測。
權(quán)利要求
1.一種動態(tài)的二進制代碼測試用例生成方法,其特征在于該方法的具體步驟如下 步驟A.實現(xiàn)二進制代碼運行時的動態(tài)插裝框架,觀察二進制的執(zhí)行過程; 步驟B.根據(jù)動態(tài)插裝框架收集到的動態(tài)運行時信息,如指令、寄存器、內(nèi)存訪問信息,把二進制代碼翻譯成中間語言; 步驟C.根據(jù)動態(tài)插裝框架中記錄的輸入點信息,將輸入點作為符號,傳播與輸入點相關(guān)的執(zhí)行過程,在每個分支處收集路徑約束; 步驟D.將收集到的路徑約束,通過變異路徑算法得到新的路徑約束,將該路徑約束轉(zhuǎn)化為求解器可識別的查詢語句; 步驟E.使用求解器計算新路徑約束中,輸入需滿足的條件,再借助動態(tài)插裝框架把新產(chǎn)生的輸入交給二進制代碼再次執(zhí)行。
2.根據(jù)權(quán)利要求I所述的一種動態(tài)的二進制代碼測試用例生成方法,其特征在于步驟A中所述的二進制代碼為Windows平臺下的x86機器代碼;所述的二進制代碼的動態(tài)插裝框架,包括 Al.在每條指令執(zhí)行完成后插裝; A2.在每個線程開始時插裝; A3.在每個動態(tài)鏈接庫被加載時插裝; A4.記錄每條指令的執(zhí)行上下文; A5.記錄每次內(nèi)存訪問信息; A6.記錄分支指令是否被執(zhí)行。
3.根據(jù)權(quán)利要求I所述的一種動態(tài)的二進制代碼測試用例生成方法,其特征在于步驟B所述的中間語言中,包括三種存儲介質(zhì) Bll.臨時變量,在每個基本塊中臨時申請,用于實現(xiàn)靜態(tài)單賦值,為寄存器與內(nèi)存間的媒介; B12.寄存器,與機器指令中的寄存器相同,讀寫寄存器使用中間語言中的Get和Put操作完成; B13.內(nèi)存,內(nèi)存地址由常量或臨時變量表示,讀寫內(nèi)存使用中間語言中的LDI e和STI e操作完成。
4.根據(jù)權(quán)利要求I所述的一種動態(tài)的二進制代碼測試用例生成方法,其特征在于步驟B中所述的中間語言由語句IRStmt組成,語句IRStmt包括 B21. IMark語句,表示每個基本塊的入口標(biāo)志,其中包括該基本塊對應(yīng)機器指令的開始地址及該指令的字節(jié)數(shù); B22. Put語句,表示把臨時變量的值寫入寄存器; B23. Store語句,表示把臨時變量的值寫入內(nèi)存; B24. IRDirty語句,表示調(diào)用有副作用的函數(shù); B25. Exit語句,表示基本塊的出口。
5.根據(jù)權(quán)利要求4所述的一種動態(tài)的二進制代碼測試用例生成方法,其特征在于所述的語句IRStmt由表達式IRExpr組成,表達式IRExpr包括B31. Get表達式,表示從寄存器中讀取值; B32. Tmp表達式,表示臨時變量;B33. Binop表達式,表示二元操作; B34. Unop表達式,表不一兀操作; B35. Load表達式,表示從內(nèi)存中讀取值; B36. Const表達式,表示常量; B37. MuxOX 表達式,表不 if-then-else 語句。
6.根據(jù)權(quán)利要求I所述的一種動態(tài)的二進制代碼測試用例生成方法,其特征在于步驟C所述的輸入點包括三種情況 命令行參數(shù)程序運行時傳遞的參數(shù),如控制臺程序啟動時傳遞的參數(shù); 文件類輸入表示通過ReadFile讀取文件內(nèi)容,作為輸入; 網(wǎng)絡(luò)輸入表示通過Recv、RecvFrom讀取網(wǎng)絡(luò)中的內(nèi)容,作為輸入。
7.根據(jù)權(quán)利要求I所述的一種動態(tài)的二進制代碼測試用例生成方法,其特征在于步驟C所述的將輸入點作為符號,即傳播符號方法是在中間語言上進行,需要考慮以下幾種情況 Cl. Put操作,檢查賦值給寄存器的臨時變量是否依賴于輸入; C2.賦值給臨時變量時,左值需要考慮以下幾種情況 C21.從臨時變量中讀,檢查該臨時變量是否依賴于輸入; C22.從內(nèi)存中讀,檢查該內(nèi)存中的值是否依賴于輸入; C23.從寄存器中讀,檢查該寄存器是否依賴于輸入; C24. 一元操作與二元操作,檢查操作數(shù)是否依賴于輸入; C3. Store操作,檢查寫入內(nèi)存的臨時變量是否依賴于輸入。
8.根據(jù)權(quán)利要求I所述的一種動態(tài)的二進制代碼測試用例生成方法,其特征在于步驟D所述將收集到的路徑約束,通過變異路徑算法得到新的路徑約束,包括二元操作,一元操作、位移操作,有符號擴展、無符號擴展,比較操作以及是否跳轉(zhuǎn)標(biāo)志。
9.根據(jù)權(quán)利要求I所述的一種動態(tài)的二進制代碼測試用例生成方法,其特征在于步驟D所述求解器可識別的查詢語句包括以下幾種元素 Dl. BITVECTOR (X)類型的變量聲明,表示X個布爾變量的數(shù)組;聲明需混合以ASSERT語句,每個ASSERT接收包括已聲明的變量的表達式作為參數(shù); D2.算術(shù)謂詞和比較操作的變型JnBVLT是一個無符號的小于比較謂詞,而BVSLT是有符號的小于比較; D3.比特向量索引的比特向量的數(shù)組;為使用這樣的數(shù)組,需聲明一個新的ARRAYBI TVECTOR (X) OF BI TVECTOR (Y)類型的變量,X表示數(shù)組地址的大小和每個項是Y位的比特向量;STP允許數(shù)組變量索引,如某長度的比特向量或長比特向量的子集;這樣就簡單地表示從一個符號內(nèi)存地址讀取值。
全文摘要
本發(fā)明公開了一種動態(tài)的二進制代碼測試用例生成方法。實現(xiàn)動態(tài)的二進制插裝工具,可收集二進制代碼執(zhí)行過程中,寄存器、內(nèi)存、線程、系統(tǒng)調(diào)用、庫加載等動態(tài)上下文信息,將此類信息傳送到二進制代碼翻譯組件中,轉(zhuǎn)化為一種中間語言,并在此中間語言上進行符號執(zhí)行,傳播符號輸入,收集依賴于輸入的路徑約束。然后把此路徑約束輸入到路徑生成組件中,提出一種新的同級分支路徑變異算法及策略,在每次符號執(zhí)行后盡可能多地生成新的路徑約束,再使用定理證明器來求解新的路徑約束,得到滿足該路徑約束的新輸入,把新輸入傳送給二進制代碼進行再一次具體執(zhí)行,不斷循環(huán)從新的執(zhí)行中得到新的路徑約束,生成新的輸入,從而提高二進制代碼覆蓋率。
文檔編號G06F11/36GK102799529SQ20121024349
公開日2012年11月28日 申請日期2012年7月13日 優(yōu)先權(quán)日2012年7月13日
發(fā)明者李舟軍, 馬金鑫, 忽朝儉, 章張鍇 申請人:北京航空航天大學(xué)