Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
gdbfuzz — ハードウェアブレークポイントを使用した組み込みシステムのファジング | Kitploit
ツール/GitHubGitHub/boschresearch/gdbfuzz
組み込みシステムセキュリティ脆弱性分析デバッガファジングハードウェアセキュリティバイナリ解析論文と研究学習と教育ファームウェア解析Archived
GitHubboschresearch/gdbfuzz

gdbfuzz

ハードウェアブレークポイントを使用した組み込みシステムのファジング

194202年前Kitploit レビュー済み

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有
リポジトリを見る

GDBFuzz: デバッガ駆動ファジング

これは論文「Fuzzing Embedded Systems using Debugger Interfaces」の付属コードです。 論文のプレプリントはこちら https://publications.cispa.saarland/3950/ から入手できます。このコードにより、ユーザーは論文で報告された結果を再現し、拡張することができます。 結果を報告、再現、拡張する際には、上記の論文を引用してください。

フォルダ構造

root@kitploit:~
.
    ├── benchmark               # Googleのファザーテストスイートをビルドし、実験を実行するスクリプト
    ├── dependencies            # GDBFuzzの依存関係をインストールするMakefile
    ├── evaluation              # 論文で提示された生の実験データ
    ├── example_firmware        # 評価に使用される組み込みサンプルアプリケーション
    ├── example_programs        # GDBFuzzをテストするためのコンパイル済みサンプルプログラムと設定
    ├── src                     # GDBFuzzの実装
    ├── Dockerfile              # すべてのGDBFuzz依存関係がインストールされたDockerイメージを作成するため
    ├── LICENSE                 # ライセンス
    ├── Makefile                # Dockerイメージを作成するか、GDBFuzzをローカルにインストールするMakefile
    └── README.md               # このREADMEファイル

プロジェクトの目的

GDBFuzz のアイデアは、マイクロコントローラのハードウェアブレークポイントをカバレッジガイド付きファジングのフィードバックとして活用することです。そのために、広範な適用可能性を可能にする汎用インターフェースとしてGDBを使用します。ファームウェアのバイナリ解析にはGhidraを使用します。このコードには、メソッドを評価するためのベンチマーク設定が含まれています。また、サンプルファームウェアファイルも含まれています。

はじめに

GDBFuzzは組み込みシステム向けのカバレッジガイド付きファジングを可能にしますが、評価目的で一般的なユーザーアプリケーションをファジングすることもできます。マイクロコントローラでのファジングには、テスト対象デバイスにファズデータを問題なく送信できるように、GDBFuzzをローカルにインストールすることをお勧めします。

ローカルインストール

GDBFuzz はUbuntu 20.04 LTSおよびRaspberry Pi OS 32ビットでテストされています。 前提条件はjavaおよびpython3です。まず、新しい仮想環境を作成し、すべての依存関係をインストールします。

root@kitploit:~
virtualenv .venv
source .venv/bin/activate
make
chmod a+x ./src/GDBFuzz/main.py

サンプルプログラムでローカル実行

GDBFuzzは以下のキーを持つ設定ファイルから設定を読み取ります。

root@kitploit:~
[SUT]
# テスト対象バイナリファイルへのパス。
# 例えば、.elfファイルや.binファイルなど。
binary_file_path = <path>

# CFGのルートノードのアドレス。
# ブレークポイントはこのCFGのノードに配置されます。
# 例: 'LLVMFuzzerTestOneInput' または 'main'
entrypoint = <entrypoint>

# ブレークポイントがローテーションされるまでに、ブレークポイントがヒットせずに実行される入力数。
until_rotate_breakpoints = <number>


# 同時に配置できるブレークポイントの最大数。
max_breakpoints = <number>

# 無視する関数のブラックリスト。
# ignore_functionsはスペース区切りの関数名リストです。例: 'malloc free'
ignore_functions = <スペース区切りのリスト>

# {Hardware, QEMU, SUTRunsOnHost} のいずれか
# Hardware: 外部コンポーネントがgdbサーバーを起動し、GDBFuzzがこのgdbサーバーに接続します。
# QEMU: GDBFuzzがQEMUを起動します。QEMUはbinary_file_pathをエミュレートし、gdbserverを起動します。
# SUTRunsOnHost: GDBFuzzがGDB内でターゲットプログラムを起動します。
target_mode = <mode>

# ghidraを起動し、SUTを解析し、ghidraブリッジサーバーを手動で起動したい場合はFalseに設定します。
start_ghidra = True


# ソフトウェアブレークポイント(エラー処理コード用)を設定するアドレスのスペース区切りリスト。
# これらの実行はクラッシュと見なされます。
# 例: software_breakpoint_addresses = 0x123 0x432
software_breakpoint_addresses = 


# トリガーされたすべてのソフトウェアブレークポイントをエラーと見なすかどうか
consider_sw_breakpoint_as_error = False

[SUTConnection]
# 'SUT_connection_path' ファイル内のクラス 'SUT_connection_class' は、
# 入力がSUTにどのように送信されるかを実装します。
# 入力は、例えばWi-Fi、シリアル、Bluetoothなどを介して送信できます。
# このクラスは ./connections/SUTConnection.py を継承する必要があります。
# 詳細については ./connections/SUTConnection.py を参照してください。
SUT_connection_file = FIFOConnection.py

[GDB]
path_to_gdb = gdb-multiarch
#アドレス:ポート形式で記述
gdb_server_address = localhost:4242

[Fuzzer]
# バイト単位
maximum_input_length = 100000
# 秒単位
single_run_timeout = 20
# 秒単位
total_runtime = 3600

# オプション
# 各ファイルに1つのシードが含まれるディレクトリへのパス。シードを使用しない場合は、値を空のままにします。
seeds_directory = 

[BreakpointStrategy]
# 基本ブロックを選択する戦略は、
# 'src/GDBFuzz/breakpoint_strategies/' にあります。
# 論文では以下の戦略を使用しています。
# 'RandomBasicBlockStrategy.py' - 未到達の基本ブロックをランダムに選択
# 'RandomBasicBlockNoDomStrategy.py' - 上記と似ていますが、到達ノードを導出するために支配関係を使用しません。
# 'RandomBasicBlockNoCorpusStrategy.py' - 最初のものと似ていますが、入力コーパスの成長を防ぎ、したがってカバレッジ測定を伴うブラックボックスファジングのように動作します。
# 'BlackboxStrategy.py' - ブレークポイントを設定しません
breakpoint_strategy_file = RandomBasicBlockStrategy.py

[Dependencies]
path_to_qemu = dependencies/qemu/build/x86_64-linux-user/qemu-x86_64
path_to_ghidra = dependencies/ghidra


[LogsAndVisualizations]
# {DEBUG, INFO, WARNING, ERROR, CRITICAL} のいずれか
loglevel = INFO

# 出力ファイル(例:グラフ、ログファイル)が保存されるディレクトリへのパス。
output_directory = ./output

# Trueに設定すると、MQTTクライアントがUI要素(例:グラフ)を送信します。
enable_UI = False

サンプル設定ファイルは ./example_programs/ にあり、benchmark/benchSUTs/GDBFuzz_wrapper/common/ にあるファジングハーネスを使用してコンパイルされたサンプルプログラムも同梱されています。 以下のコマンドで1時間ファジングを開始します。

root@kitploit:~
chmod a+x ./example_programs/json-2017-02-12
./src/GDBFuzz/main.py --config ./example_programs/fuzz_json.cfg

最初にGhidraがバイナリ実行ファイルを解析する出力が表示され、その後ブレークポイントが再配置またはヒットされたときにメッセージが表示されます。

ファジング出力

設定ファイルで指定された output_directory に応じて、trial-0 というフォルダが作成され、以下の構造になります。

root@kitploit:~
.
    ├── corpus            # 入力コーパスを含むフォルダ。
    ├── crashes           # クラッシュする入力(ある場合)を含むフォルダ。
    ├── cfg               # 隣接リスト形式の制御フローグラフ。
    ├── fuzzer_stats      # ファジングキャンペーンの統計。
    ├── plot_data         # ファジングキャンペーンの相対時間にどの基本ブロックに到達したかを示すテーブル。
    ├── reverse_cfg       # 逆制御フローグラフ。

GUIモードでのGhidraの使用

設定ファイルで start_ghidra = False を設定することで、GDBFuzzはGUIモードで動作するGhidraインスタンスに接続します。そのためには、ghidra_bridgeプラグインをスクリプトマネージャーから手動で起動する必要があります。ファジング中に、到達したプログラムブロックが緑色でハイライトされます。

LinuxユーザープログラムでのGDBFuzz

Linuxユーザーアプリケーションのファジングでは、GDBFuzzはAFL、AFL++、libFuzzerなど、ほぼすべてのファザーで使用される標準の LLVMFuzzOneInput エントリーポイントを利用します。 benchmark/benchSUTs/GDBFuzz_wrapper/common には、互換性のある任意のファズハーネスを、/tmp/fromGDBFuzz にある名前付きパイプを介して入力を取得するスタンドアロンプログラムにコンパイルするためのラッパーがあります。 これにより、明確に定義された入力インターフェースを介してデータを消費する組み込みデバイスをシミュレートし、任意のアプリケーションでGDBFuzzを実行できます。便宜上、benchmark/benchSUTs にスクリプトを作成し、後述するようにラッパーを使用して評価のすべてのプログラムをコンパイルします。

注: GDBFuzzはLinuxユーザーアプリケーションをファジングするためのものではありません。その場合はAFL++や他のファザーを使用してください。ラッパーは、大規模なベンチマークと比較を可能にするための評価目的でのみ存在します。

Dockerコンテナでのインストールと実行

私たちのアプローチの全体的な有効性は、Dockerコンテナとしてデプロイされた大規模ベンチマークで示されています。

root@kitploit:~
make dockerimage

Dockerコンテナで上記の実験を実行するには(設定ファイルで指定された1時間)、example_programs と output フォルダをボリュームとしてマウントし、次のようにGDBFuzzを起動します。

root@kitploit:~
chmod a+x ./example_programs/json-2017-02-12
docker run -it --env CONFIG_FILE=/example_programs/fuzz_json_docker_qemu.cfg -v $(pwd)/example_programs:/example_programs -v $(pwd)/output:/output gdbfuzz:1.0

現在の作業ディレクトリに、上記で説明した構造の出力フォルダが表示されるはずです。

詳細な手順

私たちの評価は2つの部分に分かれています。

  1. 意図されたセットアップ、つまりハードウェア上でのGDBFuzz。
  2. 結果の独立した分析と比較を可能にするエミュレート環境でのGDBFuzz。

GDBFuzzは任意のGDBサーバーと、したがってほとんどのマイクロコントローラ用デバッグプローブで動作します。

GDBFuzz vs ブラックボックス(RQ1)

論文のRQ1に関して、example_firmware にある異なるファームウェアを持つ異なるマイクロコントローラ上でGDBFuzzを実行します。 各実験で、GDBFuzzを RandomBasicBlock 戦略と RandomBasicBlockNoCorpus 戦略で実行します。後者はフィードバックなしのファジングのように動作しますが、達成されたカバレッジを測定することはできます。 RQ1に答えるために、RandomBasicBlock 戦略と RandomBasicBlockNoCorpus 戦略の達成されたカバレッジを比較します。 対応する設定ファイルは各サブフォルダにあり、4つの開発ボードでのファジング設定方法を以下で説明します。

STM32 B-L4S5I-IOT01A ボードでの GDBFuzz

GDBFuzzはGDBサーバーへのアクセスを必要とします。この場合、B-L4S5I-IOT01Aとそのオンボードデバッガが使用されます。このオンボードデバッガは 'st-util' プログラムを介してGDBサーバーをセットアップし、localhost:4242 でこのGDBサーバーへのアクセスを可能にします。

  • STLINKドライバをインストール リンク
  • MCUボードとPCをUSBで接続(MCUボードでは、'USB STLINK'とラベル付けされたUSBコネクタに接続)
root@kitploit:~
sudo apt-get install stlink-tools gdb-multiarch

STM32 B-L4S5I-IOT01A用のファームウェア(例:arduinojsonプロジェクト)をビルドしてフラッシュします。

前提条件:platformio (pio) をインストール

root@kitploit:~
cd ./example_firmware/stm32_disco_arduinojson/
pio run --target upload

参考までに:platformioはSUTの .elf ファイルをここに保存します:./example_firmware/stm32_disco_arduinojson/.pio/build/disco_l4s5i_iot01a/firmware.elf この .elf ファイルは後でGhidraのユーザー設定でも使用されます。

新しいターミナルを開き、以下を実行してGDBサーバーを起動します:

root@kitploit:~
st-util

arduinojsonのユーザー設定でGDBFuzzを実行します。USBポートを介してマイクロコントローラにデータを送信できます。マイクロコントローラはこのデータをシリアル経由でSUTに転送します。この場合、/dev/ttyACM0 がマイクロコントローラボードへのUSBデバイスです。システムが別のデバイスをマイクロコントローラボードに割り当てた場合は、設定ファイル内の /dev/ttyACM0 をそのデバイスに変更してください。

root@kitploit:~
./src/GDBFuzz/main.py --config ./example_firmware/stm32_disco_arduinojson/fuzz_serial_json.cfg

ファザー統計とログは ./output/... ディレクトリにあります。

CY8CKIT-062-WiFi-BT ボードでの GDBFuzz

pyocd をインストール:

root@kitploit:~
pip install --upgrade pip 'mbed-ls>=1.7.1' 'pyocd>=0.16'

デバイスに 'KitProg v3' が搭載されていることを確認し、適切なボタンを押してボードを 'Arm DAPLink' モードにします。 GDBサーバーを起動:

root@kitploit:~
pyocd gdbserver --persist

ファームウェアをフラッシュし、ファジングを開始します。例:

root@kitploit:~
gdb-multiarch
    target remote :3333
    load ./example_firmware/CY8CKIT_json/mtb-example-psoc6-uart-transmit-receive.elf
    monitor reset
./src/GDBFuzz/main.py --config ./example_firmware/CY8CKIT_json/fuzz_serial_json.cfg

ESP32 と Segger J-Link での GDBFuzz

  • ESP32 SDK をインストール

ESP32用のファームウェア(例:platformioを使用したarduinojsonの例)をビルドしてフラッシュします。

root@kitploit:~
cd ./example_firmware/esp32_arduinojson/
pio run --target upload

J-Linkデバッガ用のopenocd設定ファイルに次の行を追加します:jlink.cfg

root@kitploit:~
adapter speed 10000

新しいターミナルを開き、以下を実行してGDBサーバーを起動します:

root@kitploit:~
get_idf
openocd -f interface/jlink.cfg -f target/esp32.cfg -c "telnet_port 7777" -c "gdb_port 8888"

arduinojsonのユーザー設定でGDBFuzzを実行します。USBポートを介してマイクロコントローラにデータを送信できます。マイクロコントローラはこのデータをシリアル経由でSUTに転送します。この場合、/dev/ttyUSB0 がマイクロコントローラボードへのUSBデバイスです。システムが別のデバイスをマイクロコントローラボードに割り当てた場合は、設定ファイル内の /dev/ttyUSB0 をそのデバイスに変更してください。

root@kitploit:~
./src/GDBFuzz/main.py --config ./example_firmware/esp32_arduinojson/fuzz_serial.cfg

ファザー統計とログは ./output/... ディレクトリにあります。

MSP430F5529LP での GDBFuzz

https://www.ti.com/tool/MSP430-GCC-OPENSOURCE からTI MSP430 GCCをインストール

GDBサーバーを起動

root@kitploit:~
./gdb_agent_console libmsp430.so

または(より安定)。https://github.com/dlbeer/mspdebug/ からmspdebugをビルドして使用:

root@kitploit:~
until mspdebug --fet-skip-close --force-reset tilib "opt gdb_loop True" gdb ; do sleep 1 ; done

GhidraはTI MSP430コントローラ用のバイナリをそのまま解析できません。これを修正するには、Ghidra GUIでファイルをインポートし、アーキテクチャとしてMSP430Xを選択し、自動解析をスキップします。次に、「シンボルテーブル」を開き、名前でソートし、$C$L* のような名前のシンボルをすべて削除します。これで自動解析を実行できます。解析後、Ghidra GUIからghidraブリッジを手動で起動し、次にGDBFuzzを起動します。

root@kitploit:~
./src/GDBFuzz/main.py --config ./example_firmware/msp430_arduinojson/fuzz_serial.cfg

USB ファジング

pyusb を使用して非rootユーザーとしてUSBデバイスにアクセスするには、適切なルールをudevに追加します。次の行を /etc/udev/rules.d/50-myusb.rules に貼り付けます:

root@kitploit:~
SUBSYSTEM=="usb", ATTRS{idVendor}=="1234", ATTRS{idProduct}=="5678" GROUP="usbusers", MODE="666"

udevをリロード:

root@kitploit:~
sudo udevadm control --reload
sudo udevadm trigger

Fuzzware との比較(RQ2)

論文のRQ2では、GDBFuzzをエミュレーションベースのアプローチ Fuzzware と比較します。最初に、前述のように同梱のファームウェアファイルに対してGDBFuzzとFuzzwareを実行します。 各GDBFuzz実験について、制御フローグラフファイルから有効な基本ブロックを含むファイルを次のように作成します:

root@kitploit:~
cut -d " " -f1 ./cfg > valid_bbs.txt

次に、fuzzwareの結果に対してカバレッジを再生できます: fuzzware genstats --valid-bb-file valid_bbs.txt

バグの発見(RQ3)

クラッシュまたはハングする入力が見つかると、それらは crashes フォルダに保存されます。評価中に、次の3つのバグを発見しました:

  1. STM32 USBデバイススタックの無限ループ。forループ内でuint8_tインデックス変数を攻撃者が制御可能なuint32_t変数とカウント比較したことが原因。
  2. Cypress JSONパーサーのバッファオーバーフロー。固定サイズの内部バッファに対する長さチェックの欠如が原因。
  3. Cypress JSONパーサーのNULLポインタ参照解除。検証チェックの欠如が原因。

Raspberry Pi 4a(8Gb)での GDBFuzz

GDBFuzzは、若干の変更を加えることでRaspberry Piホスト上でも実行できます:

  1. Ghidraを修正して32ビットOSで動作するようにする必要があります。

ファイル ./dependencies/ghidra/support/launch.sh:125 で、JAVA_HOME 変数をハードコードする必要があります。例:JAVA_HOME="/usr/lib/jvm/default-java"

  1. STLinkは正しく動作するためにバージョン1.7以上である必要があります。→ ソースからビルド

他のボードでの GDBFuzz

他のボードのソフトウェアをファジングするために、GDBFuzzは以下を必要とします:

  1. ハードウェアブレークポイントとGDB準拠のデバッグプローブを備えたマイクロコントローラ
  2. ファームウェアファイル
  3. 実行中のGDBServerと適切なGDBアプリケーション
  4. ファジングを開始するエントリーポイント(例:パーサー関数またはアドレス)
  5. エントリーポイントでのコードの実行をトリガーする入力インターフェース(例:シリアル接続)(src/GDBFuzz/connections を参照)

これらのプロパティはすべて設定ファイルで指定する必要があります。

フルベンチマークの実行(RQ4 - 8)

RQ 4〜8では、大規模なベンチマークを実行します。 まず、前述のようにDockerイメージをビルドし、benchmark/benchSUTs/GDBFuzz_wrapper/common にあるファジングハーネスを使用して、Googleの Fuzzer Test Suite からアプリケーションをコンパイルします。

root@kitploit:~
cd ./benchmark/benchSUTs
chmod a+x setup_benchmark_SUTs.py
make dockerbenchmarkimage

次に、benchmark/scripts/benchmark.py と benchmark/scripts/benchmark_aflpp.py のベンチマーク設定を要件に合わせて変更し(特に number_of_cores、trials、seconds_per_trial)、以下のコマンドでベンチマークを開始します:

root@kitploit:~
cd ./benchmark/scripts
./benchmark.py $(pwd)/../benchSUTs/SUTs/ SUTs.json
./benchmark_aflpp.py $(pwd)/../benchSUTs/SUTs/ SUTs.json

./benchmark/scripts に、各実験のプロットファイル(経過時間に対するカバレッジ)、ファザー統計ファイル、制御フローグラフファイルを含むフォルダが作成されます(evaluation/fuzzer_test_suite_qemu_runs と同様)。

[オプション] 可視化のインストールと可視化の例

GDBFuzzには、カバーされたノードの制御フローグラフをプロットするオプション機能があります。これはデフォルトでは無効になっています。このセクションの手順に従い、ユーザー設定で 'enable_UI' を 'True' に設定することで有効にできます。

ホスト側:

インストール

root@kitploit:~
sudo apt-get install graphviz

最新バージョンの nodeをインストールします。例:こちら の オプション2(リンク)を使用してください。オプション2を使用し、オプション1は使用しないでください。これにより、nodeとnpmの両方がインストールされます。参考までに、私たちのバージョン番号は次のとおりです(新しいバージョンでも動作するはずです):

root@kitploit:~
➜ node --version
v16.9.1
➜ npm --version
7.21.1

Web UIの依存関係をインストール:

root@kitploit:~
cd ./src/webui
npm install

mosquitto MQTTブローカーをインストールします。例:こちら(リンク)を参照

mosquittoブローカーの設定を更新:ファイル /etc/mosquitto/conf.d/mosquitto.conf を次の内容で置き換えます:

root@kitploit:~
listener 1883
allow_anonymous true

listener 9001
protocol websockets

mosquittoブローカーを再起動:

root@kitploit:~
sudo service mosquitto restart

mosquittoブローカーが実行中であることを確認:

root@kitploit:~
sudo service mosquitto status

出力に 'Active: active (running)' というテキストが含まれている必要があります。

Web UIを起動:

root@kitploit:~
cd ./src/webui
npm start

Webブラウザが自動的に 'http://localhost:3000/' で開くはずです。

enable_UI が True に設定されたユーザー設定ファイルを使用してGDBFuzzを起動します。上記のDockerコンテナとarduinojson SUTを使用できます。ただし、'enable_UI' を 'True' に設定してください。

'blue' でカバーされたノードがカバーされています。白いノードはカバーされていません。親ノードがカバーされている場合にのみ、カバーされていないノードを表示します(完全な制御フローグラフを描画すると、制御フローグラフが大きい場合に時間がかかりすぎます)。

ライセンス

GDBFuzzはAGPL-3.0ライセンスの下でオープンソース化されています。詳細については、 LICENSE ファイルを参照してください。

GDBFuzzに含まれるその他のオープンソースコンポーネントのリストについては、 ファイル 3rd-party-licenses.txt を参照してください。

ツールをダウンロード