GREYONE Data Flow Sensitive Fuzzing

目錄

 

Abstract

Introduction

1.1questions to address

1.2 our solution

1.3 result

2 design of greyone

2.1 Fuzzer-driven Taint Inference

2.1.1 Taint inference

2.1.2 Comparison with Traditional Taint Analysis.

2.1.3 Identify Direct Copies of Inputs.              

2.2 Taint-Guided Mutation

2.2.1 Prioritize Bytes to Mutate

2.2.3 Determine Where and How to Mutate

2.3符合性導向的進化

2.3.1符合性計算

2.3.2 Conformance-Guided Seed Updating

2.3.3 On-the-fly Mutation Rebase

2.3.4符合性指導下的種子選擇

3 Implementation

3.1 Modularized Framework

3.2 Static Analysis and Instrumentation.

6 Related Work

6.1 Taint Inference

6.2 Seed Mutation

6.3 Seed Updating and Selection

6.4 Performance Optimization


Abstract

數據流分析(例如,動態污點分析)已經被證明有助於指導fuzzer探索難以訪問的代碼並發現漏洞。然而,傳統的污點分析是勞動密集型的、不準確的、緩慢的,影響了模糊化的效率。除了污點,很少使用數據流特性。

本文提出了一種數據流敏感的模糊化解決方案greyone,首先利用經典的特徵污點來指導模糊化。採用一種輕量級的、合理的模糊驅動的污點推斷(fti)方法,通過在模糊過程中改變輸入字節的同時監測變量的值變化來推斷變量的污點。針對這個問題,我們提出了一個新的輸入優先級模型來確定要探索的分支、要變異的字節以及如何變異。此外,我們使用另一個數據流特徵約束符合性,即污染變量到未觸及分支中預期值的距離,來調整模糊化的演化方向。

我們實現了一個greyone的原型,並在LAVA數據集和19個真實世界程序上對其進行了評估。結果表明,在代碼覆蓋率和漏洞發現方面,它都優於各種最新的模糊器。在lava數據集中,greyone發現了所有列出的bug,還有336個未列出。在現實世界的程序中,Greyone平均發現了2.12倍的獨特程序路徑和3.09倍的獨特錯誤比最先進的進化模糊器,包括AFL,Vuzzer,Collafl,Angora和Honggfuzz,而且,Greyone平均發現了1.2倍的獨特程序路徑和1.52倍的獨特錯誤比最先進的符號解釋輔助模糊器Qsym。共發現105個新的安全漏洞,其中41個已被CVE確認。

Introduction

基於進化的變異的模糊算法(如afl[44])已經成爲當前最流行的漏洞發現方法之一,並得到了廣泛的應用和研究。這類模糊器的核心任務是確定進化方向,以及在何處以及如何變異種子輸入,以探索難以訪問的代碼,並滿足複雜的數據流約束以觸發潛在的漏洞。一個常見的解決方案是利用符號執行來解決控制流約束,並幫助fuzzer探索代碼,如driller[37]、qsym[43]和diggfuzz[45]所提出的。然而,符號執行太重,無法擴展到大型應用程序,也無法解決許多複雜的約束,如單向函數。研究人員還試圖通過預測要變異的字節和要採取的變異操作,通過深度學習和強化學習來改進模糊器。然而,它們仍處於早期階段,改進並不顯著。

相反,數據流分析1(例如,動態污點分析)被證明對指導模糊化是有用的。TaintScope[40]利用它來定位校驗和。vuzzer[30]使用它來標識分支指令中使用的字節和值。angora[10]使用它來繪製與路徑約束相關的輸入字節的形狀。這些解決方案利用污點來確定在哪裏以及如何以不同的方式變異,並在一些應用程序中顯示出良好的性能。

1.1questions to address

然而,傳統的動態污點分析方法存在一些侷限性。首先,這是勞動密集型的,需要大量的人工勞動。例如,vuzzer[30]最初只支持x86平臺。通常,這些解決方案必須使用自定義污染傳播規則以本機或中間表示形式解釋每個指令。他們還必須爲外部函數調用或系統調用構建污點模型。其次,這是不準確的。例如,一些受污染的數據值可能會影響控制流,從而進一步影響其他數據,形成隱式數據流。如果隱式流被忽略,則會導致欠污染;如果這些流都被計算在內,則會導致過度污染[19]。最後,它非常慢(通常是管理費用的幾倍),使得模糊效率很低。這些嚴重限制了動態污染分析在模糊控制中的應用和效率。因此,首先要解決的研究問題是:rq1:如何爲有效的模糊化執行輕量級和精確的污染分析?

使用推斷的污點屬性,Vuzzer[30]對分支指令中使用的輸入字節進行變異,並不精確地用期望值(例如,幻數)替換它們。redqueen[4]進一步標識了輸入的所有直接副本,即直接用於分支約束的輸入字節(如幻數和校驗和),並用期望值替換它們。然而,它們既不能解決與輸入的間接副本(即在分支約束中轉換和間接使用的輸入字節)相關的分支約束,也不能確定要探索的分支和要變異的字節的優先級。因此,需要解決的第二個研究問題是:rq2:如何有效地引導帶有污染的突變?

現有的進化fuzzer一般演變爲增加代碼覆蓋率。例如,afl[44]將發現新代碼的測試用例添加到seed隊列中,並從隊列中一次選擇一個進行變異。許多其他的解決方案,如aflfast[6]和collafl[14],被提出來進一步改進選擇種子的方式,加速進化速度。然而,他們只考慮控制流特性,而不考慮數據流特性,例如污染屬性或約束符合性,並且可能在變異期間浪費能量來探索難以到達的分支。因此,需要解決的第三個研究問題是:rq3:如何根據數據流特性調整模糊器的進化方向?

1.2 our solution

爲了解決上述問題,我們提出了一種新的數據流敏感模糊解greyone。

fuzzer驅動污點推斷(fti)。我們首先提出fti通過pilot的fuzzer階段來推斷變量的污染,在此階段,我們系統地改變每個輸入字節(一次一個)並監視變量的值。如果變量的值在輸入字節發生變化時發生變化,我們可以推斷前者受到了污染,並依賴於後者。

這個推論是合理的,即沒有過度污染的問題。它還對由隱式流或外部調用引起的不足污染問題免疫。實驗表明,fti比傳統的污染分析更準確,例如,能夠找到2到4倍的依賴關係(沒有假陽性)。此外,它避免了編寫污染傳播規則的勞動密集型工作,並且在運行時非常快速。這個輕量級的、可靠的解決方案可以擴展到大型程序,併爲除模糊之外的其他應用程序場景提供支持。

污染導向突變。輸入字節對代碼覆蓋率的貢獻不同。我們利用fti提供的污點對輸入字節進行排序。更具體地說,我們優先考慮影響更多未觸及分支得的輸入字節的變異,並使得依賴於更高優先級輸入字節的未觸及分支優先。當探索一個分支時,我們按照優先級順序改變它的依賴輸入字節,精確地用期望值(和較小的變化)替換輸入的直接副本。

符合導向的進化。許多fuzzer(例如afl)使用控制流特性(例如代碼覆蓋率)來指導進化。爲了有效地探索難以觸及的分支(例如,那些與輸入的indirect copies相關的分支),我們建議使用互補的數據流特徵來調整演化方向。注意,對於未觸及分支中使用的每個受污染變量,我們需要翻轉一些位以匹配預期值。所需的工作量與符合約束有關,即受污染變量與未觸及分支中預期值的距離。

我們使用這個數據流特性來調整模糊器的進化方向。首先,在種子隊列中加入符合性較高的測試用例,使模糊器逐步提高整體符合性,最終滿足非觸及分支的約束。然後,對一符合較高的種子進行優先排序,從隊列中選擇變異種子,加速新分支的探索。這種進化可以更快地滿足約束條件,就像Angora使用的梯度下降[10]。但它可以避免陷入局部極小值,帶來長期穩定的改善。此外,我們將正在進行的突變重新定位到新的種子上,並在運行中獲得更高的符合性。實驗表明,該方法顯著提高了突變效率。

1.3 result

我們實現了greyone的原型,並在lava-m數據集和19個開源應用程序上對其進行了評估。

我們的污染分析引擎fti優於經典的污染分析解決方案dfsan[2]。平均而言,它會發現1.3倍多的未觸及分支受到污染(即,取決於輸入字節),並在模糊期間生成1倍多的不同路徑。

greyone在代碼覆蓋率和漏洞發現方面都優於6個最新的進化模糊器,包括afl和collafl[14]。在lava數據集中,greyone發現了所有列出的bug,還有336個未列出的bug。在現實世界的應用中,greyone發現了2.12倍的不同路徑、1.53倍的新邊、6倍的不同崩潰和3.09倍的錯誤比第二好的fuzzer。此外,greyone在繞過複雜的程序約束方面表現出了非常好的性能,甚至優於最先進的符號執行輔助fuzzer qsym[43]。

在實際應用中,greyone發現的不同路徑是qsym的1.2倍,新邊是qsym的1.12倍,不同崩潰是qsym的2.15倍,錯誤是qsym的1.52倍。Greyone總共在這些應用程序中發現了105個未知漏洞。在向上遊供應商報告後,我們瞭解到其中25家供應商是已知的(但不是公開的)。其餘80個bug中,有41個被cve證實。總之,我們做出了以下貢獻:

我們提出了一種污染導向突變策略,能夠優先考慮要探索的分支和要突變的輸入字節,並確定如何(準確地)突變。

我們提出了一個新的符合性導向的演化解決方案來調整模糊化的方向,同時考慮到數據流的特性,包括污染屬性和約束符合性。

我們實現了一個原型greyone,並在19個廣泛測試的開源應用程序上對其進行了評估,結果表明它優於各種最新的fuzzer。

我們在19個應用程序中發現105個未知漏洞,並幫助供應商改進產品。

2 design of greyone

如圖1所示,Greyone的整個工作流程與AFL類似,包括種子生成/更新、種子選擇、種子變異和測試/跟蹤等步驟。

首先,我們在模糊循環中引入一個新的步驟,即fti,來推斷變量的污點。通過對輸入種子執行字節級變異並對其進行測試,我們進行了一次pilot fuzzer。在pilot fuzzer過程中,我們監控程序變量的值變化。一旦變量的值發生變化,我們就可以推斷它受到了污染,並且依賴於變化的輸入字節。此外,我們還可以識別所有使用輸入直接副本的受污染變量。

其次,利用fti提供的污染屬性,進一步引導模糊算子以更有效的方式對種子進行變異。我們對哪些輸入字節要變異,哪些分支要探索排序。此外,我們還確定如何改變輸入字節,包括輸入direct和indirect copies。

最後,我們利用符合性引導進化來調整模糊方向。除了代碼覆蓋率,我們在測試過程中跟蹤受污染變量的約束符合性,並在種子隊列中添加具有較高符合性的測試用例,使得模糊器逐漸增加符合性併到達未受影響的分支。然後,我們對符合性較高的種子進行優先級排序,以從隊列中進行選擇,從而加速進化。此外,一旦我們發現一個新的種子具有更高的符合性,我們就將正在進行的突變重新定位到這個新的種子上在運行中,從而提高突變效率。

2.1 Fuzzer-driven Taint Inference

如[10,30]所示,污點分析可以引導fuzzer走向有效的突變,並幫助探索難以觸及的分支。然而,傳統的解決方案是勞動密集型的、緩慢的和不準確的。Greyone引入了一個輕量級且可靠的解決方案,即模糊驅動污點推斷(FTI)。

直覺。如果一個變量的值在我們改變一個輸入字節後發生變化,我們可以推斷前者依賴於後者,無論是顯式的還是隱式的。此外,更改此輸入字節可能會更改使用此變量的分支的約束,從而導致新的分支探索。

Fti關聯規則。假設我們有一個程序變量var(在給定的指令行)和一個種子輸入s,另一個輸入s[i]是通過改變輸入s的第i個字節得到的,當給定輸入s時,讓v(var;s)是var的值。如果以下條件成立,我們聲明變量var取決於輸入s的第i個字節。

此外,如果分支指令br的任何一個操作數變量依賴於輸入s的第i字節,則我們聲明此分支br依賴於此輸入字節。換句話說,如果從輸入字節到分支的數據流不滿足非關聯規則[16],則後者依賴於前者。與傳統的指令級污染分析(如taintinclude[46])不同,此規則捕獲高級依賴項,並且更準確。如後文所述,它具有較少的誤報(即過度污染)和假陰性(即污染不足)。

Algorithm 1 Fuzzing-driven Taint Inference.

Input: seed

Output: {br,taint[seed]|br∈branches(P)}

1: // Target program is instrumented to collect information, as P'

2: State = Execute(P';seed)

3: for each candidate mutation method Opr do

4:   for each available mutation operand Opd do

5:     for each position pos in the seed do

6:       seed’= Mutate(seed;Opr;Opd; pos)

7:       State’= Execute(P';seed’)

8:       for br∈uncovered_branches(State) do

9:         for var∈br do

10:           if State(var) ≠State’(var) then

11:               br:taint[seed]∪= {pos}

12: end if

13: end for

14: end for

15: end for

16: end for

17: end for

2.1.1 Taint inference

根據上述直覺和干擾規則,fti在一個piot模糊階段推斷污染屬性,該階段可與afl的確定性模糊階段集成,具體步驟如下,如算法1所示。

字節級變異。我們使用一組預定義的變異規則(例如,單比特翻轉、多比特翻轉和算術運算),一次對種子輸入進行一個字節的變異。對於每個種子輸入和每個輸入偏移位置,可以用這種方式導出一組新的測試用例blm(s,pos)。注意,由於以下原因,我們不會同時改變多個字節。首先,如果多個字節發生變異,導致污染不足或污染過度,我們無法準確確定哪個字節負責潛在的值更改。其次,單字節變異產生的測試用例更少,帶來的性能開銷更少。

可變值監控。然後,我們將生成的測試用例提供給測試,並在測試期間監視程序變量的值。爲了支持監控,我們使用特殊的值跟蹤代碼對目標應用程序進行檢測。注意,我們可以用這種方式監視所有程序變量。但是,爲了模糊化的目的,我們只監視路徑約束中使用的變量。首先,監控更少的變量要快得多。第二,只有這些變量纔會影響路徑探索,而僅僅爲了探索所有分支而對它們進行監控就足夠了。

污點推斷。最後,在測試了每組測試用例blm(s,pos)之後,我們檢查路徑約束中使用的每個變量的值是否保持完整。如果變量var的值發生變化,我們可以推斷var受到了污染,並且依賴於輸入種子s的pos-th字節。

清單1:fti的激勵示例

/ / magic number : direct copy of input [0:8] vs . constant

2 i f ( u64 ( input ) == u64 ( "MAGICHDR" ) ) {

bug1 ( ) ;

4 }

5 / / checksum : direct copy input [8:16] vs . computed val

6 i f(u64 ( input +8) == sum( input +16 , len-16) ) {

7       bug2 ( ) ;

8 }

9 / / length : direct copy of input [16:18] vs . constant

10 i f ( u16 ( input +16) > l e n ) ) { bug3 ( ) ; }

11 / / indirect copy of input [18:20]

12 i f ( foo ( u16 ( input +18) ) = = . . . ) { bug4 ( ) ; }

13 / / implicit dependency : var 1 depends on input[20:24]

14 i f ( u32 (input +20) == . . . ) {

15         var 1 = . . . ;

16 }

17 / / var 1 may change if input [ 2 0 : 2 4 ] change s

18 / / FTI infers : var 1 depends on input [ 2 0 : 2 4 ]

19 i f ( v a r1 == . . . ) { bug5 ( ) ; }

 

如清單1所示,它是從redqueen[4]擴展而來,當我們對輸入的第20、21、22或23個字節進行變異時,我們可以在第20行的變化處檢測分支中使用的變量var1的值。因此,var1依賴於這四個字節。

2.1.2 Comparison with Traditional Taint Analysis.

與傳統的污染分析方法相比,fti方法所需的人工操作更少,而且更輕巧、準確。

體力勞動。傳統的污染分析(如[20])需要勞動密集型的工作。一般來說,每個指令/語句都必須使用自定義指令特定的污染傳播規則進行解釋,或者提升/轉換爲中間表示形式,然後使用一般的污染傳播規則進行分析。fti是獨立於體系結構的,不需要額外的努力就可以移植到新的平臺上。速度。快速道掃描速度很快。首先,它基於靜態代碼檢測,而不是動態二進制檢測。其次,它只監視路徑約束中使用的變量的值,而不是所有的程序變量。第三,它不需要用自定義規則解釋個別指令。

速度。快速道掃描速度很快。首先,它基於靜態代碼檢測,而不是動態二進制檢測。其次,它只監視路徑約束中使用的變量的值,而不是所有的程序變量。第三,它不需要用自定義規則解釋個別指令。

準確度。fti比傳統的污染分析方法更準確。其推理規則是合理的。如果一個變量被報告依賴於一個特定的輸入字節,那麼它很可能是真的。換句話說,它沒有過度污染的問題。它也有更少的污染問題。實際上,大多數未受污染的問題都是由無處不在的隱式數據流和外部函數或系統調用的丟失引起的。fti對這些病例免疫。然而,由於字節級變異導致的不完全模糊,fti可能仍然存在不足污染問題。圖2展示了FTI的工作原理。與傳統的動態污點分析不同,fti可以通過較少的努力來提高精度,而傳統的動態污點分析只關注指令,存在着過度污點和不足污點的問題。

正面比較。值得注意的是,最近的幾部作品都有類似的想法或類似的結果。taintinclude[46]可以爲每個指令推斷污染傳播規則,而無需手動操作。但由於每條指令都有變異,因此在污點規則推斷階段速度非常慢。profuzzer[42]每次也會改變一個輸入字節。但是它監視覆蓋範圍的變化而不是值的變化,無法推斷污染依賴性。mutaflow[26]監視sink api中的更改,並可以判斷參數是否被污染。但它關注的是api而不是變量,無法爲變量提供精確的污染信息。此外,它缺乏系統的測試,例如fti進行的polit模糊測試,因此有更多的未受污染的問題。

2.1.3 Identify Direct Copies of Inputs.              

通常,一些輸入字節將直接複製到變量中,並與分支指令中的預期常量或計算值進行比較,如清單1中的第2行(幻數)、第6行(校驗和)和第10行(長度檢查)所示。這些輸入字節應替換爲分支中預期的精確值(或類似於±1的微小變化),以繞過難以到達的路徑約束。

fti可以有效地識別輸入的所有直接拷貝。對於分支指令中使用的每個受污染變量,我們可以將其與依賴輸入字節相匹配。如果它們的值相等,我們將變量報告爲輸入的直接副本。否則,我們將其報告爲輸入的間接副本。

2.2 Taint-Guided Mutation

基於變異的fuzzer將以某種方式變異種子輸入並生成新的測試用例,以探索新代碼並觸發潛在的漏洞。Greyone利用FTI提供的污點來確定哪些字節要變異,哪些分支要探索,以及確定如何變異。

2.2.1 Prioritize Bytes to Mutate

如[29]所述,並非所有的輸入字節都平等。一些字節應該優先進行變異,以獲得更好的模糊效果。我們認爲,如果一個輸入字節可以影響更多未觸及的分支,那麼它應該優先於其他輸入字節,因爲改變這個輸入字節更可能觸發未觸及的分支,並觸發更復雜的程序行爲,因爲更多的分支狀態已經改變。如圖3所示,種子輸入s的偏移位置處的每個輸入字節可能影響多個變量,然後影響多個分支,其中一些分支未被任何測試用例探索。我們定義一個字節的權重爲依賴於這個字節的未觸及分支的計數,如下所示。

其中,如果到目前爲止任何測試用例都沒有探索分支br,則isuntouched返回1,否則返回0。根據fti,如果分支br依賴於pos-th輸入字節,則函數depon返回1,否則返回0。

2.2.2 Prioritize Branches to Explore

如圖3所示,一個程序路徑可能有多個未觸及的相鄰分支。類似地,爲了獲得更好的模糊化結果,一些未觸及的分支應該優先考慮,我們認爲,依賴於更高權重輸入字節的未觸及分支應該優先於其他未觸及分支。如果一個未觸及的分支依賴於更多的高權重輸入字節,爲了探索這個分支,我們將對其依賴的輸入字節進行變異。如上所述,對這些高權重輸入字節進行變異更可能觸發未觸及的分支(包括與要探索的分支不同的分支)。因此,對於種子s,我們將未觸及的分支br在相應路徑中的權重作爲其所有相關輸入字節的權重之和進行計算,如下所示。

2.2.3 Determine Where and How to Mutate

利用輸入字節和未探測分支的權重,可以進一步確定種子變異策略。

在哪裏變異?給定一個種子和它運行的程序路徑,我們將按照方程3的分支權重降序,沿着該路徑逐個探索未受影響的相鄰分支。在探索一個特定的未觸及的鄰居分支時,我們將根據等式2,按照字節權重的降序,對其相關的輸入字節逐個進行變異。

在探索一個特定的未觸及的鄰居分支時,我們將根據等式2,按照字節權重的降序,對其相關的輸入字節逐個進行變異。

如何變異輸入的直接副本?如上所述,輸入的直接副本應與未觸及分支中預期的值匹配。因此,在變異過程中,我們將輸入字節的直接副本替換爲精確的期望值(對於幻數和校驗和等)和具有微小變化的值(例如,長度檢查±1)。

剩下的核心問題是如何得到期望值。有兩種情況。如果需要一個常量(如幻數),我們用fti記錄這個常量。如果需要運行時計算值(例如校驗和),我們首先將格式錯誤的輸入饋送到測試中,然後使用fti獲取所需的運行時值。然後我們使用記錄的值(和微小的變化)來修補依賴的輸入字節。

注意,redqueen[4]也可以改變輸入字節的直接副本。與greyone不同,redqueen無法精確定位從屬字節的確切位置。它必須對種子進行數百次變異,才能得到一個具有更高熵的彩色版本,這條路徑是相同的。再次測試着色版本,並與原始種子進行比較,以定位從屬字節的潛在位置。着色過程非常緩慢,候選位置的數量也可能很大。因此,精確地對依賴字節進行變異要比灰體浪費更多的時間。

如何變異輸入的間接副本?

如果某些輸入字節影響未觸及的分支,但它們的直接副本未在該分支中使用,則我們將根據等式2按字節權重降序逐個對這些字節進行變異。

更具體地說,我們將對每個相關字節應用隨機位翻轉和算術運算。與fti中使用的字節級變異不同,在這個階段可以同時變異多個相關字節。

如後文所述,我們的符合性引導進化解決方案將使突變在運行中重新定位到更好的種子上,這將大大改進間接拷貝的突變。

減輕污染不足的問題。如前所述,FTI可能因未完成測試而存在污染問題。因此,對於任何未觸及的分支,fti報告的依賴輸入字節都可能不完整。爲了探索這個分支,我們還必須對丟失的依賴輸入字節進行變異。更具體地說,除了對fti報告的相關輸入字節進行變異之外,我們還以小概率隨機地對其相鄰字節進行變異。

2.3符合性導向的進化

廣泛的模糊器(如afl)使用控制流特徵,如代碼覆蓋率,來指導模糊化的進化方向。爲了有效地探索難以到達的分支(例如,那些與輸入的間接副本相關的分支),我們建議使用互補的數據流特徵來調整模糊化的演化方向。我們注意到,對於未觸及分支中使用的每個受污染變量,我們需要翻轉其依賴輸入字節的一些位,使其與預期值匹配。一些測試用例比其他測試用例需要更少的努力(即,比特翻轉)。所需的工作量與約束符合性有關,即受污染變量與未受影響分支中預期值的距離。符合性較高的種子更有可能產生使用未觸及分支的測試用例。在此基礎上,我們利用種子的約束符合性來調整模糊化的演化方向。我們對種子更新和選擇策略進行了相應的修改,使模糊器朝着這個方向發展。模糊化過程中生成的測試用例更有可能具有更高的符合性,並最終滿足難以達到的約束

2.3.1符合性計算

約束符合性指示目標(例如seed)與路徑約束的匹配程度。

未觸及分支的符合性。給定一個依賴於兩個操作數var1和var2的未觸及分支br,我們將其約束符合性定義如下。

其中,函數NumEqualBits返回兩個參數之間的相等位數。注意,對於switch語句中的分支,它依賴的兩個變量是switch條件和case值。

基本塊的符合性。給定一個種子s和一個基本塊bb,bb可以有多個未觸及的鄰居分支(例如,switch語句)。我們將BB的約束符合性定義爲其所有未觸及的相鄰分支的最大符合性:

測試用例的符合性。給定一個測試用例,它的約束符合性定義爲它所探索的所有基本塊的符合性得分之和。

注意,具有較高約束符合性的種子可能具有(1)更多未觸及的鄰居分支,以及(2)具有較高約束符合性的單個未觸及分支。因此,進一步的突變可能很快觸發更多未觸及的分支或針對單個未觸及的分支。

2.3.2 Conformance-Guided Seed Updating

除了發現新代碼的測試用例外,我們還將具有更高約束符合性的測試用例添加到種子隊列中。爲了有效地支持這種新的種子更新方案,我們提出了一種新的種子隊列結構。

二維種子隊列。傳統的種子隊列通常保存在一個鏈表中,每個節點代表一個探索唯一路徑4的種子。我們將每個節點擴展爲包含多個種子,這些種子探索相同的路徑,具有相同的符合性但塊符合性不同,從而形成一個二維種子隊列,如圖4所示。

種子隊列更新。圖4還顯示了在以下三種情況下如何更新種子隊列。

A新路徑。如果測試用例發現新代碼,那麼它將作爲一個新節點添加到seed隊列中,與其他覆蓋引導模糊器(例如afl)相同。

B.路徑相同,但符合性較高。如果測試用例找不到任何新代碼,但其符合性高於隊列中相應節點(具有相同路徑)中的種子,則此節點將被替換爲僅包含此測試用例的新節點。

C 相同的路徑和符合性,但基本塊符合性不同。如果測試用例探索相同的路徑,並且與隊列中相應節點中的種子具有相同的符合性,但是基本塊符合性的分佈與該節點中的種子不同,那麼我們將把此測試用例附加到該節點。

值得注意的是,在最後一種情況下,由於測試用例具有唯一的基本塊符合性分佈,因此它可以派生新的測試用例來快速觸發一些基本塊的非接觸鄰居分支,因此是有用的。

比較。這種種子更新策略使得模糊器以與安哥拉梯度下降算法相當的速度逐漸提高整體符合性,並以較快的速度滿足未觸及分支的約束[10]。但它可以避免像安哥拉那樣陷入當地最低水平,並帶來長期穩定的改善。

注意,honggfuzz[38]還比較了分支語句中操作數的相等性。如果分支的相等性增加,則會將測試用例添加到種子隊列中。但是,它不排除與觸碰分支相關的比較指令,這些指令對分支探索是無用的。此外,基本塊內部可能有多個比較指令,但並非所有指令都與分支相關。最後,它缺乏本文提出的有效的二維種子隊列結構,限制了它的效率。

2.3.3 On-the-fly Mutation Rebase

一旦我們發現一個測試用例與之前的種子運行相同的程序路徑,但具有更高的符合性,即如前所述的案例B,我們不僅通過用一個新節點替換相應的節點來將該測試用例添加到種子隊列中,而且還替換被替換種子的所有用途。特別是,如果被替換的種子被一個正在進行的突變所使用,我們將把突變重新定位到新種子上,因爲新種子更好。這個操作可以動態完成,如圖1中的紅線所示。實驗表明,該優化技術是非常有效的。例如,它將在LAVA數據集中查找相同數量的錯誤的速度提高了三倍。

2.3.4符合性指導下的種子選擇

許多工作[6,14]已經證明,種子選擇策略可以加速模糊進化。我們建議在種子選擇過程中優先考慮符合性較高的種子。更具體地說,我們迭代種子隊列的鏈表,並選擇具有更高符合性和更高概率的鏈接節點。然後在這個連接節點中隨機選擇一個種子進行進一步的變異。利用該方案,更容易選擇符合性較高的種子。進一步的突變更有可能產生符合性更高的測試用例,這可以滿足非接觸分支難以達到的約束。

3 Implementation

我們用20000行C/C++代碼實現了GyyOne的原型。當前的原型支持使用llvm字節碼分析應用程序。在這裏,我們將介紹它的一些實現細節。

3.1 Modularized Framework

如圖1所示,greyone由幾個核心成分組成,如種子更新、種子選擇、種子突變和檢測。我們實現了一組可擴展接口來支持各種策略和未來的改進。

測試用例評分。進化模糊器通常根據一定的測試用例評分算法,將一些測試用例放到種子庫中進行進一步的變異。我們實現了測試用例評分的通用接口,能夠支持afl採用的覆蓋引導種子更新策略和greyone採用的符合性引導策略。

種子優先級。模糊算子通常根據某種種子評分算法對種子進行優先排序,以選擇和分配不同的能量進行變異。我們實現了一個種子評分的通用接口,能夠支持greyone採用的符合性指導的種子選擇策略和其他fuzzer使用的策略(如collafl[14]和aflfast[6])。

種子變異算法。除了其他模糊算子(如afl)實現的變異算子(如字節翻轉)外,我們還增加了對fti使用的字節級變異的支持,以及直接拷貝變異,其中模糊算子被告知要使用的確切偏移量和確切值。

塊管理。模糊器通常需要特殊的數據結構來支持組件之間的有效通信和有效的決策。我們構造了許多基於樹和哈希表的結構來存儲這些信息,包括控制流圖、代碼覆蓋率、種子符合性、變量的污染屬性和變量的值。

選擇性測試。除了代碼覆蓋跟蹤,Greyone在測試過程中還有兩種模式:(1)用於FTI的可變值監視模式;(2)用於進化調整的符合性引導跟蹤模式。爲了有效地調度這些不同的測試模式,我們擴展了afl使用的fork服務器,以便根據需要在它們之間進行切換。例如,在模糊化過程中,如果一個種子花費了太多的變異能量或者符合性暫時沒有增加,那麼我們將從符合性跟蹤模式切換到常規覆蓋跟蹤模式。

3.2 Static Analysis and Instrumentation.

爲了支持本文提出的策略,我們需要首先使用靜態分析來分析目標應用程序,並在運行時收集一些信息。在clang的幫助下進行了一些基本的過程間控制流分析,得到了控制流圖和其他必要的信息。

覆蓋範圍跟蹤。collafl[14]指出,傳統的覆蓋跟蹤方案(如afl)存在嚴重的散列衝突問題。我們用複製了collafl的緩解方式。

符合性跟蹤:爲了支持符合性跟蹤,我們檢測每個分支語句(包括條件分支和switch語句)以計算其操作數的相等位數(通過諸如“內置”popcount之類的操作)。

變值監控:fti依賴於模糊化過程中的變值監控。我們測試應用程序以記錄路徑約束中使用的變量值。更具體地說,我們爲所有這些變量分配唯一的id,並將它們的值存儲在一個位圖中(id作爲鍵),類似於存儲afl使用的代碼覆蓋率的位圖。

6 Related Work

基於進化變異的模糊算法由於其可擴展性和高效性,在實際應用中取得了巨大的成功。代表解afl[44]以獲得更高的碼覆蓋率爲進化方向,以幾乎隨機的方式突變種子。許多其他的解決方案,包括污點分析,已經被提出來改進基於變異的模糊。

6.1 Taint Inference

污點分析是包括模糊化在內的許多應用的基本技術。傳統的污點分析解決方案[2,20]在很大程度上依賴於爲每個指令編寫污點傳播規則的手動操作,並且遭受嚴重的污點不足和過度污點問題。

對傳統污點分析的改進。針對傳統污點分析中存在的誤差問題,提出了許多改進方案。dytan[11]跟蹤間接污點傳播,以緩解污點不足的問題,但帶來了許多誤報。dta++[19]定位隱式控制流分支,並使用離線符號執行進行污點下診斷。然而,它的缺點是解決了複雜的條件和高性能的開銷。taintinclude[46]採用基於測試的解決方案自動推斷污點傳播規則。但它的重量很重,不能解決不準確的問題。

基於變異的推斷。最近的一些工作提出了基於變異的污點推斷,在某些應用中有較好的性能。sekar[31]採用黑盒測試,利用預先定義的突變規則推斷污染,能夠檢測注入攻擊。mutaflow[26]通過對敏感源api進行變異來監控安全敏感api的變化,能夠檢測到易受攻擊的信息流。這兩種方法側重於局部程序行爲,僅限於信息流檢測。在模糊應用中,redqueen[4]使用隨機變異給輸入着色,以推斷與直接複製輸入相關的污點。fairfuzz[24]和profuzzer[42]監視多個運行之間的控制流變化模式,以推斷變異字節的部分類型。這些解都沒有考慮到變異後變量值的變化,因此都不能提供準確的污染信息。

本文提出了一種模糊驅動的污點推斷方法fti。我們執行系統的字節級變異來執行pilot模糊。在模糊化過程中,我們監控變量的值變化,並據此推斷污染屬性。該解決方案自動化、輕量級且更精確。

6.2 Seed Mutation

許多研究[10,13,30,44]表明,種子突變是提高模糊處理效率和準確性的最熱點和最困難的方向之一。人們提出了許多方法試圖解決如何以及在哪裏變異。

a)基於靜態分析的優化。steelix[25]和laf-intel-pass[1]將這些長常量比較靜態地分解爲多個短比較。從而使bomb隨機模糊器以更高的概率滿足路徑約束。然而,它帶來了太多的語義等價路徑,無法處理非恆定比較。symfuzz[8]利用靜態符號分析來檢測輸入位之間的依賴關係,並使用它來計算最佳變異率。然而,這一過程是緩慢的,並且計算出的位之間的依賴關係並沒有顯示出許多變異的改進。

b)基於學習的模式。Rajpal等人[29]提出了一個基於RNN的模型,根據歷史突變及其相應的代碼覆蓋反饋,預測種子中的最佳突變位置。康斯坦丁等人[7]利用深度強化學習對模糊循環進行建模,並在隨後的模糊迭代中選擇最佳的變異動作。這些解決方案尚處於早期階段,尚未顯示出顯著的改進。neuzz[35]確定了程序平滑的重要性,並使用增量學習技術來指導變異

c)  基於符號的解決方案。這類解決方案本質上是利用符號執行來解決複雜的路徑約束,而這些約束是基於變異的模糊算法難以滿足的。driller[37]週期性地選擇陷入基於變異的模糊化的路徑,並使用符號執行來解決這些路徑的約束。qsym[43]將符號執行移植到本機x86指令並放寬要解決的路徑約束,從而提供更好的分析性能並降低約束解決的速度。Diggfuzz[45]設計了一個概率路徑優先化模型來量化每條路徑的難度,並對它們進行優先排序,以便共同執行。由於約束求解的開放性挑戰,所有這些基於符號的解決方案都無法擴展到大型應用中。

d)基於污染的突變。一些模糊者利用污染來引導突變。Dowser[17]和Borg[27]分別使用Taint來定位緩衝區邊界衝突和緩衝區過度讀取漏洞。buzzfuzz[15]使用dta跟蹤影響敏感庫或系統調用的外部種子輸入區域。TaintScope[40]利用細粒度DTA來標識校驗和分支。Vuzzer[30]能夠跟蹤比較變量和常量(如幻數)的分支,並相應地指導變異。angora[10]基於dta進行形狀推斷和梯度下降計算。這些解決方案受到不精確的污染,限制了複雜程序的效率。

此外,dta的高開銷極大地限制了dta在大型應用中的應用。在輕量級污染導向突變解中,fairfuzz[24]和profuzzer[42]無法獲得變量的精確污染屬性,在探索難以到達的分支時效率低下。此外,它們還會重複地改變一些輸入字節,即使相關的分支已經被探索過,因爲它們對分支狀態不敏感。redqueen[4]專注於識別輸入的直接副本和使用它們的分支,無法處理輸入的間接副本的普遍使用。

我們的解決方案greyone利用輕量級和聲音污染推理解決方案fti來獲得更多的污染屬性(沒有過度污染),以及輸入偏移和分支之間的精確關係,以確定要探索的分支和要變異的字節的優先級,並確定如何精確地變異它們。

6.3 Seed Updating and Selection

種子更新和選擇可以調整模糊的進化方向。一個好的解決方案可以提高fuzzer查找更多代碼和錯誤的效率[28]並朝着潛在易受攻擊的目標代碼[5,9,39]前進。

種子更新的研究很少,但近年來提出了許多種子選擇的解決方案。這些解決方案一般收集越來越多的輔助控制流信息來指導種子選擇。在一開始,afl[44]優先處理那些較小的種子和較短的執行時間,以便在給定的時間段內生成更多的測試用例。然後,aflfast[6]指出了種子選擇的重要性,並對很少被採摘變異和探索寒冷路徑的種子進行了優先排序。從那時起,各種控制流特性被用於指導種子選擇,例如,通過優先排序較深路徑[30]或未接觸的相鄰分支[14]。

然而,這些解決方案沒有考慮任何數據流特性,因此在探索具有複雜約束的路徑時效率低下。honggfuzz[38]和libfuzzer[32]利用弱數據流特性來指導種子選擇。更具體地說,它們計算所有分支的操作數之間的距離,並將其用於指導種子選擇。

Greyone只對所有受污染的未觸及分支評估約束一致性,從而改進了此策略。它還利用了一種新穎的二維種子隊列結構,爲高效的種子更新和選擇提供支持。它能夠避免安哥拉使用的基於學習的解決方案所面臨的局部最小問題[10]。此外,greyone還應用了一種新的動態突變rebase來進一步加速模糊的進化。

6.4 Performance Optimization

性能是有效模糊化的一個重要因素。爲了提高模糊處理的性能,人們提出了幾種解決方案,如提高並行執行能力[41]或提高插裝能力[18,36]。untracer[36]最近的工作消除了已經探索過的基本塊中不必要的工具,並減少了開銷。Greyone還對儀器進行了優化,根據需要選擇了更多的輕量級測試模式,並在不同的模糊模式之間切換,提高了模糊的速度。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章