AFL學習(一)對於AFL插樁的理解
前言
最近剛剛接觸AFL(american fuzzy lop),打算先通過閱讀AFL原始碼來進行學習,在讀原始碼之前我看了看AFL技術白皮書(Technical “whitepaper” for afl-fuzz),本文主要寫一下我目前對於AFL插樁的粗淺理解,如有錯誤,懇請指正。
參考資料:
白皮書原文
一、程式碼覆蓋率及其相關概念
在介紹AFL插樁之前,先簡單介紹一下相關的基本概念
1.程式碼覆蓋率
程式碼覆蓋率是一種度量程式碼的覆蓋程度的方式,也就是指原始碼中的某行程式碼是否已執行。其計量方式很多,但無論是GCC的GCOV還是LLVM的SanitizerCoverage,都提供函式(function)、基本塊(basic-block)、邊界(edge)三種級別的覆蓋率檢測,更具體的細節可以參考LLVM的官方文件。
2.基本塊(Basic Block)
縮寫為BB,指一組順序執行的指令,BB中第一條指令被執行後,後續的指令也會被全部執行,每個BB中所有指令的執行次數是相同的,也就是說一個BB必須滿足以下特徵:
只有一個入口點,BB中的指令不是任何跳轉指令的目標。
只有一個退出點,只有最後一條指令使執行流程轉移到另一個BB
3.邊(edge)
AFL的技術白皮書中提到fuzzer通過插樁程式碼捕獲邊(edge)覆蓋率。那麼什麼是edge呢?我們可以將程式看成一個控制流圖(CFG),圖的每個節點表示一個基本塊,而edge就被用來表示在基本塊之間的跳轉。知道了每個基本塊和跳轉的執行次數,就可以知道程式中的每個語句和分支的執行次數,從而獲得比記錄BB更細粒度的覆蓋率資訊。
4.元組(tuple)
具體到AFL的實現中,使用二元組(branch_src, branch_dst)來記錄當前基本塊 + 前一基本塊 的資訊,從而獲取目標的執行流程和程式碼覆蓋情況。
二、AFL插樁
什麼是插樁?
在AFL編譯檔案時候afl-gcc會在規定位置插入樁程式碼,可以理解為一個個的探針(但是沒有暫停功能),在後續fuzz的過程中會根據這些樁程式碼進行路徑探索,測試等。
AFL通過插樁的形式注入到被編譯的程式中,實現對分支(branch、edge)覆蓋率的捕獲,以及分支節點計數。程式碼大致如下:
cur_location = <COMPILE_TIME_RANDOM>;
shared_mem[cur_location ^ prev_location]++;//將當前塊和前一塊異或儲存到shared_mem[]
prev_location = cur_location >> 1;//cur_location右移1位區分從當前塊到當前塊的轉跳
程式碼十分簡單,我們來分析一下
第一行就是用一個隨機數cur_location 標記當前的塊。
之後將當前塊和前一塊異或儲存到shared_mem[],其中shared_mem[]陣列是一個被呼叫者傳入插樁二進位制的64Kb SHM大小的區域。
最後一行將cur_location右移一位作為prev_location,這樣就完成了對兩個塊的路徑的標記。
這裡就會有幾個問題
1.為什麼要將cur_location 和 prev_location進行異或處理,如果進行其他處理效果會怎樣?
得到的答案是可能作者覺得這樣處理得到的結果還不錯,這裡暫時還沒想明白。
2.為什麼要將cur_location進行除以二之後再賦給prev_location?
這裡是為了區分兩個塊之間不同方向的路徑,設想直接將cur_location作為下一個塊的pre_location,那麼這將很難鑑別A ^ B和B ^ A,這樣顯然不是我們想要的結果。
此外,在分支較多的情況下,產生的資料會發生衝突,下圖就是白皮書中貼出的資料。
相關文章
- afl入門學習
- AFL原始碼分析(一)原始碼
- fuzz——AFL基礎使用方法
- AFL二三事 -- 原始碼分析 1原始碼
- AFL二三事 -- 原始碼分析 2原始碼
- AFL二三事 -- 原始碼分析 3原始碼
- AFL++初探-手把手Fuzz一個PDF解析器
- 基於原型鏈劫持的前端程式碼插樁實踐原型前端
- 對checkpoint的理解一文的學習
- 如何使用AFL-FUZZ進行網路協議軟體的模糊測試協議
- Android 位元組碼插樁Android
- nyc 插樁無法插樁使用裝飾器的程式碼,請問有什麼解決辦法嗎?
- Android AOP之位元組碼插樁Android
- Android編譯期插樁,讓程式自己寫程式碼(一)Android編譯
- 對於Fragment的一些理解Fragment
- 深入探索編譯插樁技術(二、AspectJ)編譯
- 可代替 ASM,使用 AnnotationProcessor 做程式碼插樁ASM
- XML學習筆記(一):關於字元編碼的理解XML筆記字元
- 初學 PHP 對於回撥函式的一些理解PHP函式
- Android位元組碼插樁採坑筆記Android筆記
- java學習中對類和物件的理解Java物件
- Linux| |對於UDP的學習LinuxUDP
- 對於BFC的理解
- 對於MVVM的理解MVVM
- 插頭DP學習筆記筆記
- 對於Redux原始碼的一些理解Redux原始碼
- 對於最近的一些理解和思考
- 對epoll機制的學習理解v1
- 個人對於vue的理解Vue
- 對於button元素的理解
- 關於對Host的理解
- 對於Database recovery的理解Database
- webgl centroid質心插值的一點理解Web
- 開發 IDEA Plugin 引入探針,基於位元組碼插樁獲取執行SQLIdeaPluginSQL
- 調研位元組碼插樁技術,用於系統監控設計和實現
- Java學習之流Stream理解(一)Java
- (學習筆記)python 對__init__的初步理解筆記Python
- ElasticSearch學習筆記(二)——對聚合的簡單理解Elasticsearch筆記