第三章 固件获取与提取:从源头到二进制
做固件逆向,第一步不是反汇编,而是拿到固件本身。很多人一上来就想着怎么分析,结果卡在“没固件”这一步,白白浪费时间。
这一章,我就带你走一遍固件获取的完整路径。从官网下载,到设备备份,再到最硬核的Flash读取。每一步都有坑,我会把踩过的坑都指出来。
3.1 固件来源:三条路,各有千秋
固件从哪来?说白了就三个渠道。我按推荐程度排个序:
| 来源 | 难度 | 完整性 | 适用场景 |
|---|---|---|---|
| 官网下载 | ★☆☆ | 通常完整 | 消费类产品、开源硬件 |
| 设备备份 | ★★☆ | 可能被裁剪 | 已部署设备、无网络环境 |
| Flash读取 | ★★★ | 最完整 | 加密设备、定制固件 |
官网下载是最省事的。但有个问题——厂商经常只放最新版,旧版本固件可能已经下架了。我习惯用 wget 配合 --recursive 参数把整个固件目录扒下来,存到本地归档。
设备备份这条路,我是在做工业路由器逆向时学会的。设备本身有固件升级功能,但升级包往往需要校验签名。怎么办?
我的做法是:通过串口或 SSH 登录设备,用 dd 命令把 Flash 分区整个读出来。
# 查看分区表
cat /proc/mtd
# 备份整个 Flash
dd if=/dev/mtd0 of=/tmp/full_flash.bin bs=65536
# 通过 TFTP 传回本地
tftp -p -l /tmp/full_flash.bin 192.168.1.100
嗯,这里要注意:很多嵌入式设备的内存很小,直接 dd 到 /tmp 可能撑爆。我建议分块读取,或者用 nc 直接管道传输。
3.2 使用编程器读取Flash:硬核玩家的必修课
当软件手段走不通时,就得动硬件了。编程器读取Flash,是逆向工程师的看家本领。
3.2.1 J-Link vs ST-Link:选对工具
| 特性 | J-Link | ST-Link |
|---|---|---|
| 支持芯片范围 | ARM Cortex全系列 + 部分RISC-V | STM32全系列 |
| 速度 | 最高50 MHz SWO | 最高4 MHz SWD |
| 价格 | ¥200-2000+ | ¥20-100 |
| 调试功能 | 完整(RTT、ETM、实时跟踪) | 基础(断点、单步) |
| 固件提取 | 支持通过SWD/JTAG直接读Flash | 需配合STM32 Utility |
我个人习惯:日常调试用ST-Link,便宜够用。但做逆向提取时,我必用J-Link。为什么?因为J-Link的 JLinkExe 命令行工具太强了,可以写脚本批量操作。
# 启动 JLinkExe
JLinkExe -device STM32F407VG -if SWD -speed 4000 -autoconnect 1
# 在 JLink 命令行中执行
connect
savebin C:\dump\flash_dump.bin 0x08000000 0x100000
exit
这段命令会从 0x08000000 开始,读取 1MB 的 Flash 内容,保存为二进制文件。
3.2.2 接线与飞线:BGA芯片的噩梦
遇到BGA封装的芯片,才是真正的考验。我记得有一次,客户送来一块工业控制板,主控是BGA封装的i.MX6。Flash芯片藏在BGA下面,根本没法直接夹。
怎么办?飞线。
我的飞线流程是这样的:
- 定位引脚:用万用表测量BGA焊盘到PCB过孔的通路,找到Flash的CS、MISO、MOSI、SCLK、VCC、GND。
- 刮开阻焊层:用刀片轻轻刮掉过孔上的绿油,露出铜面。
- 上锡:用细尖烙铁给过孔上锡,锡量要少,否则会连到旁边的过孔。
- 焊接飞线:用0.1mm的漆包线,一端焊在过孔上,另一端焊在编程器的转接板上。
- 固定:用热熔胶把飞线固定在PCB上,防止拉扯脱落。
这里有个坑:BGA芯片的Flash引脚往往和CPU共用,飞线时如果CPU还在供电,可能会造成总线冲突。我习惯先把CPU的供电断开,或者把CPU的复位引脚拉低,让CPU处于复位状态。
3.3 固件加密与保护机制:道高一尺
拿到固件只是第一步。如果固件被加密或保护了,你拿到的只是一堆乱码。
3.3.1 常见的保护手段
| 保护类型 | 原理 | 破解难度 | 典型芯片 |
|---|---|---|---|
| 读保护(RDP) | 禁止通过调试接口读取Flash | ★★☆ | STM32(RDP Level 1/2) |
| 加密固件 | 固件本身被AES/RSA加密 | ★★★ | NXP i.MX、TI Sitara |
| 安全启动 | 签名验证,防止篡改 | ★★★★ | 高通、MTK、全志 |
| 熔丝/OTP | 一次性编程,烧断后不可恢复 | ★★★★★ | 很多车规级MCU |
3.3.2 绕过读保护:我的实战经验
STM32的RDP Level 1是最常见的。怎么绕过?
我试过几种方法:
- 电压毛刺攻击:在读取Flash的瞬间,给VDD引脚注入一个短时高压脉冲,让CPU跳过读保护检查。成功率大概30%,而且容易烧芯片。
- 冷启动攻击:把芯片降温到-40°C以下,利用SRAM的数据保持特性,在复位瞬间读取残留数据。这个方法对某些老芯片有效。
- 固件漏洞利用:通过串口或网络接口,利用固件本身的漏洞(如缓冲区溢出)来dump内存。这是最优雅的方式。
3.3.3 加密固件的处理思路
加密固件看起来无解,但其实有突破口:
- 密钥存储位置:密钥通常存储在芯片的OTP区域或eFuse中。如果能通过物理手段读取OTP(比如用聚焦离子束FIB),就能拿到密钥。
- 解密过程监控:芯片在启动时,会从Flash读取加密固件,用内置密钥解密后执行。如果能用逻辑分析仪抓取CPU和Flash之间的数据总线,就能捕获解密后的明文。
- 侧信道攻击:通过分析芯片的功耗或电磁辐射,推断出密钥。这个需要专业设备,但确实可行。
嗯,这些方法都挺硬核的。对于大多数场景,我建议优先寻找固件更新包——很多厂商的更新包是未加密的,或者加密密钥就硬编码在更新程序里。
3.4 本章知识结构图
下面这张图,把固件获取与提取的完整流程串起来了:
3.5 小结
固件获取是逆向分析的基础。我的建议是:
- 先走软件路线(官网、设备备份),实在不行再动硬件。
- 动硬件时,优先用编程器通过SWD/JTAG读取,飞线是最后的选择。
- 遇到加密保护,别硬刚。先看看有没有固件更新包、有没有调试接口、有没有已知漏洞。
你想想看,如果连固件都拿不到,后面的分析就是空中楼阁。把这一步走扎实了,后面的路就好走了。