3. 文件系统解析:Squashfs、Cramfs、JFFS2 文件系统解析、文件系统挂载与只读问题处理

拿到固件之后,第一件事是什么?

我个人习惯,不是急着去翻代码,而是先看看它的文件系统是什么类型。你想想看,固件里藏着路由器的配置、Web 界面、二进制程序,甚至后门。如果连文件系统都挂不上,后面全是白搭。

今天我们就来聊聊固件里最常见的三种文件系统:SquashfsCramfsJFFS2。我会结合我踩过的坑,告诉你它们怎么解析、怎么挂载,以及遇到只读问题该怎么处理。

3.1 为什么固件爱用这些文件系统?

说白了,嵌入式设备资源有限。Flash 空间就那么几兆到几十兆,RAM 更是抠着用。所以文件系统必须满足两个条件:

  • 压缩率高:能塞更多东西进去
  • 只读或日志型:防止意外断电搞坏系统

Squashfs 和 Cramfs 是只读压缩文件系统,适合存放固件本体。JFFS2 是日志型文件系统,适合存放配置、日志等需要频繁写入的数据。

核心思路:拿到固件后,先用 binwalkfile 命令识别文件系统类型,再选择对应的工具进行解析。

3.2 Squashfs 解析:最常用的固件文件系统

Squashfs 是目前思科、TP-Link、小米等路由器固件最常用的文件系统。它支持高压缩比,而且解压速度快。

3.2.1 识别 Squashfs

binwalk 扫描固件,你会看到类似这样的输出:

$ binwalk firmware.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             uImage header, ...
...
1048576       0x100000        Squashfs filesystem, little endian, version 4.0, ...

看到 "Squashfs filesystem" 字样,就说明找到了。注意看版本号,Squashfs 4.0 和 3.0 的压缩算法不同,解压工具也不一样。

3.2.2 解压 Squashfs

我推荐用 unsquashfs 工具,它是 squashfs-tools 包里的。用法很简单:

# 先提取出 Squashfs 分区
dd if=firmware.bin of=squashfs_part.bin bs=1 skip=1048576

# 解压
unsquashfs -d output_dir squashfs_part.bin

如果遇到 "Unknown compression" 错误,别慌。这通常是因为固件用了 LZMA 或 XZ 压缩,而你的工具版本太老。升级 squashfs-tools 到最新版就行。

我的经验:有一次我解压一个思科交换机固件,unsquashfs 报错说 "unsupported compression type 3"。查了半天,发现是用了 LZMA 压缩,而系统自带的 squashfs-tools 不支持。后来我编译了最新版,问题解决。所以,工具版本很重要

3.2.3 重新打包 Squashfs

分析完文件系统,你可能想修改某些文件(比如加个后门),然后重新打包。用 mksquashfs 命令:

mksquashfs modified_dir new_squashfs.bin -comp xz -b 131072

注意,压缩算法和块大小要和原固件一致,否则设备可能不认。怎么知道原固件的参数?用 unsquashfs -s squashfs_part.bin 查看。

3.3 Cramfs 解析:老牌只读文件系统

Cramfs 比 Squashfs 更老,现在用得少了,但在一些老旧思科设备上还能见到。它的特点是简单、轻量,但压缩率不如 Squashfs。

3.3.1 识别与解压

Cramfs 的魔数是 0x28CD3D45(小端序)。binwalk 也能识别:

$ binwalk firmware.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
...
2097152       0x200000        Cramfs filesystem, little endian, size: 4194304

解压用 cramfsckuncramfs

# 方法一:cramfsck(推荐)
cramfsck -x output_dir cramfs_part.bin

# 方法二:uncramfs(老工具)
uncramfs cramfs_part.bin output_dir

注意:Cramfs 不支持大于 256MB 的文件系统,而且单个文件不能超过 16MB。如果你解压时遇到 "File too large" 错误,说明固件可能用了 Cramfs 的变种,或者根本不是 Cramfs。

3.3.2 重新打包 Cramfs

mkcramfs 命令:

mkcramfs modified_dir new_cramfs.bin

嗯,这里要注意:mkcramfs 默认会使用 zlib 压缩,但有些老设备只支持未压缩的 Cramfs。你可以加 -n 参数禁用压缩。

3.4 JFFS2 解析:日志型文件系统

JFFS2 是专门为 Flash 设计的日志型文件系统。它支持磨损均衡和掉电保护,通常用于存放配置、日志等动态数据。

3.4.1 识别 JFFS2

JFFS2 的魔数是 0x1985(小端序)。binwalk 输出示例:

$ binwalk firmware.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
...
3145728       0x300000        JFFS2 filesystem, little endian, size: 2097152

3.4.2 挂载 JFFS2

JFFS2 不能直接用 unsquashfs 解压,需要挂载到 Linux 上。但有个前提:你的内核必须支持 JFFS2 和 MTD 模拟。

# 加载内核模块
modprobe mtdblock
modprobe jffs2

# 创建 MTD 设备
modprobe mtdram total_size=2097152 erase_size=65536
dd if=jffs2_part.bin of=/dev/mtdblock0

# 挂载
mount -t jffs2 /dev/mtdblock0 /mnt/jffs2

关键点total_sizeerase_size 必须和原固件一致。怎么知道?用 binwalk -Mejefferson 工具分析。

3.4.3 使用 jefferson 工具

如果你觉得挂载太麻烦,可以用 jefferson 这个 Python 工具,它可以直接解压 JFFS2 镜像:

pip install jefferson
jefferson -d output_dir jffs2_part.bin

jefferson 会自动处理擦除块大小、压缩等问题。我在项目中用过很多次,基本没出过问题。

3.5 只读问题处理:挂载后无法写入

这是新手最容易卡住的地方。你辛辛苦苦挂载了文件系统,想修改某个文件,结果发现是只读的。

3.5.1 为什么是只读?

原因很简单:Squashfs 和 Cramfs 本身就是只读文件系统。JFFS2 虽然是可写的,但如果挂载时没指定读写权限,也会变成只读。

3.5.2 解决方案

针对不同情况,我有三种处理方式:

文件系统类型 问题 解决方案
Squashfs 只读,无法直接修改 解压 -> 修改文件 -> 重新打包
Cramfs 只读,无法直接修改 解压 -> 修改文件 -> 重新打包
JFFS2 挂载后只读 检查挂载参数,加 -o rw

对于 JFFS2,我曾经犯过一个低级错误:挂载时忘了加 -o rw,结果折腾了半天。正确的挂载命令是:

mount -t jffs2 -o rw /dev/mtdblock0 /mnt/jffs2

避坑指南:我曾经在分析一个思科路由器固件时,发现 JFFS2 分区挂载后是只读的。查了半天,发现是内核没加载 mtdblock 模块。加载之后,问题解决。所以,先检查内核模块

3.6 知识体系结构图

下面这张图总结了本章的核心逻辑,帮你快速理清思路:

固件文件系统解析知识体系 固件文件系统 Squashfs unsquashfs 解压 mksquashfs 打包 Cramfs cramfsck 解压 mkcramfs 打包 JFFS2 mount -t jffs2 jefferson 解压 只读问题处理 解压修改后重新打包 | 检查挂载参数 -o rw

3.7 本章小结

文件系统解析是固件逆向的第一步,也是最关键的一步。我见过太多人卡在挂载阶段,然后放弃。其实说白了,就是三个步骤:

  1. 识别:用 binwalk 找出文件系统类型和偏移
  2. 提取:用 dd 或 binwalk -e 提取分区
  3. 解压/挂载:根据类型选择对应工具

遇到只读问题,别慌。Squashfs 和 Cramfs 本来就是只读的,解压修改后重新打包就行。JFFS2 的话,检查一下挂载参数和内核模块。

下一章,我们会深入探讨如何从文件系统中提取关键信息,比如配置文件、Web 源码和二进制程序。到时候你会发现,文件系统解析只是开胃菜,真正的挑战还在后面。


专注资料整理