
この実験的なファザーは、APIのインメモリファジングに使用することを意図しています。
v1.4 著作権 (C) 2020 Andrea Fioraldi [email protected]
Apache License v2.0 のもとで公開されています
この実験的なファザーは、API のインメモリファジングに使用することを目的としています。
AFL/AFL++ を基盤として、その設計に強く影響を受けています。
現時点では、変異器は非常にシンプルで、AFL の havoc ステージと splice ステージのみです。
tests/ 以下のサンプルでのみテストしました。これは作業中のプロジェクトですが、少なくとも GNU/Linux x86_64 および Android x86_64 で動作することが確認されています。
これを実行するには Frida >= 12.8.1 が必要です(pip3 install -U frida)、およびハーネスをコンパイルするための frida-tools が必要です。
fuzz ライブラリをカスタムハーネスにインポートし、frida-compile でコンパイルして、frida-fuzzer がターゲットアプリに注入するエージェントを生成する必要があります。
ファザーのロジックの大部分はエージェントにあります。
ハーネスは以下の形式になります。
var fuzz = require("./fuzz");
var TARGET_MODULE = "test_linux64";
var TARGET_FUNCTION = DebugSymbol.fromName("target_func").address;;
var RET_TYPE = "void";
var ARGS_TYPES = ['pointer', 'int'];
var func_handle = new NativeFunction(TARGET_FUNCTION, RET_TYPE, ARGS_TYPES, { traps: 'all' });
fuzz.target_module = TARGET_MODULE;
var payload_mem = Memory.alloc(fuzz.config.MAX_FILE);
fuzz.fuzzer_test_one_input = function (/* Uint8Array */ payload) {
Memory.writeByteArray(payload_mem, payload, payload.length);
func_handle(payload_mem, payload.length);
}
fuzz.fuzzer_test_one_input は必須です。fuzz.target_module を指定しない場合、実行されるすべてのコードがインストルメントされます。
また、fuzz.manual_loop_start = true を設定することで、コールバック内で fuzz.fuzzing_loop() を呼び出すことをファザーに伝え、自動的に呼び出さないようにすることができます(例:Android アプリでボタンがクリックされたときにファジングを開始する場合など)。
コールバック fuzz.init_callback を設定すると、ファザーが開始準備ができたときにコードを実行できます。例として tests/test_java.js を参照してください。
fuzz.dictionary は古典的なファザーの辞書で、アイテム(受け入れられる型は Array、ArrayBuffer、Uint8Array、String)を追加できる配列であり、変異器で追加の値として使用されます。例として tests/test_libxml2.js を参照してください。
frida-fuzzer は以下の引数を受け付けます:
出力フォルダを指定しない場合、/tmp の下に一時フォルダが作成されます。
初期シードを含むフォルダを指定しない場合、未定義のシード 0000 が開始シードとして使用されます。
ローカルアプリケーションをファジングする場合、frida-fuzzer の前に system-config を実行してシステムパラメータを調整し、処理を高速化するとよいでしょう。
./frida-fuzzer -spawn ./tests/test_linux64 を実行すると、端末に次のようなステータス画面が表示されます:

また、fuzz/fuzzer.js にカスタムステージを簡単に追加し、fuzz/index.js のステージリストに追加することができます。
ファザーをカスタマイズするには、fuzz/config.js を編集します。
変更したい変数は、MAP_SIZE(ファジングするコードが小さい場合は減らすことで少し高速化できます)、MAX_FILE(生成される入力の最大サイズ)、QUEUE_CACHE_MAX_SIZE(特に Android で速度向上のためにキューキャッシュサイズを増やす)です。
tests 内のサンプル Android アプリにあるネイティブ共有ライブラリをファジングしてみましょう。
仮想デバイスで root 権限があることを確認してください:
host$ adb root
リポジトリのリリースページから Android x86_64 用の frida-server をダウンロードし、/data/local/tmp の下にコピーします(adb push を使用)。
シェルを起動し、frida-server を実行します:
device# cd /data/local/tmp
device# ./frida-server
次に、テストアプリ tests/app-debug.apk をエミュレータウィンドウにドラッグ&ドロップしてインストールします。
その後、アプリを開きます。
エージェントスクリプトを frida-compile でコンパイルします:
host$ frida-compile -x tests/test_ndk_x64.js -o fuzzer-agent.js
エミュレータでアプリを開きます。
テストアプリに含まれる libnative-lib.so ライブラリの test_func 関数を次のコマンドでファジングします:
host$ ./frida-fuzzer -U -o output_folder/ com.example.ndktest1
興味深いテストケースとクラッシュは両方とも output_folder に保存されます。
お楽しみください。

OSS コミュニティの皆さん、貢献したい方のために多くの TODO があります。
これらの機能のいずれかについて疑問があれば、Twitter で DM してください。
機能の提案については、Issues セクション があります。
| -i FOLDER | 初期シードを含むフォルダ |
| -o FOLDER | 中間シードとクラッシュを含む出力フォルダ |
| -U | USB に接続 |
| -spawn | 単にアタッチする代わりにスポーンしてアタッチ |
| -script SCRIPT | スクリプトファイル名(デフォルトは fuzzer-agent.js) |