3、固件获取与提取:硬件提取方法、软件提取方法、固件加密与解密初步
好,咱们进入正题。固件逆向分析的第一步是什么?说白了,你得先拿到固件本身。没有固件,后面所有的分析都是空谈。
我见过不少新手,一上来就想着怎么反汇编、怎么找漏洞,结果连固件都读不出来,卡在第一关。这一章,我就把固件获取的几种主流方法掰开揉碎了讲清楚。硬件怎么提、软件怎么提、遇到加密怎么办,咱们一条条过。
3.1 硬件提取方法
硬件提取,就是直接跟芯片的物理引脚打交道。这活儿需要点耐心,也得有趁手的工具。我个人习惯,能上夹子就不动烙铁,能读 SPI 就不碰 JTAG,因为风险是递增的。
3.1.1 SPI Flash 夹子
这是最常用、也最温和的方法。大多数嵌入式系统的固件都存放在 SPI Flash 芯片里,比如 Winbond、Macronix、GigaDevice 这些厂家的。只要你的板子给 Flash 供电,用夹子夹住芯片引脚,就能通过编程器把内容读出来。
具体步骤大致如下:
- 识别 Flash 型号: 看芯片表面的丝印,记下完整型号。
- 连接编程器: 用夹子夹住 Flash,另一端连到编程器(如 CH341A、TL866)。注意方向,别夹反了。
- 上电读取: 给板子通电,然后用编程器软件读取整个 Flash 内容。保存为 .bin 文件。
3.1.2 JTAG/SWD 调试接口
如果固件不是存在外部 Flash,而是存在芯片内部的 Flash(比如 STM32、NXP 的 MCU),那 SPI 夹子就派不上用场了。这时候,你需要通过调试接口来读取。
JTAG 和 SWD 是两种常见的调试协议。SWD 是 ARM 公司搞的简化版,只需要两根线(SWDIO 和 SWCLK),比 JTAG 的 5 根线少,用起来更方便。
| 接口类型 | 所需引脚数 | 速度 | 适用场景 |
|---|---|---|---|
| JTAG | 5 (TMS, TCK, TDI, TDO, nTRST) | 较快 | 复杂芯片(如 FPGA、高端 MCU) |
| SWD | 2 (SWDIO, SWCLK) | 快 | ARM Cortex-M 系列 MCU |
用调试器(如 J-Link、ST-Link)连接上目标板后,可以通过工具直接读取芯片内部的 Flash。比如用 J-Link 的命令行:
JLinkExe
connect
savebin C:\firmware.bin 0x08000000 0x10000
exit
这条命令的意思是从地址 0x08000000 开始,读取 0x10000(64KB)的数据,保存为 firmware.bin。
3.1.3 芯片开盖
这是最后的手段,也是破坏性最大的方法。当 Flash 芯片是 BGA 封装,或者固件被封装在芯片内部(比如智能卡、安全芯片),你只能物理破坏芯片,用显微镜和探针台来读取。
具体做法是用浓硝酸腐蚀掉芯片的封装,露出晶圆,然后用探针直接接触存储单元。这活儿需要专业设备,而且成功率不高。我本人没干过几次,成本太高,一般公司也玩不起。
3.2 软件提取方法
硬件方法虽然直接,但有时候不方便。比如板子已经装在产品里了,拆开很麻烦。这时候,软件方法就派上用场了。
3.2.1 通过 Bootloader 提取
很多嵌入式系统都有 Bootloader,负责启动和固件更新。如果 Bootloader 提供了读取 Flash 的命令,那就省事了。
比如 U-Boot,这是 Linux 嵌入式系统里最常见的 Bootloader。进入 U-Boot 命令行后,可以用以下命令把固件读出来:
sf probe 0
sf read 0x82000000 0x0 0x100000
tftp 0x82000000 firmware.bin
这段代码的意思是:初始化 SPI Flash,从地址 0 开始读 1MB 数据到内存 0x82000000,然后通过 TFTP 传到电脑上。
3.2.2 通过系统命令提取
如果设备已经跑起了 Linux 或 RTOS,而且你能拿到 shell(比如通过 SSH、Telnet、串口),那提取固件就简单了。
常用的命令:
cat /dev/mtdblock0 > /tmp/firmware.bin—— 读取 MTD 设备(Flash 分区)。dd if=/dev/mmcblk0 of=/tmp/firmware.bin bs=1024 count=4096—— 读取 SD 卡或 eMMC 的前 4MB。scp /tmp/firmware.bin user@your-pc:/home/user/—— 把文件传到电脑。
这里有个前提:你得有 root 权限。如果设备限制了权限,你可能需要先提权。
3.2.3 通过 OTA 抓包
如果设备支持 OTA(Over-The-Air)升级,那固件肯定会在网络上传输。你只需要在设备和服务器之间抓个包,就能拿到固件。
常用的抓包工具:
- Wireshark: 抓取 HTTP/HTTPS 流量。如果是 HTTP,直接就能看到固件 URL;如果是 HTTPS,需要中间人攻击(MITM)。
- Burp Suite: 专门用来抓取和修改 HTTP/HTTPS 请求。设置好代理,让设备的流量经过你的电脑。
- tcpdump: 在路由器或设备本身上抓包,适合没有图形界面的环境。
3.3 固件加密与解密初步
拿到固件文件后,别急着高兴。先看看它是不是加密的。怎么判断?
- 看文件头: 正常的固件文件头通常是
0x00 0x00 0x00 0x00或者0xFF 0xFF 0xFF 0xFF,或者有特定的魔数(如0xFE 0xED 0xBA 0xAD)。如果文件头看起来像随机数据,那很可能是加密的。 - 看熵值: 用工具(如 binwalk -E)计算文件的熵。如果熵值接近 1.0(完全随机),那基本就是加密了。
常见的加密方式:
- XOR 加密: 最简单的加密,用固定密钥对每个字节进行异或。破解也简单,找一段已知明文(比如固件里的字符串),就能反推出密钥。
- AES 加密: 对称加密,密钥通常存储在芯片内部或 Bootloader 里。你需要从硬件或软件中找到密钥。
- RSA 签名: 不是加密,而是签名。固件本身是明文的,但附带了签名,用于验证完整性。你可以去掉签名,直接分析固件。
下面这张图,总结了固件获取与提取的完整流程,你可以对照着看:
拿到固件后,下一步就是分析它了。但那是后面章节的事。这一章,你只要记住:能软则软,不能软再硬,硬的不行就开盖。至于加密,别怕,大部分厂商的加密都很弱,或者密钥就藏在某个角落里。