它は、ソースコードの再コンパイル時にインストゥルメンテーションを行い、バイナリプログラムの内部で新しい実行パスを探索するためのテストケースを自動的に生成します。
他のインストゥルメンテーションベースの fuzzer と比較して、afl-fuzz はパフォーマンスの消費が低く、さまざまな効率的な fuzzing 戦略とテクニックを備えており、複雑な実世界のプログラムを軽減するための複雑な設定は必要ありません。
もちろん、AFL はソースコードのないバイナリプログラムに直接テストを行うこともサポートしていますが、その場合は QEMU のサポートが必要です。
afl-fuzz のインストール#
公式ウェブサイトからソースコードの圧縮ファイルをダウンロードし、解凍します。そして、次のようにコンパイルしてインストールします:
make
sudo make install
インストールが完了したら、通常はコアダンプをファイルに出力し、クラッシュ情報を特定のハンドラに送信するのではなく、次のように設定する必要があります:
sudo su
echo core > /proc/sys/kernel/core_pattern
公式ドキュメント:http://lcamtuf.coredump.cx/afl/README.txt
テスト例#
ソースコードがあるテストプログラムの場合、gcc や clang の代わりに afl を使用してコンパイルすることができます。afl のインストゥルメンテーションを使用すると、afl-fuzz のパフォーマンスが最適化され、fuzzing が高速化されます。
テストプログラム#
以下はクラッシュの例です:
#include <stdio.h>
#include <signal.h>
int main(int argc, char *argv[])
{
char buf[233] = {0};
FILE *input = NULL;
input = fopen(argv[1], "r");
if(input != 0)
{
fscanf(input ,"%s", &buf);
printf("buf is %s\n", buf);
func(buf);
fclose(input);
}
else
printf("error!");
return 0;
}
int func(char *data)
{
if(data[0] == 'A')
raise(SIGSEGV);
else
printf("ok\n");
return 0;
}
入力ファイルの最初の文字が A の場合、プログラムはクラッシュします。
afl-gcc を使用してプログラムをコンパイルし、インストゥルメンテーションを行います:
afl-gcc test.c -o test
準備#
入力と出力のフォルダを作成します:
mkdir fuzz_in fuzz_out
初期化テストケースを準備します。case の内容を aaa に設定し、fuzzer はテストケースに基づいて突然変異を行います:
echo aaa > fuzz_in/case
fuzzing の開始#
fuzz_in
はデフォルトの入力ディレクトリであり、fuzz_out
は指定した出力ディレクトリです。
afl-fuzz -i fuzz_in -o fuzz_out ./test @@
ここで@@
フラグを使用して、ファイルから入力を読み取ります。実際の実行時には、@@
はfuzz_in
ディレクトリ内のテストケースに置き換えられます。
fuzzing の結果#
fuzz_out/crashes$ cat id\:000000\,sig\:11\,src\:000000\,op\:flip1\,pos\:0
Aaa
参考文献: