2026年11月初頭、リバースエンジニアのAndrew Spode氏が鮮やかなハードウェアハック事例を公開した。通販で購入した千数百円程度のノーブランド子ども用トイカメラ上で、名作FPS『DOOM』を完全に移植・動作させることに成功したのだ。移動や射撃を含むフルゲームプレイに対応し、約30fpsの滑らかな描画とポリフォニック音効・BGMの再生を実現している。
カメラの外観はアニメ調のイラストがプリントされた安価なプラスチック筐体。外箱にはメーカー名や商標の記載がなく、取扱説明書に記された型番らしき文字は「X9S」のみ。しかしその内部には、32ビットの中国製SoC「HX3302B」が鎮座していた。
ノーブランド機器のサプライチェーンでは、開発費と原価を極限まで抑えるため、市場に流通する既成のターンキー主控チップ設計がそのまま採用される。そのため、単なる写真撮影には明らかにオーバースペックな組み込み演算能力が眠ることになる。さらに、早期市場投入を優先してセキュリティ検証が丸ごと省かれた汎用ファームウェアは、ハードウェアリバースエンジニアリングにとって理想的な実験場と化した。
図:小型カラー液晶上で30fpsで動作するDOOM。出典:Spode’s Abode
空きメモリ891KBでDOOMを駆動:千円トイカメラに秘められた120 MIPSの実力
分解前の段階では、ネット上に関連する技術資料は皆無に等しかった。唯一の手がかりとなったのは、試し撮りした写真のEXIFメタデータだった。製造者フィールドに「HX-Tech」と記されていたことから、ハッカーのJeroen Domburg氏が以前手掛けた分解事例との共通点が見出された。
Spode氏はバッテリー配線をはんだごてで外し、内部基板を取り出した。基板の中心にはHX3302Bチップ、そして8ピンの4MB SPIフラッシュメモリが実装されていた。プログラマでファームウェアを吸い出し解析を進めると、CPUアーキテクチャがOpenRISCであることが判明した。
マイクロベンチマークにより、チップの性能が明らかになった。この省電力チップは8KBのL1インストラクションキャッシュと8KBのデータキャッシュを搭載し、キャッシュスループットは164MB/sに達する。演算性能は最大120 MIPS、分岐予測ミスが頻発する負荷環境でも82 MIPSを維持した。この処理能力は、30年前の3D描画エンジンの射影計算を処理するには十二分なものだった。
最大のボトルネックとなったのはメモリ容量である。基板全体の物理RAMは2MB(読み出し速度65MB/s)。システムタスクとディスプレイのフレームバッファが大半を占有し、ユーザーコードに許されたフリーヒープはわずか891KBしかなかった。CPUサイクルには余裕があるものの、ゲームエンジン全体を1MB足らずの空間に収めなければならなかった。
図:トイカメラ基板上のHX3302Bチップと8ピンフラッシュメモリ。出典:Spode’s Abode
EXIFを活用したファームウェア抽出:検証を全廃したリファレンス設計
突破口となったのはファームウェアアップデート機能だった。カメラは起動時にSDカードのルートディレクトリにある Xly100s.bin というファイルを走査する。バイナリヘッダーにはチェックサム領域が用意されていたが、アップデータはハッシュ値の検証を一切行っていなかった。
さらにアップデート処理は部分上書き方式を採用していた。書き込みはフラッシュ先頭アドレスから開始され、書き込みサイズは入力ファイルのサイズに依存する。1MBのファイルを書き込んだ場合、先頭1MBだけが更新され、残り3MBの領域はそのまま保持される。ヘッダーのタイムスタンプを書き換えるだけでアップデートが発動するため、SDカードスロットは署名検証なしのコード注入ポートとして機能していた。
書き込み経路を確保した次に必要となったのは、メモリマップの把握である。Spode氏はメモリイメージを写真のEXIF領域に書き出して保存するという手法を考案した。標準的なJPEG規格では最大64KBのEXIFメタデータを格納できるが、カメラの既定ファームウェアは730バイト程度しか使用していなかった。
Spode氏は撮影保存ルーチンにパッチを当てた。専用のハードウェアJPEGエンコーダは内部ブートメモリに直接アクセスできないため、CPUを介して対象領域をEXIFバッファへ小分けに転送した。シャッターを1回切るごとに4KBのデータをキャプチャし、ポインタをスライドさせていく。わずか16枚の連写により、64KBのブートメモリ全体がSDカードに完全吸い出された。データを検証した結果、マスクROMによる保護はなく、すべての低レイヤーコードが露出していることが確認された。
29KBのコアコードをRAM常駐化:フラッシュXIP併用で4MBの壁を突破
PC版のオリジナル『DOOM』は動作に最低4MBのRAMを要求する。891KBという極小メモリ環境で動かすには、メモリ管理を根本から再構築する必要があった。カメラの未使用バッファを解放・整理したことで、使用可能ヒープをなんとか1.4MBまで拡張した。
しかし、寄せ集めのメモリ空間は深刻な断片化に直面した。元のエンジンは細かなメモリ確保を制限なく行うため、大きな連続領域の確保にすぐ失敗してしまう。Spode氏は小さなオブジェクト向けに専用メモリプールを構築し、ステージクリアごとにテクスチャや音声データを即座に破棄する運用を徹底してメモリ枯渇を防いだ。
コードセグメントの配置も大きな課題だった。260KBのゲームバイナリ全体をRAMに載せる余裕はない。HX3302BチップはSPIフラッシュからの直接実行(XIP)に対応しているが、計測の結果、フラッシュ上での実行はRAM実行に比べて18倍も遅いことが判明した。
エミュレータによるプロファイリングが解決の糸口となった。プロファイルデータによると、全実行時間の99%がわずか29KBのメインループ内で消費されていた。バイナリの大半は初期化処理やメニュー描画などの低頻度処理に過ぎない。そこでSpode氏は、29KBのホットループのみを物理RAMに常駐させ、残りのコールドパスはフラッシュからXIPで必要に応じて呼び出す構成を採用した。このハイブリッド実行により、厳しい制約下でもフルスピード動作を維持した。
図:ブランドロゴのないX9Sトイカメラの外観。出典:Spode’s Abode
メインループのバイパスと独自音源:直接ポーリングで30fpsを達成
メモリの制約を克服した後に立ちはだかったのは、ファームウェアのアーキテクチャだった。標準OSは協調型イベントループを採用しており、1フレームあたりのディスパッチオーバーヘッドだけで38ミリ秒を消費し、フレームレートを半減させていた。
Spode氏はメーカー製イベントフレームワークを完全に迂回し、極小の直接ポーリングループを自作した。物理GPIOレジスタを直接監視し、十字キーで移動、シャッターボタンで連射、電源ボタンの短押しで武器切り替え、長押しでメニュー呼び出し、壁への接触でドア開閉を判定するように実装。不要なスケジューリング処理を削ぎ落とした結果、フレームレートは安定して30fpsに到達した。
サウンド面でも制約があった。基板上のオーディオ出力は単一のPWMチャンネルのみだった。Spode氏はソフトウェアミキサーを実装し、複数の効果音を単一トラックのPCM信号に合成した。
さらにBGM再生も工夫された。原曲はMUS形式で作成されており、本来はFM音源チップを必要とするが、トイカメラにそのような回路はない。Spode氏はCPU負荷わずか2%で動作する超軽量ソフトウェア波形シンセサイザーを構築。矩形波と三角波による16和音ポリフォニック再生を実現し、内蔵の小型スピーカーから名作サウンドトラックを忠実に響かせることに成功した。
SCSIコマンドで任意コード実行:分解不要のUSB吸い出しルートを開拓
移植成功後、Spode氏はハック成果をコミュニティに安全に配布する方法を模索した。コンパイル済みファームウェアをそのまま配布するとゲームアセットの著作権問題が生じるため、分解や配線作業を伴わない吸い出し手順が不可欠だった。
ここでカメラのUSBストレージ機能に設計上の盲点が見つかった。ストレージモード接続時、コントローラは非公開のベンダー固有SCSIコマンドに応答した。ホストPCから制御パケットを送信することで、SoCを指定したRAMアドレスへジャンプさせて任意実行させることができたのだ。Spode氏はこの仕組みを利用してメモリプローブコードを送信。SCSI経由で注入されたマイクロコードがSoCを介して4MBのフラッシュメモリを読み出し、USB経由でPCへ転送することに成功した。
ユーザーは通常のUSBケーブルを挿すだけで、数秒でファームウェアの完全なバックアップを取得できる。汎用リファレンス設計に残されたデバッグ用インターフェースが、デバイスの脆弱な防御を決定的に崩壊させた。
1000円台のコンシューマー家電は極端な低コストと短納期によって動いている。サプライチェーンがわずか数セントの原価と数週間の開発期間を削るために流用した汎用ハードウェアには、過剰な演算能力と無防備な構造が同居している。工場から出荷された製品は、もはやメーカーの手を離れたオープンな存在だ。ハッカーコミュニティによる今回のハックは、見過ごされたノーブランド製品であっても、リバースエンジニアリングによって魅力的なプログラマブルプラットフォームに化けることを鮮やかに証明している。
参考リンク:
- Hackaday 特集記事
- Spode’s Abode リバースエンジニアリングブログ
- Sprite_tm トイカメラファームウェア解析