
TriforceAFLを使用したLinuxシステムコールファザー
新着: TriforceAFL と TLSF を試してみたい方のために、Richard Johnson が両方をインストールする Dockerfile(さらに Linux カーネルまでビルドしてくれる)を作成しました。こちらから入手できます: https://hub.docker.com/r/moflow/afl-triforce/tags/。
これは、AFL と QEMU を使用して Linux x86_64 カーネルのシステムコールファジングを実行するためのファイル群です。使用するには、https://github.com/nccgroup/TriforceAFL から TriforceAFL と、ファジング対象のカーネルイメージが必要です。スクリプトは TriforceAFL が $TAFL または ../TriforceAFL/ にあることを前提としています(注: testAfl のビルドには ../TriforceAFL/config.h が存在する必要があります)。
ビルドするには:
make
実行するには、まずカーネルを ./kern/bzImage にインストールし、/proc/kallsyms を ./kern/kallsyms に展開します。環境変数 K=kern をカーネルを指すように設定します。そして次のように実行します:
make inputs
./runFuzz -M M0
runFuzz スクリプトは常にマスター/スレーブモードで実行されるため、マスター名またはスレーブ名を指定する必要があることに注意してください。詳細な使用方法については runFuzz スクリプトを参照してください。
また、これによって作成されるのは少数のサンプル入力のみであることにも注意してください。多数の重要なシステムコールをテストするには、各システムコールの例を1つずつ、あるいは少なくともシステムコールの各「形状」ごとに1つの例を生成することをお勧めします。これらは inputs/ に配置する必要があります。例については gen2.py を参照してください。
テストケース(クラッシュなど)を再現するには、次のように実行します:
./runTest inputs/ex1
./runTest outputs/crashes/id*
また、エミュレート環境の外でドライバを実行することもできます。-t オプションで実行し、-vv で冗長なログを出力し、-x で実際のシステムコールの実行を行わないようにします:
./driver -tvvx < inputs/ex1
strace ./driver -t < inputs/ex1
カーネルを起動して対話的にテストを実行できると便利な場合があります。そのためには、rootTemplate ファイルを適宜編集し(たとえば、ルートファイルシステムにテストツールを追加するなど)、次のように実行します:
./runCmd
シェル以外のコマンドも、runCmd のコマンドライン引数として指定することで呼び出すことができます。
注: シェルの使用が終わったら、^A-c で QEMU プロンプトを表示し、quit と入力します。
デバッグは、デバッグシンボルを有効にしてビルドされたカーネルを使うと最も簡単です。runTest を使用してカーネルを起動し、ドライバを通じてテストを実行するか、runCmd を使用してシェルから手動でテストケースを実行します。実行スクリプトを編集して、afl-qemu-system-trace の起動時に -s オプションを指定します。これにより TCP ポート 1234 で gdb サポートが有効になります。getvmlinux を使用して bzImage カーネルから vmlinux カーネルイメージを抽出し、システム起動後に gdb を実行します:
cp kern/bzImage .
./getvmlinux
gdb ./vmlinux
target remote :1234
break somefunction
continue
runTest がクラッシュを引き起こした後、または runCmd で手動でバグを引き起こす前に、デバッガを接続できます。
Linux ソースはデフォルトで最適化を有効にしてコンパイルされることに注意してください。これによりデバッグが混乱し、困難になる可能性があります。ファイルが含まれるサブディレクトリの Linux make ファイルを編集し、Makefile に CFLAGS_name.o = -O0 を追加することで、ファイル単位で最適化を無効にできます。たとえば、kernel/Makefile を編集して CFLAGS_sys_ni.o = -O0 を追加すると、kernel/sys_ni.o のビルド時に最適化が無効になります。
getSyms シェルスクリプトは runCmd を使用して cat /proc/kallsyms を実行し、その出力を kallsyms というローカルファイルに抽出します。これは通常、ファジングのためにカーネルを準備するために使用されます:
K=yourKernDir ./getSyms を実行して kallsyms を取得しますmv kallsyms yourKernDir を実行してインストールします注: Linux 2.* カーネルをファジングする場合は、CPU タイマーを有効にする必要があります。タイマーが有効でない場合、パニックおよびログ検出が正しく動作しないようで、パニックがハングアップを引き起こします。タイマーを有効にするには、driver.c 内で startForkserver(0) の代わりに startForkserver(1) を呼び出します。この問題は Linux 3.* および Linux 4.* カーネルでは発生しないようです。