Embedded Test 13 · USB とその他の有線インタフェース — 記述子が語る正体

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 章に似ている)。

USB は接続直後の「自己紹介」=記述子で正体が見えるデバイス記述子VID/PID・クラスコンフィグ記述子電力・構成インタフェース記述子HID/CDC/MSC…エンドポイント記述子転送の口lsusb -v で全部ダンプ余計な顔・漏れた文字列を探すusbmon / Facedancer覗く/偽デバイスを合成宣言したクラスと実機能が合うか、独自ベンダコマンドが不正値を拒否するか
図13-1 USB 記述子の階層と道具。

2. 記述子と列挙を読む

lsusb -v -d 1234:5678         # 対象の VID:PID の全記述子を表示
dmesg -w                       # 挿抜時のカーネルログで列挙の成否・再試行を観測

3. 通信を覗く — USB キャプチャ

I²C をロジアナで、ネットワークを Wireshark で覗いた(06 章・11 章)のと同じく、USB もキャプチャできる。

4. 偽者・異常者を演じる — Facedancer 系

06 章で「偽センサ」を演じたように、USB でも PC 側から偽の USB デバイスを合成して、相手(ホスト側の機器や、機器がホストの場合の周辺)を試せる。

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. 接続の乱れ — 挿抜と過負荷

7. 何をオラクルにするか

8. 手を動かす

USB記述子を読み解く


この章のポイント