
USBマスストレージトラフィックをブロックおよびファイルレベルで傍受・解析し、USBデバイスをエミュレートし、セキュリティ研究、フォレンジック、TOCTOU脆弱性テストのためのカスタムPythonスタブをサポートします。

usb-spy は、WiFi またはイーサネット対応マイクロコントローラをベースに構築された USB マスストレージトラフィックアナライザです。
このボードは、実際のストレージデータが WiFi またはイーサネットを介してリモートサーバーから提供される一方で、ディスクイメージ(FAT または任意のファイルシステム)を偽の USB マスストレージデバイスとしてターゲットシステムに公開します。この構成により、usb-spy はターゲットが実行するすべてのブロックアクセスを傍受して分析できます。
usb-spy は生のブロックレベルのトレースに加えて、ファイルシステムを理解し、アクセスされた各ブロックを対応するファイルやディレクトリにマッピングできるため、生のセクタ番号だけでなく、どのファイルが読み書きされているかを即座に確認できます。
さらに、usb-spy は JSON 設定ファイルを介してベンダー ID、プロダクト ID、シリアル番号、製造元、製品名などのデバイスプロパティをカスタマイズすることで、あらゆる USB デバイスをエミュレートできます。これにより、テストや分析目的で特定の USB デバイスを偽装することができます。
このツールはユーザーが作成した Python スタブを通じて簡単に拡張でき、USB の読み取り/書き込みイベントやブロックレベルの操作を処理するカスタムロジックを実装できます。

サポートされているファイルシステムが検出されると、usb-spy は次の処理を行います:
現在サポートされているファイルシステム:
今後、追加のファイルシステムサポートが予定されています。
ファイルシステムがサポートされていない場合でも、usb-spy は使用可能です:
これにより、未知のファイルシステムやカスタム/プロプライエタリなファイルシステムでも usb-spy が有用であり続けます。

各サポート対象ボードのファームウェアビルド手順は以下に記載されています:
ソースコードは src ディレクトリにあります。FAT イメージをロードし、TCP ポート経由で公開し、イメージへのすべてのアクセスをログに記録します。ファイルとディレクトリ情報を表示するために、ツールは TheSleuthKit ライブラリに依存しています。
ビルドするには、ルートディレクトリで以下のコマンドを実行します
すべてのサブモジュールを取得
git submodule update --init --recursive
次に waf configure コマンドを実行します。
./waf configure
必要な依存関係をすべて確認しビルドした後、プロジェクトを実際にビルドするには以下を実行します。
./waf build
バイナリは wbuild ディレクトリに生成されます。
mtools ユーティリティパッケージを使用すると簡単に行えます。
2 MB のファイルを作成
dd if=/dev/zero of=disk.img bs=1M count=2
FAT ファイルシステムを配置(FAT32 の場合は -F を使用、それ以外は自動)
mformat -i disk.img ::
ファイルを追加
mcopy -i disk.img example.txt ::
ファイル一覧を表示
mdir -i disk.img ::
ファイルを抽出
mcopy -i disk.img ::/example.txt extracted.txt
新しく作成したイメージでスパイを実行
./usb-spy -v disk.img
ボードをターゲットの USB ポートに接続します。
特定の USB デバイスをエミュレートするには、json 設定ファイルでパラメータを上書きできます:
次の json ファイルは Kingston DataTraveler USB デバイスをエミュレートします:
{
"vendor_id": 2385,
"product_id": 5734,
"bcd_device": 272,
"product_rev": "3.0",
"manufacturer": "Kingston",
"product_name": "DataTraveler",
"serial": "509C4BBFACCDE742880C026B",
"language": 1033
}
この設定ファイルでスパイを実行
./usb-spy -c config/kingston.json disk.img
このデバイスの dmesg 出力:
usb 1-8: New USB device found, idVendor=0951, idProduct=1666, bcdDevice= 1.10
usb 1-8: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-8: Product: DataTraveler
usb 1-8: Manufacturer: Kingston
usb 1-8: SerialNumber: 509C4BBFACCDE742880C026B
usb-storage 1-8:1.0: USB Mass Storage device detected
scsi host6: usb-storage 1-8:1.0
scsi 6:0:0:0: Direct-Access Kingston DataTraveler 3.0 PQ: 0 ANSI: 2
すべての読み取り/書き込みイベントに対して独自のロジックを実装したい場合は、Python で簡単に行えます。
次の dummy イメージのように、python で USBImage クラスを実装します:
class USBImage:
def __init__(self, *args, **kwargs):
"""
Initialize the USBImage.
:param args: should contain:
- filename: The name of the file to manage.
:param kwargs: Arbitrary arguments passed from the c++ command line including:
readOnly: Whether the interface is read-only.
verbose: Whether to enable verbose logging.
block: Whether to enable block mode.
"""
pass
def getBlockNumber(self):
"""Get block number"""
return 100
def getBlockSize(self):
"""Get block size"""
return 512
def read(self, lba, buffer, size):
"""Read block"""
print(f"read block={lba} size={size}")
for i in range(size):
buffer[i] = (lba + i) % 256 # Simulate reading data
return size
def write(self, lba, buffer, size):
"""Write block"""
print(f"write block={lba} size={size}")
print(buffer)
return size
def flush(self):
"""Flush block"""
print("flush data")
そして、Python モジュールを指定してスパイを実行します。
./usb-spy --py python/dummy.py disk.img
コマンドラインから Python クラスに任意の引数を渡すこともできます。 引数は kwargs で利用可能です。
./usb-spy --py python/dummy.py --py-args arg1=2 --py-args arg2=Hello disk.img
また、usb-spy バイナリにネイティブで実装されている内容の完全な実装(約100行のコード)を提供する rawimage の例から始めることもできます。
このプロジェクトは「現状のまま」提供されます。正確性、セキュリティ、特定の目的への適合性について一切保証しません。
ツールおよびファームウェアは自己責任で使用してください。著者および貢献者は、本ソフトウェアまたはハードウェアの使用に起因する損害、データ損失、法的結果について一切の責任を負いません。
貢献を歓迎します!以下の手順に従ってください:
このプロジェクトは GNU General Public License v3.0 の下でライセンスされています。詳細は LICENSE ファイルを参照してください。