3、固件提取实战:三种主流方法
固件提取,说白了就是怎么把芯片里的程序“读”出来。这步要是卡住了,后面逆向、调试都白搭。我这些年经手的项目,提取方式基本就三类:用编程器硬读、利用Bootloader漏洞软取、通过调试接口转储。今天咱们一个一个过。
3.1 方法一:使用编程器读取SPI Flash
这是最直接、最“物理”的方法。适合那些固件存在外部SPI Flash里的情况,比如很多路由器、物联网设备。
典型场景:你拿到一块板子,主芯片是MT7620,旁边有个8脚芯片,型号是W25Q128。嗯,这就是SPI Flash,固件就躺在里面。
3.1.1 硬件连接
你需要一个编程器,我常用的是CH341A,便宜又好用。连接方式很简单:
- VCC → 3.3V(注意,别接5V,会烧芯片)
- GND → 地
- CS → 片选
- CLK → 时钟
- MOSI → 主出从入
- MISO → 主入从出
3.1.2 读取操作
连接好之后,打开编程器软件(比如AsProgrammer)。选择芯片型号,点击“读取”。等个几十秒,固件就出来了。
# 以W25Q128为例,16MB的Flash
# 读取成功后,保存为.bin文件
# 文件大小应该是16,777,216字节(16MB)
$ ls -la firmware.bin
-rw-r--r-- 1 user user 16777216 Mar 15 10:30 firmware.bin
3.2 方法二:利用Bootloader漏洞提取固件
这个方法更“优雅”。不需要拆芯片,只需要通过串口或网络,利用Bootloader的漏洞把固件“骗”出来。
典型场景:设备上电时,串口输出“Press any key to stop autoboot”。你按了回车,进入了U-Boot命令行。这就是机会。
3.2.1 常见漏洞类型
| 漏洞类型 | 描述 | 利用方式 |
|---|---|---|
| 未授权Shell | Bootloader直接暴露了命令行 | 直接执行dump命令 |
| 缓冲区溢出 | 输入超长字符串导致崩溃 | 控制PC指针,跳转到dump代码 |
| 环境变量注入 | 通过修改环境变量执行恶意命令 | 设置bootargs为非法值 |
| 固件签名绕过 | Bootloader不验证固件签名 | 上传自定义固件,包含dump功能 |
3.2.2 实战:U-Boot下dump固件
假设你进入了U-Boot命令行。可以用以下命令把Flash内容读出来:
# 1. 查看Flash信息
U-Boot> sf probe
U-Boot> sf info
# 2. 读取整个Flash到内存
U-Boot> sf read 0x82000000 0x0 0x1000000
# 3. 通过tftp发送到电脑
U-Boot> tftp 0x82000000 firmware.bin 0x1000000
电脑上启动tftp服务器,等着收文件就行。
3.3 方法三:通过JTAG/SWD接口转储Flash内容
这是最“硬核”的方法。适合那些芯片有调试接口,但Bootloader被锁、Flash被焊死的情况。
典型场景:你拿到一个工业控制器,主芯片是STM32F4,Flash是内部集成的。没有外部SPI Flash,Bootloader也进不去。这时候,JTAG/SWD就是你的救命稻草。
3.3.1 接口定义
| 接口 | 引脚 | 说明 |
|---|---|---|
| JTAG | TMS, TCK, TDI, TDO, nTRST | 5线,功能全,但占用引脚多 |
| SWD | SWDIO, SWCLK | 2线,够用,现在主流 |
3.3.2 连接与读取
你需要一个调试器,比如J-Link或ST-Link。连接SWDIO和SWCLK,再加上GND。然后:
# 使用J-Link Commander
$ JLinkExe -device STM32F407VG -if SWD -speed 4000
# 连接成功后,读取Flash
J-Link> connect
J-Link> savebin firmware.bin 0x08000000 0x100000
这里0x08000000是STM32的Flash起始地址,0x100000是大小(1MB)。
3.4 三种方法对比
我把这三种方法的特点整理了一下,方便你选型:
| 方法 | 难度 | 风险 | 适用场景 | 成功率 |
|---|---|---|---|---|
| 编程器读取 | 低 | 低(可能焊坏焊盘) | 外部SPI Flash | 高 |
| Bootloader漏洞 | 中 | 中(可能变砖) | 有串口/网络的设备 | 中 |
| JTAG/SWD转储 | 高 | 高(可能触发保护) | 有调试接口的芯片 | 中高 |
3.5 本章知识体系
下面这张图,帮你理清三种方法的逻辑关系:
3.6 避坑指南
最后,分享几个我踩过的坑:
- 编程器夹子不可靠:我曾经用夹子夹SPI Flash,结果接触不良,读出来的数据全是0xFF。后来我都是直接焊线,或者用烧录座。
- Bootloader漏洞利用要小心:有一次我试图利用缓冲区溢出,结果把Bootloader搞崩了,设备直接变砖。后来花了半天时间用编程器重刷才救回来。
- JTAG/SWD速度别太高:我习惯用4000kHz,但有些板子布线不好,高速下会出错。遇到奇怪的问题,先降速试试。
- 读保护不是闹着玩的:STM32的RDP Level 2是永久性的,一旦设置就无法解除。所以,拿到新芯片,第一件事就是检查读保护级别。