2. 固件提取与镜像分析
固件安全工程师的第一项硬功夫,是把目标设备里的固件“完整、可复现”地取出来。取不到镜像,后面的漏洞挖掘、后门排查、签名校验分析都无从谈起。本节围绕三类主流存储介质——SPI Flash、eMMC、UFS——讲清楚它们的读取路径,并用binwalk与firmware-mod-kit完成一次从原始镜像到可读文件系统的拆解。
一、先判断介质类型,再决定读取方式
拿到一块路由器、摄像头或工控板,第一步不是直接上夹子,而是确认存储介质。SPI Flash通常是8脚或16脚的小芯片,容量1MB~32MB,常见型号如W25Q128、MX25L256;eMMC是BGA封装,容量4GB~64GB,走MMC协议;UFS同样是BGA,但走M-PHY/UniPro,容量更大、速度更快,常见于手机和高端车机。判断依据有三点:芯片丝印、主控手册、以及PCB上是否有eMMC/UFS的专用供电与时钟走线。
介质不同,读取策略完全不同。SPI Flash可以离线读取,也可以在线读取;eMMC/UFS通常需要设备进入可访问状态,或直接拆焊后用专用编程器读取。面试中常被追问“为什么eMMC不能像SPI那样随便夹”,答案在于eMMC的BGA焊球间距小、信号完整性要求高,飞线极易导致读取失败或损坏芯片。
二、SPI Flash读取:离线与在线两条路
离线读取是最稳妥的方式。用热风枪拆下SPI Flash,放入编程器(如CH341A、RT809H),选择对应型号后读取。以W25Q128为例,容量16MB,读取命令如下:
flashrom -p ch341a_spi -r firmware.bin
flashrom -p ch341a_spi -w firmware.bin
读取完成后必须校验:连续读两次,用sha256sum比对哈希值。若两次不一致,说明接触不良或芯片老化,需要重新读取。在线读取则通过SPI总线夹子(如SOIC8夹)在设备通电状态下读取,优点是无需拆焊,缺点是主控可能干扰总线,导致读取数据不完整。判断依据是:读取后binwalk能识别出文件系统,且哈希稳定。
三、eMMC与UFS读取:从设备节点到镜像
eMMC在Linux下通常表现为/dev/mmcblk0,UFS表现为/dev/sda或/dev/ufs0。如果设备能进入系统或恢复模式,直接dd即可:
dd if=/dev/mmcblk0 of=emmc_full.bin bs=1M conv=noerror,sync
dd if=/dev/sda of=ufs_full.bin bs=1M conv=noerror,sync
关键参数是conv=noerror,sync,遇到坏块时用零填充并继续,避免中断。读取后检查分区表:
fdisk -l emmc_full.bin
parted emmc_full.bin unit B print
如果设备无法进入系统,就需要拆焊后用专用编程器(如Easy JTAG Plus、UFI Box)读取。UFS读取还需要注意LUN配置,因为UFS通常有多个逻辑单元,需要分别读取。面试中常考“eMMC的boot分区怎么读”,答案是/dev/mmcblk0boot0和/dev/mmcblk0boot1,这两个分区存放一级引导程序,往往包含关键密钥。
四、binwalk实战:从原始镜像到文件系统
拿到镜像后,先用binwalk做签名扫描:
binwalk firmware.bin
典型输出会显示Squashfs、JFFS2、UBI、gzip等签名及其偏移。例如:
DECIMAL HEXADECIMAL DESCRIPTION
0 0x0 uImage header
64 0x40 LZMA compressed data
131072 0x20000 Squashfs filesystem, little endian
看到Squashfs后,用binwalk -e firmware.bin自动提取。若自动提取失败,可手动指定偏移:
dd if=firmware.bin of=squashfs.img bs=1 skip=131072
unsquashfs squashfs.img
提取出的squashfs-root就是完整的根文件系统。此时重点检查/etc/passwd、/etc/shadow、/etc/init.d/、/usr/bin/,寻找硬编码凭据、启动脚本和可疑二进制。
五、firmware-mod-kit:拆解与重打包
firmware-mod-kit适合处理带有多层封装的固件。以extract-firmware.sh为例:
./extract-firmware.sh firmware.bin
它会自动识别uImage、Squashfs、Cramfs等,并输出到fmk/目录。拆解后可在fmk/rootfs/中修改文件,再用build-firmware.sh重打包。重打包时要注意:如果原固件有签名校验,修改后无法启动,此时需要先分析签名机制,或寻找未签名分区。
一个常见教学示例:某路由器固件拆解后,在/etc/init.d/rcS中发现telnetd -l /bin/sh,说明存在调试后门。修改该文件后重打包,若设备能启动且telnet可连,说明签名校验未覆盖该分区。若无法启动,则需进一步分析bootloader的校验逻辑。
六、结果判断与常见陷阱
判断提取是否成功,有三个标准:一是binwalk能识别出至少一个文件系统;二是unsquashfs或mount能正常挂载;三是文件系统内文件数量与预期相符。常见陷阱包括:SPI Flash在线读取时主控干扰导致数据错位;eMMC读取时未处理坏块导致镜像截断;UFS多LUN未全部读取导致遗漏关键分区;binwalk自动提取时因偏移错误提取出损坏文件系统。
最后给出一份可执行的检查清单,供实际工作时逐项核对:
| 检查项 | 操作 | 判断依据 |
|---|---|---|
| 介质确认 | 查看丝印与主控手册 | SPI/eMMC/UFS型号明确 |
| 读取完整性 | 连续读两次比对哈希 | 哈希一致 |
| 分区识别 | fdisk/parted查看分区表 | 分区偏移与大小合理 |
| 文件系统提取 | binwalk -e或手动dd+unsquashfs | 能挂载且文件完整 |
| 敏感文件排查 | 检查passwd、shadow、init.d | 发现硬编码凭据或后门 |
| 重打包验证 | build-firmware.sh后刷入 | 设备能启动且修改生效 |