Angora: Efficient Fuzzing by Principled Search 閱讀筆記

Abstract

不使用符號執(zhí)行來解決路徑約束,從而增加分支覆蓋率。為了有效地解決路徑約束,我們引入了幾個關鍵技術:可擴展的字節(jié)級污點跟蹤,上下文敏感的分支計數(shù),基于梯度下降的搜索和輸入長度探索。

Design

使用上下文敏感的分支覆蓋作為覆蓋的度量。每次 fuzzing,Angora 選擇一個未探索的分支并搜索探索該分支的輸入。

  • 對于大多數(shù)條件語句,其判斷僅受輸入中的幾個字節(jié)的影響,因此改變整個輸入將是徒勞的。因此,在探索分支時,Angora會確定哪些輸入字節(jié)流入相應的判斷,并專注于僅改變這些字節(jié)
  • 確定要改變的輸入字節(jié)后,將分支上的路徑約束視為輸入上黑盒函數(shù)的約束,并且我們調整梯度下降算法來解決約束
  • 在梯度下降期間,我們對黑盒函數(shù)的參數(shù)進行評估,其中一些參數(shù)由多個字節(jié)組成
  • 僅僅改變輸入中的字節(jié)是不夠的。只有在輸入超過閾值后才會觸發(fā)一些錯誤,Angora 對程序進行插樁,檢測什么時候較長的輸入能夠探索新分支并且確定所需的最小長度

上下文敏感的分支計數(shù)

元組:(l_{prev},l_{cur},context)

除了分支前后基本塊的 ID,context 是 h(stack),h 是哈希函數(shù),stack 包含調用棧的狀態(tài)。

因為上下文改變之后到達同一個分支可能觸發(fā)新的內部狀態(tài)。

目前的實現(xiàn)是使用 h 計算所有調用位置 ID 的異或,當 Angora 對程序插樁時,它會為每個調用點分配一個隨機 ID。

字節(jié)級污點跟蹤

Angora 的目標是創(chuàng)建能夠執(zhí)行未被探索的分支的輸入。當它嘗試執(zhí)行未探測的分支時,它必須知道輸入中的哪些字節(jié)偏移影響分支的判斷。因此,Angora需要字節(jié)級別的污點跟蹤。

Angora將程序中的每個變量x與污點標簽tx相關聯(lián),污點標簽tx表示輸入中可能流入x的字節(jié)偏移量。污點標簽須支持的操作:

  • INSERT(b):插入位向量b并返回其標簽。
  • FIND(t):返回污點標簽t的位向量。
  • UNION(tx; ty):返回污點標簽,表示污點標簽tx和ty的位向量的并集。

不可行的實現(xiàn):

  • 將污點標簽表示為位向量,位 i 表示輸入的第 i 個字節(jié),那么大輸入就會是禁止的。
  • 將位向量存儲在表中,使用索引作為污點標簽,但是 union 代價會很高,union 首先找到兩個標簽的位向量并計算并集 u,接下來會搜索表確定 u 是否已經(jīng)存在,代價很高。

新的數(shù)據(jù)結構,為每個位向量分配唯一標簽(無符號整數(shù)):

  • 二叉樹將位向量映射到其標簽,每個位向量 b 由 level |b| 的唯一節(jié)點 v_b 表示,其中 |b| 為 b 的長度。v_b 存儲 b 的標簽,從根到達 v_b,如果節(jié)點值為 0,向左搜索,否則向右。每個節(jié)點都包含一個指向父節(jié)點的指針,使我們可以提取出位向量。
  • 查找表將標簽映射到其位向量。標簽是該表的索引,相應的條目指向表示該標簽的位向量的樹節(jié)點。

INSERT:

  • 刪除向量的所有尾隨 0
  • 跟蹤向量中的位,如果為 0,遍歷左子樹,為 1,遍歷右子樹,如果不存在,創(chuàng)建新節(jié)點
  • 將向量標簽存儲在最后一個節(jié)點中

基于梯度下降的搜索算法

字節(jié)級污點跟蹤發(fā)現(xiàn)了輸入的哪些字節(jié)流入條件語句。但是如何改變輸入以運行未探索的分支語句?

將分支的判斷看作黑盒函數(shù) f(x) 的約束,x 是輸入中流入判斷的值的向量,f() 捕獲從程序開始到此判斷的路徑的計算,f(x) 有三種約束:

  • f(x) < 0
  • f(x) <= 0
  • f(x) == 0

如果包含邏輯運算 $$ 或者 ||,Angora 將語句拆分成多個條件語句,如 if (a && b) { s } else { t } 拆分為 if ( a ) { if ( b ) { s } else { t }} else { t }

形狀和類型推斷

對于形狀推斷,最初輸入中的所有字節(jié)都是獨立的。在污點分析期間,當指令將輸入字節(jié)序列讀入變量,其中序列的大小與基本類型的大小匹配(如 1,2,4,8 字節(jié)),Angora 標記這些字節(jié)輸入相同值。當沖突發(fā)生時,Angora 使用最小的 size。

對于類型推斷,Angora 依賴于對值進行操作的指令的語義。如果指令對有符號整數(shù)進行操作,那么 Angora 將相應的操作數(shù)推斷為有符號整數(shù),當相同的值同時用作有符號和無符號類型時,Angora 將其視為無符號類型。

輸入長度探索

與大多數(shù)其他模糊器一樣,Angora開始使用盡可能小的輸入進行模糊測試。但是,僅當輸入長于閾值時才執(zhí)行某些分支。這給模糊器帶來了兩難境地。如果模糊器使用太短的輸入,則無法探索這些分支。但如果它使用太長的輸入,程序可能運行緩慢甚至內存不足。

在污點跟蹤期間,Angora 將類似 read 的函數(shù)調用中的目標內存輸入中的相應字節(jié)偏移相關聯(lián)。它還使用特殊標簽標記來自讀取調用的返回值。如果在條件語句中使用返回值并且不滿足約束,則Angora會增加輸入長度,以便讀取調用可以獲取它請求的所有字節(jié)。

Implementation

插樁

Angora 通過 LLVM Pass 來對程序進行插樁。插樁

  • 收集條件語句的基本信息,并通過污點分析將條件語句鏈接到其對應的輸入字節(jié)偏移。
  • 記錄執(zhí)行 trace 以識別新輸入
  • 在運行時支持上下文
  • 在判斷時收集表達式值(梯度下降)

為了支持可擴展的字節(jié)級污點跟蹤,我們通過擴展 DataFlowSanitizer (DFSan) 為 Angora 實現(xiàn)了污點跟蹤。我們?yōu)?FIND 和 UNION 操作實現(xiàn)了緩存機制,顯著加快了污點跟蹤。

Angora 依賴于 LLVM 4.0.0(包括 DFSan),它的 LLVM Pass 有 820 行 C++ 代碼(不包括 DFSan),runtime 有 1950 行 C++ 代碼,包含存儲污點標簽的數(shù)據(jù)結構以及用于污染輸入和跟蹤條件語句的 hooks。

Angora 將每個 switch 語句轉換為 if 語句序列。Angora 識別 libc 函數(shù),用于在條件語句中出現(xiàn)時比較字符串和數(shù)組。例如,Angora將 “strcmp(x,y)”轉換為 “x strcmp y”,其中strcmp是Angora理解的特殊比較運算符。

Fuzzer

我們以 4488 行 Rust 代碼實現(xiàn)了 Angora,我們使用 fork server 和 CPU 綁定等技術優(yōu)化了 Angora。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Abstract 要解決的問題:使用者給出一個指定的查詢區(qū)域,我們要找到與之對應的相似區(qū)域。 該問題在相似性的定義...
    逍遙客小老虎閱讀 826評論 0 0
  • 二級考試模擬卷11、棧按先進后出的原則,所以入棧最早的最后出棧;數(shù)據(jù)的插入刪除都是在棧頂進行操作。所以棧頂元素最后...
    眼前人心上人_9a6a閱讀 585評論 0 2
  • 1. 基本概念 (1)基本塊:基本塊是指一組連續(xù)的程序指令,并且只有一個入口指令和一個退出指令(不一定是跳轉指令)...
    AxisX閱讀 4,988評論 0 1
  • 章節(jié)一 一:各環(huán)境變量的意義 1.環(huán)境變量的意義 操作系統(tǒng)中具有特定名字的對象,用于儲存一個路徑,該路徑指明某些文...
    kuriyama閱讀 801評論 0 0
  • ORA-00001: 違反唯一約束條件 (.) 錯誤說明:當在唯一索引所對應的列上鍵入重復值時,會觸發(fā)此異常。 O...
    我想起個好名字閱讀 5,957評論 0 9

友情鏈接更多精彩內容