第 24 章 使用 afl-fuzz 進行模糊測試

1 概述

American fuzzy lop (“afl-fuzz”) 是一個模糊測試器,它是一種透過提供隨機產生的輸入來測試軟體的工具,並搜尋那些會導致程式崩潰的輸入。

與大多數模糊測試器不同,afl-fuzz 會觀察被測試程式的內部行為,並調整它產生的測試案例,以觸發未探索的執行路徑。因此,afl-fuzz 產生的測試案例比其他模糊測試器涵蓋了更多被測試程式的可能行為。

這需要對要測試的程式進行儀器化處理,以便與 afl-fuzz 通訊。原生碼編譯器 “ocamlopt” 可以產生這種儀器化程式碼,允許將 afl-fuzz 用於以 OCaml 撰寫的程式。

有關 afl-fuzz 的更多資訊,請參閱網站 http://lcamtuf.coredump.cx/afl/

2 產生儀器化程式碼

afl-fuzz 所需的儀器化程式碼預設不會產生,必須透過將 -afl-instrument 選項傳遞給 ocamlopt 來明確啟用。

為了在不修改建置工具的情況下模糊測試大型系統,OCaml 的 configure 腳本也接受 afl-instrument 選項。如果 OCaml 配置了 afl-instrument,那麼所有由 ocamlopt 編譯的程式都會被儀器化。

2.1 進階選項

在極少數情況下,控制產生的儀器化程式碼量是有用的。透過將 -afl-inst-ratio N 參數傳遞給 ocamlopt,其中 N 小於 100,則可以僅為 N% 的分支產生儀器化程式碼。(請參閱 afl-fuzz 文件中關於參數 AFL_INST_RATIO 的說明,以了解其確切效果)。

3 範例

作為一個範例,我們對以下程式 readline.ml 進行模糊測試

let _ =
  let s = read_line () in
  match Array.to_list (Array.init (String.length s) (String.get s)) with
    ['s'; 'e'; 'c'; 'r'; 'e'; 't'; ' '; 'c'; 'o'; 'd'; 'e'] -> failwith "uh oh"
  | _ -> ()

有一個單一輸入 (字串「secret code」) 會導致此程式崩潰,但透過盲目隨機搜尋找到它是不切實際的。

相反地,我們啟用 afl-fuzz 儀器化程式碼進行編譯

ocamlopt -afl-instrument readline.ml -o readline

接下來,我們在 afl-fuzz 下執行該程式

mkdir input
echo asdf > input/testcase
mkdir output
afl-fuzz -m none -i input -o output ./readline

透過檢查儀器化程式碼的輸出,模糊測試器很快就會找到導致崩潰的輸入。

注意:要使用 afl-fuzz 對 OCaml 程式進行模糊測試,需要傳遞選項 -m none 以停用 afl-fuzz 的預設 50MB 虛擬記憶體限制。