4、文件系统解析:Squashfs、JFFS2、UBIFS等嵌入式文件系统

好,咱们进入正题。这一章聊的是嵌入式文件系统。说白了,就是固件里那些数据是怎么组织、怎么存放的。你拿到一个思科路由器的固件,解压出来一堆二进制文件,怎么找到里面的配置文件?怎么把文件系统挂载到本地?这些就是本章要解决的问题。

我个人习惯,拿到一个固件后,第一件事就是看它的文件系统类型。为什么?因为不同的文件系统,提取方式完全不同。你拿处理Squashfs的方法去搞JFFS2,那肯定碰一鼻子灰。

4.1 嵌入式文件系统三巨头

嵌入式世界里,文件系统就那么几种。我挑三个最常见的讲:Squashfs、JFFS2、UBIFS。你想想看,思科、华为、中兴这些厂家的固件,十有八九跑不出这三个。

文件系统 特点 适用场景 压缩方式
Squashfs 只读、高压缩比 固件根文件系统 gzip/lzma/lzo
JFFS2 可写、磨损均衡 NOR Flash zlib
UBIFS 可写、大容量支持 NAND Flash LZO/zlib

嗯,这里要注意。Squashfs是只读的,你没法直接往里面写东西。但好处是压缩率高,同样的空间能塞更多数据。我在项目中遇到过,一个40MB的固件,解压出来能有200MB。这就是Squashfs的功劳。

4.2 Squashfs的挂载与提取

Squashfs是最常见的。思科很多低端路由器都用它。怎么识别?用binwalk扫一下固件,看到"Squashfs filesystem"的标识,那就是了。

提取Squashfs,我推荐两种方法:

  1. 用unsquashfs直接解压——最简单,一行命令搞定
  2. 挂载后拷贝——适合你想保留文件属性的场景

方法一:unsquashfs解压

# 先找到Squashfs的起始偏移
binwalk -Me firmware.bin

# 假设偏移是0x123456,直接解压
unsquashfs -offset 0x123456 firmware.bin

# 解压后的文件在squashfs-root目录下

我曾经遇到过一个坑。有个固件,binwalk识别出了Squashfs,但unsquashfs死活解压不出来。后来发现是厂商自己魔改了Squashfs的头部。怎么办?手动分析偏移,用dd把Squashfs部分切出来,再尝试挂载。

小技巧:如果unsquashfs报错,试试用sasquatch。这个工具能处理一些非标准的Squashfs变种。

4.3 JFFS2的处理方式

JFFS2在思科的老设备上很常见。它跟Squashfs不一样,是可写的。但这也意味着它更复杂——有日志结构、有磨损均衡。

提取JFFS2,我一般用jefferson这个工具。它是个Python写的JFFS2解析器,比手动挂载方便多了。

# 安装jefferson
pip install jefferson

# 提取JFFS2文件系统
jefferson -d output_dir jffs2_partition.bin

你可能会问,为什么不直接挂载?嗯,因为JFFS2需要MTD设备支持。你在普通Linux上挂载JFFS2,得先模拟一个MTD设备。不是不行,但麻烦。jefferson直接解析二进制文件,省事。

注意:JFFS2的镜像可能有多个erase block。jefferson会自动处理,但如果你用dd切分,一定要算好每个block的大小。我见过有人切错了,结果文件系统全是乱码。

4.4 UBIFS——大容量NAND的标配

UBIFS是后来兴起的,专门针对NAND Flash。思科的中高端设备,比如Catalyst系列,很多都用它。UBIFS比JFFS2强在哪?支持更大的分区、更快的挂载速度、更好的压缩。

提取UBIFS,需要两步走:

  1. 从固件中分离出UBI镜像
  2. ubireaderubi_reader提取文件
# 用ubireader提取
ubireader_extract_files ubi_image.bin

# 或者手动挂载(需要内核支持)
modprobe ubi
ubiattach -p /dev/ubi_ctrl -m 0 -O 2048
mount -t ubifs ubi0:rootfs /mnt/ubifs

我个人习惯用ubireader。为什么?因为手动挂载需要内核模块,而且不同内核版本兼容性不一样。ubireader是纯Python的,跨平台,省心。

4.5 关键配置文件定位

文件系统挂载好了,接下来就是找配置文件。思科设备最重要的配置文件是startup-configrunning-config。但它们在文件系统里的位置,不同型号不一样。

我总结了一个查找路径的优先级:

  • /etc/startup-config —— 最常见的位置
  • /flash/startup-config —— 有些设备放在flash分区
  • /nvram/startup-config —— 老设备喜欢放这里
  • /mnt/config/startup-config —— 定制化固件可能的位置

除了startup-config,还有几个文件值得关注:

文件名 说明 重要性
startup-config 启动配置文件 ⭐⭐⭐⭐⭐
running-config 当前运行配置 ⭐⭐⭐⭐
private-config 加密的私有配置 ⭐⭐⭐
system.cfg 系统级配置 ⭐⭐⭐

实战技巧:如果找不到startup-config,试试搜索所有包含"enable password"或"username"的文件。用grep -r "enable password" .,往往能直接定位到配置文件。

4.6 知识体系总览

说了这么多,我画个图帮你理清思路。嵌入式文件系统解析的核心流程,其实就是三步:识别类型、挂载提取、定位关键文件。

嵌入式文件系统解析核心流程 步骤1:固件分析 步骤2:类型识别 步骤3:挂载提取 binwalk扫描 hexdump分析 Squashfs JFFS2 / UBIFS unsquashfs / jefferson ubireader / mount 最终目标:定位startup-config

这张图把整个流程串起来了。你从固件分析开始,识别出文件系统类型,然后选择合适的工具挂载提取,最后定位到startup-config。每一步都有对应的工具和方法,按图索骥就行。

4.7 避坑指南

最后,分享几个我踩过的坑:

  • 偏移量算错——binwalk给出的偏移是十进制,但有些工具要十六进制。我曾经因为这个浪费了半天。
  • 文件系统被加密——有些厂商会对Squashfs进行AES加密。遇到这种情况,先找解密密钥,通常在bootloader里。
  • 配置文件被混淆——startup-config里的密码可能是加密的。别慌,思科的加密算法有规律可循,Type 7密码可以直接在线解密。

我的建议:每次处理新固件,先建一个工作目录。把binwalk的结果、提取的文件、分析笔记都放一起。这样回头查问题,能省不少时间。

好了,文件系统解析这块就讲这么多。你把这些方法练熟了,以后拿到任何嵌入式固件,都能快速找到你想要的东西。

专注资料整理