几十元儿童相机跑通DOOM:公版固件沦为极客后门

几十元儿童相机跑通DOOM:公版固件沦为极客后门

DOOM硬件逆向固件破解嵌入式系统HX3302B消费电子

数据源:Hackaday + Spode's Abode

2026 年 11 月初,逆向开发者 Andrew Spode 公布了一项破解记录。他网购了一台售价不足百元的儿童玩具相机。在这台无名设备上,他成功移植并运行了经典射击游戏《DOOM》。游戏支持全功能走位与射击,画面以约 30 帧流畅渲染,并伴随多复音音效与背景乐。

机身塑料外壳印着卡通图案。包装盒上没有任何厂商名称或商标,说明书里唯一的代号是 X9S。机壳内搭载的却是一颗 32 位国产芯片 HX3302B。

白牌硬件供应链为了压低开销,直接采用现成的主控芯片方案。廉价玩具因此获得了超出拍照所需的富余算力。为了赶工上市,公版固件省略了安全防御。封闭的玩具由此沦为硬件逆向的绝佳试验场。

儿童玩具相机屏幕上流畅运行 DOOM 画面 图:儿童玩具相机在小尺寸彩屏上以 30 帧运行 DOOM。来源:Spode’s Abode。

891KB 剩余内存跑通 DOOM:百元玩具暗藏 120 MIPS 算力

拆解机壳前,设备在网络上几乎查不到技术资料。唯一的线索藏在样张的 EXIF 元数据中。相机样张的制造商字段标注着「HX-Tech」。这让开发者联想到极客 Jeroen Domburg 先前的拆解记录。

Spode 焊开电池引线,拆出内部电路板。主板核心是一颗 HX3302B 芯片,配有一颗 8 引脚的 4MB 闪存。他使用编程器读取芯片固件。逆向分析确认,其 CPU 采用了 OpenRISC 指令集。

基准测试测算出了芯片性能。这颗低功耗芯片拥有 8KB 一级指令缓存与 8KB 数据缓存,缓存读写吞吐量达到 164MB/s。处理器能够输出最高 120 MIPS 的运算能力。即便遇到频繁分支跳转,算力依然保持在 82 MIPS。这套性能足以承担三十年前 3D 游戏的投影运算。

内存容量构成了主要瓶颈。整机配备 2MB 物理 RAM,读取速度为 65MB/s。系统任务与显示缓冲区占去大半空间,留给第三方代码的可用内存仅剩下 891KB。算力周期虽然富余,引擎却必须塞进不足 1MB 的空间里。

拆解后的儿童玩具相机主板与主控芯片 图:玩具相机电路板上的 HX3302B 芯片与 8 引脚闪存芯片。来源:Spode’s Abode。

利用 EXIF 盲导出固件:公版设计省掉全部安全校验

固件更新通道是撕开防线的第一道缺口。相机会从 SD 卡根目录加载名为 Xly100s.bin 的文件。每次开机,系统都会自动扫描该文件。文件头部预留了校验和字段,升级程序却从未核对散列值。

更新程序采用了局部覆盖机制。擦写操作从闪存首地址展开,写入长度取决于输入文件大小。若塞入一个 1MB 大小的文件,相机只改写前 1MB 数据,闪存后半段的 3MB 区域保持原样。修改头部时间戳便能触发刷机。公版固件实际上将存储卡槽变成了无校验的代码注入孔道。

确认写入可行后,开发者需要摸清内存布局。他采用了将内存镜像写入图片 EXIF 结构的技巧。标准 JPEG 格式允许存储高达 64KB 的 EXIF 数据,该相机拍照时仅占用约 730 字节。

Spode 改写了相机的拍照保存例程。硬件编码器无法直接接触启动内存。他便利用 CPU 将目标区域分段搬运到 EXIF 缓存区中。快门每按一次捕获 4KB 数据,指针自动滑动一个窗口。连拍 16 张照片,64KB 内部启动内存便完整写入存储卡。比对数据后证实,系统不存在掩膜 ROM,全部底层代码均裸露在外。

29KB 核心代码入驻内存:闪存执行分流打破 4MB 门槛

PC 平台原版《DOOM》以 4MB 内存为运行基准。面对 891KB 的玩具硬件,内存管理必须从底层重构。开发者清理了相机未调用的空闲缓存,可用内存由此拼凑扩充到 1.4MB。

拼凑而来的空间存在重度碎片化。稍大尺寸的连续内存极易分配失败。原版引擎并未限制碎块分配,零散对象会切碎连续空间。Spode 为小型分配建立了专属内存池。关卡与音效资源也被设置为通关即焚,避免占死内存。

代码段的安放是另一个棘手挑战。2MB 内存装不下整套游戏二进制。芯片支持直接从 SPI 闪存原位执行代码。但测试表明,闪存执行代码比在 RAM 中慢了足足 18 倍。

开发者通过本地模拟器采集了代码执行特征。探针数据显示,99% 的运行时间仅在 29KB 的主循环中耗尽。整整 260KB 的二进制代码中,大部分只是冷启动与菜单逻辑。Spode 将 29KB 的热循环指令锁定在物理 RAM 中常驻,其余冷路径则保留在闪存中按需读取。这种分流执行方案,让游戏在严苛内存下维持了全速运转。

儿童玩具相机正面外观与按键布局 图:机身没有品牌标识的 X9S 玩具相机外观。来源:Spode’s Abode。

旁路主循环与自制合成器:硬编码轮询换来 30 帧满血输出

解决了内存冲突后,固件架构成为压制帧率的瓶颈。原始系统运行着一套事件调度循环。单帧事件轮询的空耗高达 38 毫秒,使帧率直接腰斩。

Spode 绕开了原厂事件框架。他改写了一套极简的直读主循环。程序直接通过寄存器轮询物理 GPIO 引脚。方向键绑定行走,快门键用于连续开火。轻按电源键切换武器,长按唤出设置菜单。推挤墙面则直接触发开门判定。精简后的按键轮询消除了调度延迟,游戏帧率攀升至 30 FPS。

音频硬件同样缺乏多声道支持。相机板载只提供单路 PWM 输出。Spode 开发了一套软混音模块,将多路音效合成单轨信号。

背景音乐摆脱了额外的芯片依赖。原版音乐采用 MUS 格式,传统上由专业 FM 芯片合成。玩具主板并无此类发声单元。Spode 编写了一套超轻量的软件波形发生器。合成器仅调用 2% 的 CPU 算力。它通过方波与三角波产生 16 复音旋律,在蜂鸣喇叭上复现了原版原声。

SCSI 指令暴露任意执行:公版漏洞撕开免拆机刷机通道

游戏成功移植后,开发者考虑将其向大众分发。分发已编译固件存在版权侵权隐患。Spode 决定寻找一种免拆机、免飞线的固件导出手段。

相机的 USB 接口露出了低级设计漏洞。在常规存储挂载模式下,设备响应未公开的 SCSI 供应商指令。主机可向总线发送控制包,要求芯片跳转至指定内存地址运行。Spode 借助代码分析工具生成了一段内存探针代码。主机通过 SCSI 协议将微指令注入 RAM。芯片随后代劳读取 4MB 闪存,分块打包回传给电脑。

玩家只需插上一根普通 USB 传输线,几秒内即可无损备份固件。公版方案在接口上遗留的调试通道,直接瓦解了原本薄弱的硬件防线。

百元级消费电子产品由低成本与快节奏驱动。供应链为了节约几美分与数周工期,倾销着算力冗余却无安全防护的公版硬件。设备出厂流入流通领域后,简陋的固件架构不再受原厂羁绊。极客社区的技术穿透表明,任何被遗忘的白牌计算单元,都能在逆向工程中蜕变为可编程的极客平台。

参考链接:

  • Hackaday 专题报道
  • Spode’s Abode 逆向技术博客
  • Sprite_tm 儿童相机固件分析