
AFL/QEMUによるフルシステムエミュレーションでのファジング。
新着: TriforceAFLとTLSFを試してみたい方のために、Richard Johnsonが両方をインストールするDockerfile(さらにLinuxカーネルまでビルドしてくれます)を作成しました。こちらから入手できます https://hub.docker.com/r/moflow/afl-triforce/tags/。
もう1つの新着: afl-tminがフォークサーバーに対応しました!
https://github.com/nccgroup/TriforceAFL Jesse Hertz [email protected] Tim Newsham [email protected]
これはQEMUを使用したフルシステムファジングをサポートするAFLのパッチ版です。 同梱のQEMUは、x86_64のシステムエミュレータを実行する際にブランチの トレースを可能にするよう更新されています。AFLのフォークサーバーを起動し、 ファズ設定を行い、テストケースの開始と終了をマークするための 追加命令が組み込まれています。
注: すべてのAFLツールが新しい変更でテストされたわけではありません。 以下のツールはある程度テストされています:
ビルド方法:
make
カバレッジマップを取得するには:
echo hello > /tmp/hello
./afl-showmap -o coverage.txt -QQ --
./afl-qemu-system-trace -kernel ../bzImage
-initrd ../initramfs.cpio.gz -m 1G -nographic
-append "console=ttyS0" -aflFile /tmp/hello
cat coverage.txt
ファズするには:
egrep ' (panic|log_store)$' ../mykern/kallsyms ffffffff8108e570 t log_store ffffffff8181064b T panic
mkdir inputs
echo hello > inputs/hello
./afl-fuzz -i inputs -o outputs -QQ --
afl-qemu-system-trace -kernel bzImage -initrd root.cpio.gz
-m 1G -nographic -append "console=ttyS0"
-aflPanicAddr ffffffff8181064b -aflDmesgAddr ffffffff8108e570
-aflFile @@
(注: "-Q"オプションを使用する場合とは異なり、"-QQ"オプションを使用する場合は、 afl-qemu-system-traceへの完全なコマンドラインを指定する必要があります)。
この修正版AFLの使用方法の詳細については、 Linuxシステムコールファザーを参照してください: https://github.com/nccgroup/TriforceLinuxSyscallFuzzer.
新しいAFLフラグ: -QQ - ユーザーモード(-Q)ではなくフルシステムエミュレーションでQEMUを使用
新しいQEMUフラグ: -aflFile - ファザーの入力が含まれるファイルの名前 -aflPanicAddr - パニック検出用のカーネルパニックアドレス -aflDmesgAddr - ロギングの検出とログメッセージの傍受のための dmesgログ機能のLinuxカーネルアドレス
新しいQEMU命令: 0f 24 - aflCall edi=1 startForkserver(esi=enableTicks) AFLのフォークサーバーを起動します。この時点以降、各テストは フォークされた別々の子プロセスで実行されます。enableTicksが 非ゼロの場合、QEMUは子プロセスをフォークした後にCPUタイマーを 再度有効にします。それ以外の場合は有効になりません。 edi=2 getWork(esi=ptr, edx=sz) ptr[0..sz]に次の入力テストケースを格納します。実際に 格納されたサイズ(<= sz)を返します。 edi=3 startWork(esi=ptr) AFLにトレースの開始を指示します。引数は、トレースするコードの 開始アドレスと終了アドレスを示す2つのクアドワードを持つ バッファを指します。この範囲外の命令はトレースされません。 edi=4 doneWork(esi=exitCode) AFLにテストケースが完了したことを通知します。パニックが 検出された場合、AFLはテストケースを即座に停止します。 それ以外の場合は、doneWorkが呼び出されるまで実行を続けます。 指定されたexitCodeはAFLに返されます。(コードは、テストケース中に dmesgログが検出された場合、すべての終了コードに値64をOR演算 することができますが、現在は行われていません。)
新しいQEMUブロックドライバ: -drive filename=privmem: このブロックドライバは、ドライブのイメージをコピーオンライトメモリに 保持するため、変更がディスクに永続化されることはありません。 あるテストケースによる変更は、他のテストケースから分離されます。
Written and maintained by Michal Zalewski [email protected]
Copyright 2013, 2014, 2015, 2016 Google Inc. All rights reserved. Released under terms and conditions of Apache License, Version 2.0.
新バージョンや追加情報については、以下を参照してください: http://lcamtuf.coredump.cx/afl/
他のユーザーと情報交換したり、主要な新機能の通知を受け取るには、 [email protected] にメールを送信してください。
** このファイルを読む時間がない場合は、QuickStartGuide.txtを参照してください。 **
ファジングは、実世界のソフトウェアにおけるセキュリティ問題を特定するための、 最も強力で実績のある戦略の1つです。これまでにセキュリティ上重要な ソフトウェアで発見されたリモートコード実行や権限昇格のバグの大半は、 ファジングによるものです。
残念ながら、ファジングは比較的浅いものでもあります。盲目的でランダムな 変異では、テスト対象コードの特定のコードパスに到達する可能性は非常に低く、 一部の脆弱性はこの手法の射程外に取り残されます。
この問題を解決するための試みは数多く行われてきました。初期のアプローチの 1つであるコーパス蒸留は、Tavis Ormandyによって先駆けられました。この方法は、 カバレッジシグナルを利用して、大規模で高品質な候補ファイルのコーパスから 興味深いシードのサブセットを選択し、それを従来の手段でファズします。この アプローチは非常にうまく機能しますが、そのようなコーパスがすぐに利用可能で ある必要があります。さらに、ブロックカバレッジの測定はプログラム状態の 非常に単純な理解しか提供せず、長期的なファジングの方向付けにはあまり 役立ちません。
その他のより高度な研究は、プログラムフロー解析(「コノリック実行」)、 シンボリック実行、静的解析などの技術に焦点を当てています。これらの方法は すべて実験環境では非常に有望ですが、実用においては信頼性とパフォーマンスの 問題に悩まされる傾向があり、現時点では「愚かな」ファジング技術に代わる 実行可能な選択肢を提供していません。
American Fuzzy Lopは、非常にシンプルながら堅牢な計装ガイド式遺伝的 アルゴリズムと組み合わされたブルートフォースファザーです。プログラムの 制御フローに対する微妙で局所的な変化を簡単に検出するために、修正された 形式のエッジカバレッジを使用します。
少し単純化すると、アルゴリズム全体は次のように要約できます:
ユーザーが提供した初期テストケースをキューに読み込む、
キューから次の入力ファイルを取り出す、
プログラムの測定された動作を変えない最小サイズまでテストケースを 削減する、
バランスが取れ、よく研究されたさまざまな従来のファジング戦略を 使用してファイルを繰り返し変異させる、
生成された変異のいずれかが、計装によって記録された新しい状態遷移を もたらした場合、変異した出力をキューの新しいエントリとして追加する。
2に戻る。
発見されたテストケースは、より新しくカバレッジの高い発見によって陳腐化した ものを排除するために定期的に間引かれ、さらにいくつかの計装駆動型の労力 最小化ステップを受けます。
ファジングプロセスの副次的な結果として、このツールは興味深いテストケースの 小さな自己完結型コーパスを作成します。これらは、他の労力やリソースを大量に 消費するテスト体制のシードとして非常に役立ちます。例えば、ブラウザ、 オフィスアプリケーション、グラフィックススイート、またはクローズドソース ツールのストレステストなどです。
このファザーは、盲目的ファジングやカバレッジのみのツールよりもはるかに 優れた即時パフォーマンスを提供するよう徹底的にテストされています。
ソースコードが利用可能な場合、サードパーティコードの標準的なビルドプロセス においてgccやclangのドロップイン置換として機能するコンパニオンツールに よって計装を注入できます。
計装のパフォーマンスへの影響はかなり控えめです。afl-fuzzが実装する他の 最適化と組み合わせることで、ほとんどのプログラムは従来のツールと同程度か、 それ以上の速度でファズできます。
ターゲットプログラムを再コンパイルする正しい方法はビルドプロセスの詳細に よって異なる場合がありますが、ほぼ普遍的なアプローチは次のとおりです:
$ CC=/path/to/afl/afl-gcc ./configure $ make clean all
C++プログラムの場合は、CXX=/path/to/afl/afl-g++も設定する必要があります。
clangラッパー(afl-clangおよびafl-clang++)も同じように使用できます。 clangユーザーは、llvm_mode/README.llvmで説明されているように、より高性能な 計装モードを利用することもできます。
ライブラリをテストする場合、stdinまたはファイルからデータを読み取り、 テスト対象のライブラリに渡す単純なプログラムを見つけるか作成する必要が あります。そのような場合、この実行可能ファイルを計装済みライブラリの静的 バージョンにリンクするか、実行時に正しい.soファイルがロードされるように することが不可欠です(通常はLD_LIBRARY_PATHを設定します)。最も簡単な方法は 静的ビルドで、通常は次のようにして可能です:
$ CC=/path/to/afl/afl-gcc ./configure --disable-shared
'make'を呼び出すときにAFL_HARDEN=1を設定すると、CCラッパーが自動的に コードハードニングオプションを有効にし、単純なメモリバグの検出が 容易になります。
追記: ASANユーザーは、重要な注意事項についてnotes_for_asan.txtファイルを 確認することをお勧めします。
ソースコードが利用できない場合、ファザーはブラックボックスバイナリの 高速なオンザフライ計装の実験的サポートを提供します。これは、あまり知られて いない「ユーザースペースエミュレーション」モードで動作するQEMUの バージョンによって実現されます。
QEMUはAFLとは別のプロジェクトですが、次のようにしてこの機能を簡単に ビルドできます:
$ cd qemu_mode $ ./build_qemu_support.sh
追加の手順と注意事項については、qemu_mode/README.qemuを参照してください。
このモードはコンパイル時計装より約2〜5倍遅く、並列化にはあまり適しておらず、 その他の癖がある場合もあります。
正しく動作するために、ファザーには、対象アプリケーションが通常期待する 入力データの適切な例を含む1つ以上の開始ファイルが必要です。基本的な ルールは2つあります:
ファイルは小さく保ってください。1 kB未満が理想的ですが、厳密に 必要というわけではありません。サイズが重要な理由については、 perf_tips.txtを参照してください。
複数のテストケースは、互いに機能的に異なる場合にのみ使用してください。 画像ライブラリをファズするために50枚の異なるバケーション写真を 使っても意味がありません。
このツールに付属するtestcases/サブディレクトリには、開始ファイルの良い例が 多数あります。
追記: スクリーニング用に大量のデータコーパスが利用可能な場合、afl-cmin ユーティリティを使用して、ターゲットバイナリの異なるコードパスを実行する 機能的に異なるファイルのサブセットを特定するとよいでしょう。
ファジングプロセス自体はafl-fuzzユーティリティによって実行されます。この プログラムには、初期テストケースを含む読み取り専用ディレクトリ、調査結果を 保存するための別の場所、そしてテストするバイナリへのパスが必要です。
stdinから直接入力を受け付けるターゲットバイナリの場合、通常の構文は 次のとおりです:
$ ./afl-fuzz -i testcase_dir -o findings_dir /path/to/program [...params...]
ファイルから入力を受け取るプログラムの場合は、'@@'を使用して、入力ファイル名を 配置するターゲットのコマンドライン上の位置をマークします。ファザーがこれを 置き換えてくれます:
$ ./afl-fuzz -i testcase_dir -o findings_dir /path/to/program @@
-fオプションを使用すると、変異したデータを特定のファイルに書き込むことも できます。これは、プログラムが特定のファイル拡張子などを期待する場合に 便利です。
計装されていないバイナリは、QEMUモード(コマンドラインに-Qを追加)または 従来の盲目的ファザーモード(-nを指定)でファズできます。
-tおよび-mを使用して、実行されるプロセスのデフォルトのタイムアウトと メモリ制限を上書きできます。これらの設定の調整が必要になる可能性のある ターゲットのまれな例としては、コンパイラやビデオデコーダがあります。
ファジングパフォーマンスを最適化するためのヒントは、perf_tips.txtで 説明されています。
afl-fuzzは、一連の決定的なファジングステップを実行することから始まり、 これには数日かかる場合があることに注意してください。zzufやhonggfuzzと 同様に、すぐに簡易的な結果を得たい場合は、コマンドラインに-dオプションを 追加してください。
表示される統計情報の解釈とプロセスの健全性の監視方法については、 status_screen.txtファイルを参照してください。特にUI要素が赤でハイライト されている場合は、必ずこのファイルを確認してください。