4、固件解包:使用Binwalk、dd、unsquashfs、jefferson等工具解包不同文件系统
拿到一个固件,第一件事是什么?
不是直接逆向,也不是扔进IDA。你得先把它拆开,看看里面到底装了啥。就像收到一个快递,总得先拆箱子吧?
固件解包这事儿,我干了快十年了。说实话,刚开始那会儿我也踩过不少坑。有一次分析某款路由器固件,用Binwalk扫了半天啥也没发现,后来才发现是文件头被篡改了。嗯,这些经验教训,今天一并分享给你。
4.1 固件解包的核心思路
固件本质上就是一个大二进制文件。它可能包含:
- Bootloader(引导程序)
- 内核镜像
- 文件系统(SquashFS、JFFS2、CramFS等)
- 配置文件、Web界面资源
- 各种二进制可执行文件
解包的目标,就是把这些东西从固件里提取出来。说白了,就是做"逆向拆解"。
核心原则:先识别,再提取。别上来就一顿操作猛如虎,先搞清楚固件是什么格式、用了什么文件系统。
我个人习惯,拿到固件后先跑一遍 file 命令和 binwalk,看看能发现什么。
4.2 Binwalk:固件分析的瑞士军刀
Binwalk 是我用得最多的工具,没有之一。它就像一个"固件CT扫描仪",能帮你快速定位固件里的各个组件。
4.2.1 基本用法
# 扫描固件,识别文件类型和偏移
binwalk firmware.bin
# 提取所有识别的文件
binwalk -e firmware.bin
# 递归提取(遇到嵌套固件继续解包)
binwalk -Me firmware.bin
# 只提取特定类型的文件
binwalk -D 'squashfs:rootfs.squashfs' firmware.bin
你想想看,一个简单的 -e 参数,就能把固件拆得七零八落。但要注意,Binwalk 不是万能的。
避坑指南:我曾经遇到一个固件,Binwalk 扫描出来一堆偏移,但提取出来的文件全是坏的。后来发现是固件用了自定义的魔数(Magic Number),Binwalk 的签名库没覆盖到。这时候就得手动分析了。
4.2.2 进阶技巧
Binwalk 的熵分析功能很实用。它能帮你判断固件是否加密或压缩。
# 生成熵图
binwalk -E firmware.bin
# 指定偏移范围扫描
binwalk -e -o 0x100000 firmware.bin
熵值高的区域,通常是压缩或加密数据。熵值低的区域,可能是明文数据或填充字节。这个技巧我在分析某款IoT摄像头固件时用过,一下子就定位到了加密的配置文件。
4.3 dd:最朴素的切割工具
别小看 dd,它虽然古老,但关键时刻能救命。当 Binwalk 识别出偏移量但提取失败时,我就用 dd 手动切割。
# 从固件中切割指定偏移和大小的数据
dd if=firmware.bin of=header.bin bs=1 skip=0 count=512
# 切割文件系统部分
dd if=firmware.bin of=rootfs.squashfs bs=1 skip=0x100000 count=0x500000
参数说明:
| 参数 | 含义 |
|---|---|
if |
输入文件 |
of |
输出文件 |
bs |
块大小(通常设为1,按字节操作) |
skip |
跳过多少字节开始读取 |
count |
读取多少字节 |
我的经验:用 dd 时,bs=1 虽然慢,但最精确。如果固件很大,可以先用 bs=1024 试切,确认偏移后再用 bs=1 精切。
4.4 SquashFS:最常见的嵌入式文件系统
SquashFS 是嵌入式设备中最常见的只读文件系统。压缩率高,读取快,非常适合资源受限的设备。
4.4.1 使用 unsquashfs 解包
# 解包 SquashFS 镜像
unsquashfs rootfs.squashfs
# 指定输出目录
unsquashfs -d ./extracted_rootfs rootfs.squashfs
# 查看 SquashFS 信息(不解包)
unsquashfs -s rootfs.squashfs
解包后,你会得到一个完整的文件系统目录树。里面通常有 /bin、/usr、/etc、/www 等目录。
4.4.2 处理变种 SquashFS
有些厂商会对 SquashFS 做魔改。比如修改压缩算法、改变块大小等。这时候标准 unsquashfs 会报错。
我记得有一次分析某品牌路由器固件,unsquashfs 直接报 "Unknown compression type"。后来我查了源码,发现它用了 LZMA 压缩,但标准工具只支持 ZLIB。解决办法是重新编译带 LZMA 支持的 unsquashfs。
# 编译支持 LZMA 的 unsquashfs
cd squashfs-tools
make
# 然后使用编译后的版本
注意:如果遇到 "Failed to read superblock" 错误,说明文件系统可能被加密或损坏。别急着放弃,先检查一下偏移是否正确。
4.5 JFFS2:日志结构的文件系统
JFFS2 是另一种常见的嵌入式文件系统,特别适合闪存设备。它支持磨损均衡和掉电保护。
4.5.1 使用 jefferson 解包
jefferson 是目前最常用的 JFFS2 解包工具。它比老旧的 jffs2dump 好用得多。
# 安装 jefferson
pip install jefferson
# 解包 JFFS2 镜像
jefferson rootfs.jffs2
# 指定输出目录
jefferson -d ./extracted_jffs2 rootfs.jffs2
jefferson 会自动处理 JFFS2 的节点结构,提取出完整的文件系统。
4.5.2 处理 JFFS2 的常见问题
JFFS2 镜像有时会包含 OOB(Out-of-Band)数据。这些数据是闪存的额外信息,jefferson 默认会忽略它们。
如果遇到 "No JFFS2 nodes found" 错误,可能是镜像被截断了,或者包含了额外的头部信息。这时候可以试试:
# 先跳过前 N 字节再解包
dd if=rootfs.jffs2 of=clean.jffs2 bs=1 skip=256
jefferson clean.jffs2
小技巧:JFFS2 的魔数是 0x1985(小端序)。你可以用 hexdump 或 binwalk 搜索这个值,快速定位文件系统的起始位置。
4.6 其他文件系统及工具
除了 SquashFS 和 JFFS2,你还会遇到:
| 文件系统 | 解包工具 | 特点 |
|---|---|---|
| CramFS | cramfsck、cramfsswap |
老式只读文件系统,已较少使用 |
| UBIFS | ubireader、ubi_reader |
用于 NAND Flash,支持动态坏块管理 |
| YAFFS2 | unyaffs |
专为 NAND Flash 设计,日志结构 |
| ROMFS | romfsck |
极简只读文件系统,常用于 Bootloader |
# CramFS 解包示例
cramfsck -x ./extracted_cramfs rootfs.cramfs
# UBIFS 解包示例
ubireader_extract_files rootfs.ubi
# YAFFS2 解包示例
unyaffs rootfs.yaffs2 ./extracted_yaffs
4.7 实战:完整解包流程
下面是一个典型的固件解包流程。我拿一个虚构的路由器固件做演示。
# 1. 初步扫描
file firmware.bin
# 输出: data
binwalk firmware.bin
# 输出:
# DECIMAL HEXADECIMAL DESCRIPTION
# 0 0x0 TRX firmware header, little endian
# 256 0x100 LZMA compressed data
# 131072 0x20000 SquashFS filesystem, little endian
# 2. 提取文件系统
dd if=firmware.bin of=rootfs.squashfs bs=1 skip=131072
unsquashfs -d ./rootfs rootfs.squashfs
# 3. 检查提取结果
ls -la ./rootfs/
# 应该看到 bin, etc, lib, usr 等目录
# 4. 如果遇到问题,尝试其他偏移
binwalk -E firmware.bin # 查看熵图
binwalk -A firmware.bin # 查看 CPU 指令
核心要点:
- 先扫描,再提取。别跳过 binwalk 这一步。
- 确认偏移量。错误的偏移会导致提取失败或数据损坏。
- 检查文件系统类型。不同文件系统用不同工具。
- 遇到错误别慌。先看错误信息,再查资料。
4.8 知识体系图
下面这张图展示了固件解包的核心流程和工具选择逻辑。
4.9 常见问题与排错
解包过程中,你肯定会遇到各种问题。我把最常见的几个列出来:
- Binwalk 扫描结果为空:固件可能被加密或使用了自定义格式。试试熵分析,看看数据分布。
- 提取的文件无法解包:偏移量可能不对。用
hexdump手动确认文件系统魔数位置。 - 解包后文件系统不完整:固件可能被分割成多个部分。检查是否有其他偏移位置。
- 工具报错 "Unknown compression":厂商可能魔改了压缩算法。需要找对应版本的解包工具。
我的建议:建立一个"固件解包工具箱",把常用的工具和脚本放在一起。遇到新固件,先跑一遍自动化脚本,能省不少时间。
好了,固件解包这部分就讲到这里。工具和方法都给你了,剩下的就是多练。记住,每个固件都有自己的脾气,别指望一招鲜吃遍天。
公众号:蓝海资料掘金营,微信deep3321