2. 固件镜像获取与解析
固件安全扫描的第一步,是把设备里那块“看不见的软件”变成分析主机上可读、可拆、可检索的文件集合。这一步通常称为固件镜像获取与解析。它包含三个连续动作:拿到镜像、识别并拆出内部结构、把文件系统挂载起来做内容审计。三者缺一不可——只拿到镜像不解析,等于拿到一个加密压缩包;解析出文件却不挂载,很多路径、权限、软链接关系仍然看不清楚。
一、常见固件格式及其结构特征
固件并不是单一格式,而是按设备类型分成几大族。理解每族的“容器—载荷”关系,决定了后面该用哪种工具、按什么顺序拆。
UEFI/BIOS 固件:现代 x86 平台固件通常是一个 SPI Flash 镜像,典型容量 8MB、16MB 或 32MB。镜像头部是 Flash Descriptor(描述区域布局),随后是 ME/CSME 区域、GbE 区域、BIOS 区域。BIOS 区域内部是 UEFI 固件卷(FV),FV 里装着多个 FFS 文件,FFS 里再包着 PE32 模块、驱动、DXE 驱动和 Setup 变量默认值。它的关键特征是“层层嵌套的卷结构”,而不是文件系统。解析重点是 UEFITool、uefi-firmware-parser 这类能识别 FV/FFS 的工具。
嵌入式 Linux 固件:最常见的是厂商发布的 .bin/.img/.trx 升级包。典型布局是:头部厂商元数据(magic、版本、校验)→ U-Boot 引导程序 → Linux 内核(zImage/uImage)→ 设备树 DTB → 根文件系统(SquashFS、JFFS2、UBIFS、ext4、cramfs)。很多路由器固件还会在头部加 TRX 或 Broadcom tag。它的关键特征是“多段拼接 + 尾部文件系统”,解析重点是按 magic 逐段切分。
RTOS 固件:常见于 IoT 模组、工控设备、车载 ECU。镜像往往没有文件系统,而是扁平地址空间:中断向量表 → 启动代码 → RTOS 内核 → 应用任务 → 常量数据。格式可能是原始 bin、Intel HEX、Motorola S-record,或带 CRC 的私有封装。解析重点是识别 CPU 架构(ARM Cortex-M、MIPS、RISC-V)、加载地址和入口点,而不是找文件系统。
二、提取工具:binwalk 与 firmware-mod-kit
binwalk 是固件解析的“第一把刀”。它通过内置签名库扫描镜像,识别压缩流、文件系统、内核、引导程序等。常用命令:
# 仅扫描,不提取,先看整体结构
binwalk firmware.bin
# 递归提取所有识别到的内容
binwalk -e firmware.bin
# 指定提取目录,并保留权限
binwalk -e --directory=out firmware.bin
# 熵值分析,判断是否加密或压缩
binwalk -E firmware.bin
熵值图很关键:如果某段熵接近 1.0,说明是高熵数据,可能是加密或强压缩,直接提取会失败,需要先找解密逻辑或密钥。binwalk 的局限是签名匹配,遇到私有格式或偏移错位时可能漏报,此时要结合手动十六进制分析。
firmware-mod-kit(FMK)更适合“已知是嵌入式 Linux 固件”的场景。它封装了 extract-firmware.sh 和 build-firmware.sh,能自动识别 TRX、SquashFS、CramFS 等,并把根文件系统解到 fmk/rootfs。典型用法:
./extract-firmware.sh firmware.bin
# 输出目录结构:
# fmk/rootfs/ 解开的根文件系统
# fmk/image_parts/ 各分段镜像
# fmk/unsquashfs/ SquashFS 解包日志
FMK 的价值在于“可重建”:修改 rootfs 后可用 build-firmware.sh 重新打包,便于做动态验证。但它对 UEFI 和 RTOS 支持有限,不要拿它去拆 BIOS 镜像。
三、文件系统识别与挂载
提取出文件系统镜像后,下一步是识别类型并挂载。识别优先看 magic:SquashFS 以 hsqs 开头,JFFS2 以 0x1985 开头,UBIFS 有 UBI# 标记,ext4 有 0x53EF。也可用 file 和 binwalk 辅助判断。
挂载时要注意:嵌入式文件系统常是小端、非 4K 块、带压缩,直接 mount 可能失败。推荐用只读挂载,避免污染证据:
# SquashFS 只读挂载
sudo mount -t squashfs -o loop,ro rootfs.squashfs /mnt/fw
# ext4 镜像
sudo mount -t ext4 -o loop,ro rootfs.ext4 /mnt/fw
# JFFS2 需要 mtdram 或 nandsim 模拟
sudo modprobe mtdram total_size=65536 erase_size=256
sudo modprobe mtdblock
sudo dd if=rootfs.jffs2 of=/dev/mtdblock0
sudo mount -t jffs2 /dev/mtdblock0 /mnt/fw
挂载成功后,重点审计这些位置:/etc/passwd、/etc/shadow、/etc/init.d/、/usr/sbin/、/www/、/lib/。检查硬编码口令、私钥、调试后门、启动脚本里的明文凭据、以及带 setuid 位的二进制。若文件系统是只读 SquashFS,还要注意厂商是否在启动时用 overlay 写入可写层,这会影响漏洞利用路径的判断。
四、实操中的判断与常见坑
实际解析时,最常遇到三类问题。第一,binwalk 提取失败或只提出一堆碎片,通常是因为镜像被私有头偏移、异或加密或分块压缩。此时应先用 binwalk -E 看熵曲线,再用十六进制编辑器定位 magic 的真实偏移,必要时写脚本做异或或解头。第二,SquashFS 版本不匹配导致 unsquashfs 报错,可用 unsquashfs -s 查看版本,换用对应版本的 squashfs-tools。第三,JFFS2/UBIFS 无法直接 loop 挂载,必须借助 mtdram、nandsim 或 ubiblock 模拟 MTD 设备。
还有一个容易被忽略的点:很多固件在根文件系统之外,还有独立的 /data 或 /nvram 分区,里面存着设备配置、Wi-Fi 口令、证书。这些分区往往不在主镜像里,而是运行时从 Flash 另一区域读取。做完整审计时,应结合设备启动日志或分区表(/proc/mtd、/proc/partitions)确认是否遗漏。
完成本节后,你应当能够:根据固件类型选择正确的解析路径;用 binwalk 和 firmware-mod-kit 完成提取;识别 SquashFS、JFFS2、UBIFS、ext4 等文件系统并只读挂载;在挂载后的根文件系统中定位口令、脚本、私钥和 setuid 二进制等高风险对象。下一阶段将在此基础上,对提取出的二进制和脚本做静态漏洞扫描。