squashFS 文件系统

squashFS 文件系统

简绍

SquashFS(Squashed File System)是一种压缩只读文件系统,广泛应用于嵌入式系统、Live CD、容器镜像以及需要高效存储的只读环境中。它能够将整个文件系统压缩成一个单一的镜像文件,同时保持对文件和目录的快速访问。

该文件系统最初由 Phillip Lougher 开发,目标是在最小化存储空间的同时,提供良好的读性能。SquashFS 支持多种压缩算法(如 gzip、lzma、xz、zstd 等),并具备块级压缩、inode 和目录表压缩等特性,使其在磁盘空间受限的场景中表现优异。

由于其压缩高效、结构简单、加载快速,SquashFS 成为了很多 Linux 发行版(如 Ubuntu 的 initrd)、嵌入式固件(如 OpenWrt、路由器固件)和容器技术(如 AppImage)中首选的文件系统格式之一。

特点

SquashFS 作为一种专为压缩与只读访问设计的文件系统,具备以下几个显著特点:

1. 高压缩比

SquashFS 支持多种压缩算法(如 gzip、lzma、xz、zstd),能够显著减小文件系统镜像的体积。例如,在嵌入式系统中,它可以大幅减少固件大小,节省宝贵的闪存空间。

2. 只读文件系统

SquashFS 是只读的,这意味着一旦构建完成,内容不可更改。这种特性非常适合用于系统引导、Live 系统、容器镜像等不需要写操作的场景,同时增强了系统的完整性与安全性。

3. 支持大文件和大目录

SquashFS 支持最大达 2^64 字节的文件和文件系统,适用于大规模数据的只读分发。同时,它能高效处理包含成千上万个文件的大型目录结构。

4. 块级压缩

文件内容按块压缩,支持不同大小的压缩块(如 4KB 到 1MB)。块级压缩有助于更快的随机读取性能,因为只需解压相关块即可访问指定内容。

5. 低内存占用

由于采用按需解压的机制,系统在访问 SquashFS 文件时仅解压必要的数据块,整体内存占用较低,适合资源受限的嵌入式平台。

6. 支持多种平台与工具

SquashFS 具有良好的跨平台支持,Linux 内核内置对其的支持,同时拥有成熟的构建与挂载工具(如 mksquashfsunsquashfs),易于集成和使用。

Superblock 分析

在任何文件系统中,Superblock(超级块)都承担着记录文件系统全局元数据的关键角色。对于 SquashFS 而言,superblock 位于镜像文件的起始位置(偏移地址为 0x0),用于描述整个文件系统的结构和入口点信息,是挂载和解析镜像的第一步。

1. superblock 总览

SquashFS 的 superblock 长度固定为 96 字节(v4.0 以后),其结构在头文件 squashfs_fs.h 中定义(对于工具链如 squashfs-tools 或 Linux 内核中的源码)。一个典型的结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
struct squashfs_super_block {
__le32 s_magic; // 魔数,固定为 0x73717368 ("hsqs")
__le32 inodes; // inode 总数
__le32 mkfs_time; // 创建时间(Unix 时间戳)
__le32 block_size; // 块大小(通常为 128KB)
__le32 fragments; // 碎片数量
__le16 compression; // 压缩算法类型
__le16 block_log; // log2(block_size)
__le16 flags; // 标志位,如是否启用校验、是否排序等
__le16 no_ids; // id 数量(用于用户和组)
__le16 s_major; // 主版本号
__le16 s_minor; // 次版本号

__le64 root_inode; // 根目录 inode 的偏移地址
__le64 bytes_used; // 镜像总大小(含 superblock)
__le64 id_table_start; // ID 表起始地址
__le64 xattr_id_table_start;// xattr ID 表地址
__le64 inode_table_start; // inode 表地址
__le64 directory_table_start;// 目录表地址
__le64 fragment_table_start; // 碎片表地址
__le64 export_table_start; // export 表地址(用于 NFS 等)
};

2. 关键字段解析

  • s_magic: 魔数 "hsqs",用于校验是否为 SquashFS 文件系统。

  • block_size: 影响读性能和压缩效果,越大压缩比越高,但访问小文件可能效率降低。

  • compression: 表示所用压缩算法,如 1 为 zlib,2 为 lzma,3 为 lzo,4 为 xz,5为lz4,6 为 zstd。

  • root_inode: 是根目录的入口,在挂载时会从此位置开始解析整个文件系统的目录树。

  • inode_table_startdirectory_table_start: 定位核心的文件与目录元数据。

  • flags: 标志位,各个标志位如下

    1
    2
    3
    4
    5
    6
    7
    8
    #define SQUASHFS_NOI            0        // SQUASHFS_UNCOMPRESSED_INODES(未压缩的 inode)
    #define SQUASHFS_NOD 1 // SQUASHFS_UNCOMPRESSED_DATA(未压缩的数据块)
    #define SQUASHFS_NOF 3 // SQUASHFS_UNCOMPRESSED_FRAGMENTS(未压缩的碎片)
    #define SQUASHFS_NO_FRAG 4 // SQUASHFS_NO_FRAGMENTS(不使用碎片)
    #define SQUASHFS_ALWAYS_FRAG 5 // SQUASHFS_ALWAYS_FRAGMENTS(总是使用碎片)
    #define SQUASHFS_DUPLICATE 6 // SQUASHFS_DUPLICATES(启用重复数据检测)
    #define SQUASHFS_EXPORT 7 // SQUASHFS_EXPORTABLE(导出支持,如 NFS)
    #define SQUASHFS_COMP_OPT 10 // SQUASHFS_COMP_OPTS(压缩选项相关)

    检测标志位宏

    1
    #define SQUASHFS_BIT(flag, bit)		((flag >> bit) & 1)  #检测对应的标志位是否为1

3. 实际分析方法

基于IOT固件分析

得到加密固件,先用binwalk3分析,看到文件系统起始位置和大小

image-20250523160649322

用dd命令提取出来文件系统

1
dd if=MX25L25633F@WSON8_20230829_113609.BIN of=300000.squashfs bs=1 skip=3145728 count=20383964

用工具squashfs-info分析文件系统superblack内容,就可以分析相关加密了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
❯ ./squashfs-info 300000.squashfs
s_magic: 1936814952
inodes: 1711
mkfs_time: 1675834056
block_size: 1048576
fragments: 27
compresultsion: 4
block_log: 20
flags: 192
no_ids: 2
s_major: 4
s_minor: 0
root_inode: 735320905
bytes_used: 20383964
id_table_start: 20383956
xattr_id_table_start: 18446744073709551615
inode_table_start: 20349938
directory_table_start: 20362450
fragment_table_start: 20380678
lookup_table_start: 20383930