第78章 固件逆向(一):固件提取、binwalk使用、文件系统分析
固件逆向,说白了就是拆解嵌入式设备的“灵魂”。我做了这么多年逆向,最深的体会是:拿到一个硬件设备,第一步不是上示波器,而是先想办法把它的固件“请”出来。没有固件,后面的一切都是空谈。
这一章,咱们就聊聊固件提取的几种路子、binwalk这个神器的用法,以及怎么分析文件系统。嗯,这些都是基本功,但也是最容易踩坑的地方。
固件提取的几种姿势
固件提取,说白了就是想办法把设备里的二进制程序拷贝出来。方法有很多,我按常用程度排个序:
- 直接从官网下载——别笑,这是最省事的。很多厂商会提供固件更新包,直接下载解压就行。
- 从Flash芯片读取——用编程器或者JTAG/SWD接口,把Flash里的内容dump出来。
- 通过串口/UART获取——如果设备有调试串口,可以在启动时中断引导,进入uboot或bootloader的shell,然后用命令把固件导出来。
- OTA更新包抓取——抓包工具截获设备升级时的网络流量,从HTTP/FTP/TFTP等协议中提取固件。
- 拆解芯片直接读——遇到加密或者锁死的芯片,有时候得用热风枪吹下来,上编程器硬读。
binwalk——固件分析的瑞士军刀
binwalk这个工具,我用了快十年了。它本质上是一个固件文件扫描器,能识别出固件里嵌入了哪些文件系统、压缩包、内核镜像等等。
基本用法很简单:
# 扫描固件,看看里面有什么
binwalk firmware.bin
# 提取所有识别到的文件
binwalk -e firmware.bin
# 只提取特定类型的文件(比如只提取文件系统)
binwalk -D 'squashfs:rootfs:squashfs' firmware.bin
# 显示详细的偏移量和签名信息
binwalk -Me firmware.bin
binwalk的工作原理,说白了就是靠“签名匹配”。它内置了上百种文件格式的魔数(Magic Number),比如SquashFS文件系统的签名是hsqs,JFFS2的签名是0x1985,等等。
重要:binwalk -e 提取出来的文件,默认放在 _firmware.bin.extracted 目录下。进去看看,你会发现一堆文件夹和文件,其中最重要的就是文件系统镜像。
文件系统分析——找到真正的“肉”
固件里最常见的文件系统类型有几种:
| 文件系统类型 | 常见场景 | 特点 |
|---|---|---|
| SquashFS | OpenWrt、路由器固件 | 只读、压缩率高、启动快 |
| JFFS2 | 老款嵌入式设备 | 可读写、支持磨损均衡 |
| UBIFS | 较新的Linux设备 | 比JFFS2更高效、支持大容量 |
| CramFS | 非常老的设备 | 简单、但功能有限 |
| initramfs/CPIO | 临时根文件系统 | 内存中运行、用于早期引导 |
提取出文件系统之后,怎么挂载它?我一般这么干:
# 如果是SquashFS
unsquashfs rootfs.squashfs
# 如果是JFFS2(需要mtdblock设备)
modprobe mtdblock
modprobe jffs2
dd if=rootfs.jffs2 of=/tmp/jffs2.img
mount -t jffs2 /tmp/jffs2.img /mnt/jffs2
# 如果是UBIFS(需要ubi工具)
modprobe ubi
ubiformat /dev/mtd0 -f rootfs.ubi
ubiattach -m 0
mount -t ubifs ubi0:rootfs /mnt/ubifs
我曾经踩过的坑:有一次分析一个路由器固件,binwalk识别出了SquashFS,但unsquashfs报错说“文件系统损坏”。折腾了半天,后来发现是固件头部有自定义的校验字段,binwalk把偏移量算错了。解决办法是手动跳过头部,用dd命令截取真正的文件系统起始位置。
实战:从零开始分析一个路由器固件
咱们走一遍完整的流程。假设你手头有一个 router_fw.bin:
# 第一步:扫描
binwalk router_fw.bin
# 输出大概长这样:
# DECIMAL HEXADECIMAL DESCRIPTION
# 0 0x0 uImage header, ...
# 64 0x40 LZMA compressed data
# 1310720 0x140000 SquashFS filesystem, little endian, ...
# 第二步:提取
binwalk -e router_fw.bin
# 第三步:进入提取目录
cd _router_fw.bin.extracted/
# 第四步:查看文件结构
ls -la
# 你会看到一堆文件,其中有个 140000.squashfs
# 第五步:解压文件系统
unsquashfs 140000.squashfs
# 第六步:进入解压后的目录,开始分析
cd squashfs-root/
ls -la
# 你会看到 /bin, /sbin, /etc, /usr 等标准Linux目录结构
到了这一步,固件逆向的“地基”就算打好了。接下来你可以分析二进制程序、找后门、挖漏洞,或者修改固件重新打包。
SVG:固件逆向核心流程
避坑指南
做固件逆向这些年,我总结了几条血泪教训:
- 不要迷信binwalk——它识别不出来不代表没有。有些固件用了自定义的魔数或者加密,binwalk会直接跳过。这时候得手动用
hexdump或者strings去翻。 - 注意字节序——ARM设备大多是Little Endian,MIPS设备可能是Big Endian。挂载文件系统时搞反了字节序,会报一堆莫名其妙的错误。
- 文件系统可能被拆分——有些固件把文件系统分成多个块,分布在固件的不同位置。binwalk -e 可能只提取到一部分,需要手动拼接。
- 别忘了检查固件头部——很多厂商会在固件头部加自定义结构,包含版本号、校验和、设备ID等信息。用
hexdump -C看看前几百个字节,往往能发现线索。
一个小技巧:如果你不确定固件里有没有文件系统,先跑一下 strings firmware.bin | grep -i "squash\|jffs\|ubifs\|cramfs"。能匹配到的话,基本就稳了。
嗯,这一章的内容就到这里。固件提取和文件系统分析是逆向的起点,也是决定后续工作能否顺利的关键。多练几次,你就能摸清各种固件的“脾气”了。