Chapter 13
USB とその他の有線インタフェース — 記述子が語る正体
この章のゴール.
USB を持つ組み込み機器を、記述子(自己申告のプロフィール)の読み出しから通信の観測・注入まで 外からテストする方法をつかむこと。あわせて CAN・イーサネット・その他の有線を、 「バスを覗く・偽者を混ぜる」という 06 章と同じ発想で扱えるようになること。
この章で使う既出の用語(定義は各リンク先). USB(01 章 2 節)、オラクル(01 章 8 節)、記録(01 章 4 節)、突入電流(03 章 2 節)、I²C(06 章 1 節)、GATT(09 章 8 節)、接続(09 章 2 節)、ファジング(10 章)、低層(10 章 6 節)、中間(11 章 3 節)
1. USB は「自己紹介」から始まる
USB 機器は接続直後に列挙(enumeration)という自己紹介を行う。「自分は何者か(ベンダ ID・製品 ID)、どんなクラスか(キーボード?シリアル?ストレージ?)、どんなエンドポイントを持つか」を記述子(descriptor)として PC に申告する。ここを読むだけで、機器の正体と外から触れる面がかなり見える。
記述子(descriptor) とは、USB 機器が自分の構成を PC に伝えるための構造化データのこと。デバイス記述子・コンフィグ記述子・インタフェース記述子・エンドポイント記述子と階層になっている(GATT の木構造、09 章に似ている)。
2. 記述子と列挙を読む
lsusb -v(Linux): VID/PID、クラス、全記述子をダンプ。まずこれ- 文字列記述子: 製品名・シリアル。デバッグ用の名前や本物のシリアルが漏れていないか
- クラス: HID/CDC(シリアル)/MSC(ストレージ)/独自ベンダクラス。宣言しているクラスと実際の機能が合っているか
- 複合デバイス: 一つの機器が複数の顔(シリアル+ストレージ等)を持つとき、余計な顔が生えていないか
lsusb -v -d 1234:5678 # 対象の VID:PID の全記述子を表示
dmesg -w # 挿抜時のカーネルログで列挙の成否・再試行を観測3. 通信を覗く — USB キャプチャ
I²C をロジアナで、ネットワークを Wireshark で覗いた(06 章・11 章)のと同じく、USB もキャプチャできる。
- Wireshark + usbmon(Linux)/ USBPcap(Windows): ホストと機器の間の全転送を記録
- ハードウェアのプロトコルアナライザ(例: 各社の USB アナライザ): より低層・確実だが高価
- 観測点として: 「ボタン操作が何の転送になるか」「独自ベンダコマンドの中身」を可視化し、平文の秘密や異常を探す
4. 偽者・異常者を演じる — Facedancer 系
06 章で「偽センサ」を演じたように、USB でも PC 側から偽の USB デバイスを合成して、相手(ホスト側の機器や、機器がホストの場合の周辺)を試せる。
- Facedancer(GreatFET 等): Python で任意の USB デバイスをエミュレート。記述子を故意に壊す、異常なエンドポイントを申告する、列挙の途中で妙な応答を返す——USB スタックのファジング(16 章)
- 機器が USB ホストなら、そこに挿す偽の周辺(偽キーボード・偽ストレージ)を演じて、認識・権限・異常入力への耐性を試す
- 逆に機器がデバイスなら、PC 側の自作ドライバ/スクリプトから異常なコントロール転送を送り込む(
pyusb)
import usb.core
dev = usb.core.find(idVendor=0x1234, idProduct=0x5678)
# 独自ベンダコマンドを直接叩く(bmRequestType, bRequest, wValue, wIndex, data)
dev.ctrl_transfer(0x40, 0x01, 0xFFFF, 0, b"\xff"*64) # 境界値・不正値を注入5. USB 以外の有線 — 発想は同じ
| バス | 覗く道具 | 偽者・注入 | 主な観点 |
|---|---|---|---|
| CAN(車載・産業) | can-utils(candump)、CANアナライザ | cansend で任意フレーム注入 | ID フィルタ、異常フレーム耐性、フラッド |
| イーサネット(有線) | Wireshark、11 章の道具一式 | パケット注入、中間者 | 11 章と同じ |
| RS-485 / Modbus | シリアルアナライザ | 偽マスタ/偽スレーブ | アドレス衝突、CRC、タイムアウト |
| 1-Wire / その他独自 | ロジアナ(04 章) | 偽デバイス | タイミング、存在検出 |
どれも「バスを受動的に覗く」→「偽の参加者を混ぜて能動的に試す」という 06 章と同じ二段構えで攻められる。
6. 接続の乱れ — 挿抜と過負荷
- 挿抜の連打: 高速に抜き挿しして列挙が毎回成功するか、リソースが漏れないか
- 給電の境界: バスパワーの電流上限付近、突入電流(03 章の電流観測と併用)
- 過負荷: 大量転送・大量フレーム(CAN フラッド)でバッファが溢れないか(16 章)
7. 何をオラクルにするか
- 記述子が仕様どおりで、余計な顔・漏れた文字列がない
- 独自コマンドが不正値を拒否し、クラッシュしない
- 偽デバイス/異常フレームに耐えて回復する
- 挿抜・過負荷でリソースが枯渇しない