4、固件获取与预处理:从芯片、开发板、OTA包、官网等渠道获取固件,固件文件识别与解包
固件逆向分析的第一步,也是最容易被忽视的一步,就是“拿到正确的固件”并“正确地打开它”。在实际渗透测试、漏洞研究或产品调试中,分析人员往往花费大量时间在错误的文件格式、加密的OTA包或未文档化的私有头文件上。本章将系统梳理固件的四大获取渠道(芯片/板载存储、开发板/调试接口、OTA升级包、厂商官网/第三方聚合站),并深入讲解固件文件的识别方法(文件系统特征、头部魔数、熵值分析)与解包技术(binwalk、jefferson、sasquatch、手动拆分)。通过本章学习,读者应能独立完成从物理芯片到可分析文件系统的完整预处理链路。
4.1 固件获取的四大渠道与实战选择
核心原理:固件本质上是一段存储在非易失性存储器中的二进制数据,其物理位置决定了获取方式。从芯片直接读取是最底层、最完整的方式,但需要硬件工具和焊接/飞线能力;从开发板获取则依赖调试接口(JTAG/SWD)或Bootloader命令;OTA包是厂商分发更新的载体,通常经过压缩、加密和签名;官网/聚合站则是最便捷的途径,但可能版本滞后或缺少特定区域固件。选择哪种渠道,取决于分析目标——是研究启动流程、挖掘漏洞,还是提取配置文件。
| 渠道 | 工具/方法 | 优点 | 缺点/风险 | 适用场景 |
|---|---|---|---|---|
| 芯片直读 | SPI Flash编程器、NAND读取器、热风枪拆焊 | 最完整、无校验绕过问题 | 可能损坏芯片、需要焊接、NAND有坏块管理 | 量产设备、无OTA渠道、深度研究 |
| 开发板/调试接口 | OpenOCD + JTAG、U-Boot tftp下载、fastboot | 无需拆芯片、可交互 | 需要开发板或引出测试点、可能禁用调试口 | 原型验证、固件开发阶段 |
| OTA包 | 抓包(mitmproxy)、固件提取脚本、差分工具 | 获取最新版本、无需硬件 | 加密/签名、差分包需还原、可能需服务器端配合 | 漏洞对比、新版本分析 |
| 官网/聚合站 | wget、FTP爬取、Firmware.info、OpenWrt镜像 | 方便快捷、版本全 | 可能不包含bootloader、区域限制 | 初步分析、已知CVE验证 |
操作流程(以SPI Flash读取为例):
- 识别芯片型号:观察PCB上的8脚或16脚SOIC封装,丝印如“25Q128FVSG”表示Winbond 128Mbit SPI NOR Flash。
- 连接编程器:使用CH341A或RT809H编程器,通过测试夹或飞线连接VCC、GND、CLK、MOSI、MISO、CS#。
- 读取与校验:在编程器软件中选择对应型号,读取全片数据并保存为.bin,建议读取两次并比对哈希值。
- 处理坏块(NAND):若为NAND Flash,需使用nanddump工具配合ECC校验,或使用专用NAND读取器。
4.2 固件文件识别:从魔数到熵值分析
判断方法:拿到一个.bin文件后,不能盲目解包。首先使用file命令查看文件类型,但固件通常是裸数据,file命令可能输出“data”。此时需要手动检查头部魔数(Magic Number)。常见固件头部包括:U-Boot的“U-Boot”字符串、Linux内核的“0x1F 0x8B”(gzip)或“0xFD 0x37 0x7A 0x58”(xz)、SquashFS的“hsqs”、JFFS2的“0x85 0x19”、CramFS的“0x28 0xCD 0x3D 0x45”等。
# 查看头部16进制
hexdump -C firmware.bin | head -20
# 使用binwalk扫描嵌入式文件
binwalk firmware.bin
# 熵值分析(识别压缩/加密区域)
binwalk -E firmware.bin
熵值分析原理:熵值(Entropy)衡量数据的随机性。未压缩的代码/文本熵值通常在4.5-6.5之间;压缩或加密数据熵值接近8.0。通过绘制熵值曲线,可以快速定位固件中哪些区域是压缩的rootfs、哪些是明文配置。例如,一个典型路由器固件,前0x20000字节是U-Boot(低熵),接着是内核(中等熵),最后是SquashFS(高熵)。
binwalk扫描结果如下:
DECIMAL HEXADECIMAL DESCRIPTION
0 0x0 U-Boot version string "U-Boot 1.1.4"
131072 0x20000 Linux kernel ARM boot executable zImage
4194304 0x400000 SquashFS filesystem, little endian, version 4.0
通过dd if=firmware.bin of=kernel.bin bs=1 skip=131072 count=4063232提取内核,再使用dd if=firmware.bin of=rootfs.sqfs bs=1 skip=4194304提取文件系统。整个过程无需任何自动化工具,仅靠binwalk的偏移量提示即可完成。
4.3 固件解包:文件系统提取与手动拆分
核心工具链:binwalk是首选,但面对非标准文件系统或加密固件时,需要组合使用专用工具。SquashFS使用sasquatch(binwalk的-e参数会自动调用),JFFS2使用jefferson,CramFS使用cramfsck,UBIFS使用ubireader_extract_files。对于OTA差分包,可使用delta工具或手动对比新旧版本。
操作流程:
- 自动解包:
binwalk -eM firmware.bin,-M参数递归扫描提取出的文件。 - 手动拆分:当binwalk无法识别时,根据熵值曲线和已知偏移量,使用
dd命令手动切割。 - 文件系统挂载:对于SquashFS,使用
unsquashfs rootfs.sqfs;对于JFFS2,使用jefferson rootfs.jffs2;对于UBIFS,需先模拟NAND设备(nandsim)再挂载。 - 处理加密固件:若熵值整体接近8.0且无文件系统特征,可能整体加密。需寻找固件解密密钥(通常在Bootloader中)或利用已知明文攻击。
| 文件系统类型 | 魔数/特征 | 解包工具 | 备注 |
|---|---|---|---|
| SquashFS | hsqs (0x68 0x73 0x71 0x73) | unsquashfs / sasquatch | 只读压缩,最常见于路由器 |
| JFFS2 | 0x85 0x19 | jefferson | 日志型,用于NAND Flash |
| CramFS | 0x28 0xCD 0x3D 0x45 | cramfsck | 老式设备,压缩比低 |
| UBIFS | UBI# (0x55 0x42 0x49 0x23) | ubireader_extract_files | 需要处理UBI卷层 |
| ext4 | 0x53 0xEF | debugfs / mount | 常见于eMMC设备 |
binwalk -A(扫描opcodes)或binwalk -W(对比不同固件版本)。另外,部分厂商会在固件头部添加自定义结构,可使用binwalk -R "字符串"搜索特定标记。
4.4 常见误区与总结复盘
误区一:盲目依赖binwalk。binwalk基于特征库匹配,对于私有文件系统或加密固件无能为力。正确做法是先做熵值分析,再结合硬件原理判断布局。
误区二:忽略OTA包的差分机制。许多智能设备OTA包是差分升级(如bsdiff),直接解包会得到乱码。需先使用bspatch将差分包与旧版本合并,或寻找全量包。
误区三:混淆NOR与NAND Flash。NOR可直接读取字节,NAND需通过控制器且存在坏块。若从NAND读取的固件出现大量0xFF,可能是坏块标记或ECC校验错误。
误区四:忘记检查签名和校验和。即使成功解包,修改后的固件也无法在目标设备上运行(安全启动)。预处理阶段应记录原始固件的哈希值,以便后续对比。
binwalk仅识别出U-Boot,后续数据熵值接近8.0。分析过程:使用binwalk -E绘制熵值曲线,发现0x20000-0x400000区域熵值波动,疑似加密内核;0x400000之后熵值稳定在7.9,疑似加密文件系统。进一步检查U-Boot环境变量,发现启动参数包含decrypt_rootfs命令。实际操作:在U-Boot中执行decrypt_rootfs 0x400000 0x800000,将解密后的数据写入内存,再通过tftp导出。结果:成功获得明文SquashFS。复盘经验:对于加密固件,Bootloader是天然的“解密机”,优先分析启动流程而非强行破解加密算法。
总结:固件获取与预处理是逆向工程的地基。本章强调“渠道选择-识别-解包”三步走方法论,并指出硬件调试接口往往比软件提取更可靠。在实际项目中,建议建立固件档案表,记录来源、哈希、芯片型号、文件系统类型、解包工具链,以便后续漏洞分析时快速回溯。下一阶段,我们将深入探讨如何从解包后的文件系统中定位敏感信息与攻击面。