3. 固件获取与预处理:从芯片、板卡、OTA包、官网等途径获取固件,固件格式识别与解包
固件逆向分析的第一步,也是最容易被忽视的一步,是“拿到”并“读懂”固件本身。在实际的嵌入式安全评估、漏洞挖掘或产品研发中,我们面对的不是一个抽象的程序,而是一个封装在特定硬件介质、特定文件格式或特定传输协议中的二进制镜像。如果无法准确获取固件并正确解包,后续的静态分析、动态调试都将成为无源之水。本章将系统讲解固件的四大获取途径(芯片直读、板卡提取、OTA包捕获、官网下载),深入剖析固件格式的识别方法,并详细演示从二进制文件到可分析文件系统的完整解包流程。
上图展示了固件获取与预处理的完整工程链路。从左侧的四大获取途径出发,经过格式识别、解包处理,最终得到可分析的文件系统与内核镜像。整个过程环环相扣,任何一个环节的失误都可能导致后续分析方向错误。下面我们将逐一深入每个环节。
3.1 固件获取的四大途径与实战要点
3.1.1 芯片直读:SPI Flash 与 JTAG 提取
核心原理:绝大多数嵌入式设备(路由器、IoT 网关、工业控制器)使用 SPI NOR Flash 或 NAND Flash 存储固件。芯片直读是最底层的获取方式,通过编程器(如 CH341A、RT809H)或调试接口(JTAG/SWD)直接读取 Flash 中的原始二进制数据。这种方式不依赖设备是否运行,即使设备完全变砖也能提取。
操作流程:
- 拆解设备:定位 PCB 上的 Flash 芯片,记录型号(如 Winbond W25Q128FV、MXIC MX25L25645G)。
- 连接编程器:使用 SOP8/SOP16 测试夹或热风枪拆焊后连接编程器。注意电压匹配(3.3V 为主,部分老芯片为 5V)。
- 读取数据:在编程器软件中识别芯片型号,设置读取大小为芯片容量(如 16MB),读取并保存为 .bin 文件。
- 校验:读取两次并比对哈希值,确保数据完整性。
3.1.2 板卡提取:利用 U-Boot 或系统 Shell
如果设备可以正常启动或进入 U-Boot 命令行,板卡提取是更便捷的方式。常见方法包括:
- U-Boot 下导出:在 U-Boot 提示符下使用
md(内存显示)、mw(内存写)、nand read、sf read等命令将 Flash 内容读取到内存,再通过tftp或loadb传输到主机。 - 系统 Shell 下复制:若设备开放 telnet/SSH,可直接查看
/dev/mtd*设备节点,使用dd if=/dev/mtd0 of=/tmp/fw.bin备份。 - 利用漏洞获取 Shell:如通过命令注入、硬编码后门等获取 root 权限。
# U-Boot 下读取 SPI Flash 示例
U-Boot> sf probe 0
U-Boot> sf read 0x82000000 0x0 0x1000000 ; # 读取 16MB 到内存
U-Boot> tftp 0x82000000 firmware.bin ; # 通过 TFTP 上传到主机
3.1.3 OTA 包捕获:中间人代理与流量分析
智能设备(如智能摄像头、扫地机器人)通常通过 OTA 升级。捕获 OTA 包需要搭建代理环境:
- 配置代理:在路由器或主机上运行 mitmproxy / Burp Suite,将设备流量指向代理。
- 绕过 TLS 校验:部分设备会校验服务器证书,需将代理 CA 证书安装到设备信任库(若可写)或使用 SSL 剥离。
- 触发升级:在 App 端点击“检查更新”,捕获 HTTP/HTTPS 请求,定位固件下载 URL。
- 下载固件:直接使用 wget/curl 下载固件包,注意可能需要伪造请求头(如 User-Agent、签名参数)。
3.1.4 官网与第三方渠道
厂商官网的“技术支持/下载中心”是最合法的获取途径。但需注意:官网固件可能为增量升级包(仅包含差异文件),而非完整镜像。第三方论坛(如 OpenWrt 社区、Hackaday)常提供由开发者提取的完整固件,但需警惕被植入后门的风险,下载后务必校验哈希值。
3.2 固件格式识别:从二进制到结构化
3.2.1 文件类型初步判断
拿到固件文件后,第一步是使用 file 命令和 hexdump 查看文件头。
$ file firmware.bin
firmware.bin: data # 未知格式
$ hexdump -C firmware.bin | head -20
00000000 27 05 19 56 88 93 4d 61 67 69 63 00 00 00 00 00 |'..V..Magic.....|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
常见的固件魔数(Magic Number)包括:
| 魔数(十六进制) | ASCII 标识 | 含义 |
|---|---|---|
| 1F 8B | gzip | gzip 压缩流 |
| FD 37 7A 58 5A | xz | xz 压缩流 |
| 42 5A 68 | BZh | bzip2 压缩流 |
| 53 51 55 41 53 48 46 53 | SQUASHFS | SquashFS 文件系统 |
| 31 19 00 00 | — | JFFS2 文件系统 |
| 55 42 49 23 01 | UBI# | UBI 文件系统 |
| 7F 45 4C 46 | ELF | Linux 内核或可执行文件 |
3.2.2 Binwalk 深度扫描
Binwalk 是固件分析的核心工具,它通过特征签名扫描固件中的嵌入文件。
$ binwalk firmware.bin
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 DLOB firmware header, boot partition
262144 0x40000 LZMA compressed data
1048576 0x100000 SquashFS filesystem, little endian, version 4.0, compression:lzma
Binwalk 输出清晰地展示了固件布局:头部 + LZMA 压缩的内核 + SquashFS 根文件系统。此时可执行 binwalk -e 自动提取。
binwalk -A(opcode 扫描)或 binwalk -W(熵分析)。熵值高的区域通常为加密数据或压缩数据,熵值低的区域可能为明文代码或填充。
3.3 固件解包实战:从镜像到文件系统
3.3.1 手动解包流程
以典型的“头部 + 内核 + 文件系统”三段式固件为例:
- 跳过头部:使用
dd跳过头部,提取内核和文件系统。 - 解压内核:若内核为 LZMA 压缩,使用
lzma -d或7z x解压。 - 挂载文件系统:SquashFS 可使用
unsquashfs直接解包;JFFS2 需使用jefferson或mtd-utils。
# 提取文件系统(偏移 0x100000,大小 0x800000)
$ dd if=firmware.bin of=rootfs.squashfs bs=1 skip=1048576 count=8388608
$ unsquashfs rootfs.squashfs
Parallel unsquashfs: Using 4 processors
1792 inodes (2048 blocks) to write
[===============================================================|] 2048/2048 100%
$ ls squashfs-root/
bin dev etc lib proc sbin usr var
3.3.2 处理加密与签名固件
现代设备普遍采用 AES 加密 + RSA 签名。面对加密固件,思路如下:
- 寻找密钥:在 U-Boot 环境变量、设备树(DTB)、或未加密的引导程序中搜索硬编码密钥。
- 利用解密预言机:若设备支持“恢复模式”或“调试模式”,可能提供解密接口。
- 动态提取:在设备运行时从内存中 dump 解密后的数据(使用
devmem或冷启动攻击)。
3.4 案例拆解:某品牌 IP 摄像头的固件获取与解包
背景与目标:某安防厂商的 IP 摄像头(固件版本 V2.1.4)被曝存在多个漏洞,但厂商未提供完整固件下载,仅支持 App 内 OTA 升级。我们的目标是获取完整文件系统以进行漏洞分析。
初始现象:通过官网下载的固件仅为 2MB 的增量包,不包含完整 rootfs。使用 Binwalk 扫描仅发现少量 PNG 图标和配置文件。
关键输入数据:
- 设备型号:IPC-2340F,主控 SoC:海思 Hi3516EV200
- Flash 布局:4MB SPI NOR(uboot 256KB + kernel 2MB + rootfs 1.5MB + config 256KB)
- 网络环境:设备通过 DHCP 获取 IP,App 与设备通信使用 TLS 1.2
分析判断过程:
- 首先尝试 U-Boot 提取:通过串口进入 U-Boot,执行
sf read读取整个 Flash,成功获取 4MB 完整镜像。 - 使用 Binwalk 扫描完整镜像,发现偏移 0x100000 处有 SquashFS 文件系统。
- 但
unsquashfs解包时报错“Filesystem uses unsupported compression type: lzma”。 - 检查 SquashFS 超级块,发现压缩类型为 LZMA,而系统默认 unsquashfs 不支持。需使用
sasquatch(Binwalk 的补丁版)解包。
实际操作步骤:
# 1. 从完整镜像提取 rootfs
$ dd if=full_flash.bin of=rootfs.squashfs bs=1 skip=1048576 count=1572864
# 2. 使用 sasquatch 解包
$ sasquatch rootfs.squashfs
Processing 'rootfs.squashfs'...
Found a valid SquashFS 4.0 little-endian superblock
Compression type: lzma
Inodes count: 2048
...
$ ls squashfs-root/
bin etc lib usr var www init
结果对比:成功提取出完整的 Linux 文件系统,包含 Web 服务程序、摄像头控制程序、以及一个隐藏的 telnetd 二进制。后续分析发现该 telnetd 存在硬编码后门账号,与厂商公告的漏洞一致。
风险与代价:串口提取需要拆机并焊接调试线,存在损坏设备的风险;且设备在保修期内拆机会失去保修资格。
复盘经验:
- 优先尝试非侵入式方法(OTA 捕获、官网下载),最后才考虑硬件拆解。
- Binwalk 默认工具链不完整,建议安装
sasquatch、jefferson、ubi_reader等扩展工具。 - 提取固件后立即计算 SHA-256 并记录来源、日期、设备版本,便于审计追溯。
3.5 常见误区与总结复盘
| 误区 | 后果 | 正确做法 |
|---|---|---|
| 拿到固件直接 Binwalk -e,不检查头部 | 提取出大量碎片文件,无法还原文件系统 | 先 hexdump 查看头部,理解固件布局 |
| 忽略 OTA 包的增量特性 | 分析的是补丁而非完整系统,遗漏核心逻辑 | 结合当前运行版本,用 diff 工具对比 |
| 使用系统自带 unsquashfs 解包所有镜像 | 遇到 LZMA/XZ 压缩时报错或解包不完整 | 安装 sasquatch、squashfs-tools-ng 等增强工具 |
| 不记录固件来源和哈希值 | 无法复现分析结果,法律合规风险 | 建立固件样本库,记录元数据 |
| 忽略 Flash 分区表 | 提取的镜像可能包含 OOB 数据或冗余区域 | 从 U-Boot 环境变量或 DTS 中获取分区布局 |
总结:固件获取与预处理是逆向分析的地基。一个合格的固件分析师应掌握至少两种获取途径(如 OTA 捕获 + 芯片直读),并能熟练使用 Binwalk、Sasquatch、U-Boot 命令等工具。在解包过程中,保持对固件头部、压缩算法、文件系统类型的敏感度,遇到异常时善用熵分析和字符串搜索。最重要的是,始终记录操作日志和样本哈希,确保分析过程可复现、可审计。下一阶段,我们将基于提取出的文件系统,展开内核与应用程序的静态分析。