4、固件文件系统识别:常见文件系统特征与识别工具

在IoT固件安全分析中,文件系统是固件内部数据组织的核心骨架。当我们拿到一个固件镜像时,首要任务之一就是确定其内部采用了哪种文件系统格式。这不仅决定了后续能否正确挂载和提取文件,还直接影响对固件逻辑、漏洞面、后门植入点的判断。不同文件系统在超级块(Superblock)结构、压缩算法、Magic Number、存储布局上各有特征,而binwalk、file、strings等工具则是我们识别这些特征的主要手段。本章将系统梳理Squashfs、Cramfs、JFFS2、UBIFS、ext4五大常见文件系统的技术特征,并给出可落地的识别流程与实战案例。

固件文件系统识别决策路径 固件镜像 (firmware.bin) file + binwalk + strings 初步探测 识别Magic Number / 压缩特征 / 字符串 Squashfs hsqs / sqsh Cramfs 0x28cd3d45 JFFS2 0x1985 / 0x1986 UBIFS UBI# / UBI! ext4 0xEF53 (magic) unsquashfs / 7z cramfsck / fsck.cramfs jefferson / jffs2dump ubireader_extract_files debugfs / dumpe2fs 关键:先识别文件系统类型,再选择对应提取工具,避免盲目解包

上图展示了固件文件系统识别的基本决策路径。实际分析中,我们通常先用file和binwalk做粗粒度扫描,再根据扫描结果中的Magic Number和结构特征锁定具体文件系统类型,最后调用对应的专用工具进行提取。下面逐一展开各文件系统的技术细节与识别方法。

4.1 Squashfs:只读压缩文件系统的主力

核心原理

Squashfs是当前IoT设备(尤其是基于OpenWrt、LEDE、DD-WRT的路由器、智能家居网关)中最常见的只读压缩文件系统。它设计目标是在低开销下提供高压缩比,支持gzip、lzma、lzo、xz、zstd等多种压缩算法。Squashfs的超级块起始于偏移0,Magic Number为0x73717368(即ASCII字符串"hsqs"),在文件头部即可直接读取。其结构分为超级块、压缩选项、数据块、inode表、目录表等多个区域,每个数据块独立压缩,支持随机读取。

判断方法

  • binwalk扫描:执行binwalk firmware.bin,若输出中出现Squashfs filesystem, little endian, version 4.0, compression: xz, size: 1234567 bytes,即可确认。
  • file命令:file firmware.bin会直接返回Squashfs filesystem, little endian, version 4.0, compression: xz。
  • strings验证:在镜像中搜索"squashfs"或"hsqs"字符串,可辅助确认。

案例拆解:OpenWrt路由器固件提取

某品牌家用路由器固件router_v1.2.bin,大小约12MB。使用binwalk扫描后,在偏移0x1E0000处发现Squashfs文件系统。进一步用binwalk -e自动提取,成功解包出/etc/passwd、/usr/sbin/lighttpd等关键文件。但注意,binwalk自动提取有时会因压缩算法识别错误而失败,此时可手动指定:unsquashfs -s firmware.bin查看超级块信息,再用unsquashfs -d output_dir -o 0x1E0000 firmware.bin手动提取。

经验提醒:Squashfs v4.0是当前主流,但部分老设备使用v3.0(Magic为"sqsh")。若binwalk无法识别,可尝试7z x firmware.bin,7-Zip对Squashfs支持良好。

4.2 Cramfs:老牌只读压缩文件系统

核心原理

Cramfs(Compressed ROM File System)由Linus Torvalds开发,早期广泛用于Linux嵌入式设备。其超级块Magic Number为0x28cd3d45(小端序),位于文件偏移0。Cramfs不支持写入,所有文件被压缩存储,但压缩粒度较粗(以页为单位),压缩率通常低于Squashfs。Cramfs的inode信息直接嵌入在目录结构中,没有独立的inode表,这使得其结构相对简单,但也限制了文件数量(最大约16MB)。

判断方法

  • binwalk:识别为Cramfs filesystem, little endian, size: 8388608 bytes。
  • file命令:返回Cramfs filesystem, little endian, size: 8388608 bytes。
  • 十六进制查看:xxd firmware.bin | head,前4字节应为45 3d cd 28。

实战场景:老式IP摄像头固件

一台2015年生产的IP摄像头固件,binwalk扫描显示Cramfs文件系统。使用fsck.cramfs --extract firmware.bin命令成功提取。但提取后发现部分配置文件为乱码,原因是Cramfs对文件数据采用zlib压缩,但某些厂商修改了压缩参数。此时可用cramfsck -x output_dir firmware.bin,若仍失败,则需手动解析超级块中的root inode偏移,使用Python脚本逐文件解压。

风险提示:Cramfs不支持大于16MB的文件系统,且单个文件大小上限为16MB。若固件包超过此限制,基本可排除Cramfs。

4.3 JFFS2:面向NAND/NOR Flash的日志型文件系统

核心原理

JFFS2(Journalling Flash File System v2)专为Flash存储设计,具有磨损均衡、掉电恢复能力。其节点类型包括:dirent节点(Magic 0x1985)、inode节点(Magic 0x1986)、cleanmarker节点(Magic 0x1987)等。JFFS2没有固定的超级块位置,而是通过扫描Flash上的节点链表来重建文件系统。因此,binwalk识别JFFS2时通常报告JFFS2 filesystem, little endian,但无法给出精确偏移。

判断方法

  • binwalk:输出JFFS2 filesystem, little endian,但可能伴随多个偏移提示。
  • strings:搜索"JFFS2"或"jffs2"字符串,同时观察是否有大量文件路径信息。
  • 手动检查:在镜像中搜索85 19(小端序0x1985)或86 19,若大量出现,则极可能是JFFS2。

案例拆解:工业路由器JFFS2提取

某工业路由器固件,binwalk扫描显示在偏移0x40000和0x80000处均有JFFS2标记。使用jefferson工具(Python编写的JFFS2解析器)进行提取:jefferson firmware.bin -d output_dir。但jefferson对旧版本JFFS2支持有限,若失败,可尝试jffs2dump或手动解析节点。提取后发现/etc/config/network等配置文件,进一步分析发现默认密码硬编码漏洞。

关键点:JFFS2在NAND Flash上通常有多个擦除块,binwalk可能报告多个JFFS2段。此时应提取第一个完整段,或使用binwalk -e -M递归提取所有段。

4.4 UBIFS:现代NAND Flash的优选方案

核心原理

UBIFS(Unsorted Block Image File System)是JFFS2的继任者,专为MLC NAND和更大容量Flash设计。它运行在UBI(Unsorted Block Images)层之上,UBI负责逻辑块到物理块的映射和磨损均衡。UBIFS的超级块区域包含Magic Number 0x06101831,但更常见的识别特征是UBI卷描述符中的UBI#和UBI!标记。UBIFS支持透明压缩(LZO、zlib)、写回缓存,适合大容量存储。

判断方法

  • binwalk:输出UBIFS filesystem, little endian, size: 1234567 bytes,或UBI image, version: 1。
  • strings:搜索"UBIFS"或"UBI#",通常出现在卷描述符区域。
  • ubireader:使用ubireader_extract_files firmware.bin直接提取UBIFS内容。

实战场景:智能音箱固件分析

某智能音箱固件,binwalk显示UBIFS文件系统。使用ubireader_extract_files -o output_dir firmware.bin成功提取。但提取后部分文件权限异常,原因是UBIFS的inode权限位与标准Linux权限位存在映射差异。此时需在挂载时指定mount -t ubifs -o ro ubi0:rootfs /mnt,或使用ubireader_extract_files --perm保留权限。

经验提醒:UBIFS通常与UBI卷共存,binwalk可能先识别UBI头,再识别UBIFS。提取时应先提取UBI镜像,再从中解析UBIFS卷。

4.5 ext4:通用Linux文件系统在固件中的特殊存在

核心原理

ext4(Fourth Extended File System)是Linux桌面和服务器的主流文件系统,在IoT固件中较少作为根文件系统,但常见于以下场景:SD卡镜像、eMMC用户数据分区、开发板调试分区。ext4的超级块位于偏移1024字节处,Magic Number为0xEF53。ext4支持日志、扩展属性、大文件,但需要内核驱动支持,且不适合直接烧录到NOR/NAND Flash。

判断方法

  • file命令:返回Linux rev 1.0 ext4 filesystem data, UUID=..., volume name "rootfs"。
  • binwalk:通常报告ext4 filesystem,但binwalk对ext4的识别能力较弱,可能漏报。
  • dumpe2fs:dumpe2fs -h firmware.bin可读取超级块信息,确认文件系统版本。

案例拆解:开发板SD卡镜像分析

某开发板SD卡镜像sdcard.img,大小4GB。file命令直接识别为ext4。使用debugfs -R "ls -l /" sdcard.img列出根目录,发现app/、config/等目录。进一步使用mount -o loop,ro sdcard.img /mnt挂载后,直接读取文件。但注意,SD卡镜像可能包含多个分区,需先用fdisk -l sdcard.img查看分区表,再挂载对应分区。

风险提示:ext4文件系统在固件中可能不是从偏移0开始,而是位于某个分区内。直接对整镜像执行mount可能失败,必须先定位分区偏移。

4.6 文件系统识别工具链与综合对比

文件系统 Magic Number / 特征 binwalk识别 file识别 专用提取工具 典型应用场景
Squashfs 0x73717368 ("hsqs") 优秀 优秀 unsquashfs, 7z OpenWrt路由器、智能网关
Cramfs 0x28cd3d45 良好 良好 fsck.cramfs, cramfsck 老式IP摄像头、工控设备
JFFS2 0x1985 / 0x1986 中等 较弱 jefferson, jffs2dump 工业路由器、NAND Flash设备
UBIFS 0x06101831 / UBI# 良好 中等 ubireader_extract_files 智能音箱、高端路由器
ext4 0xEF53 (偏移1024) 较弱 优秀 debugfs, mount SD卡镜像、eMMC分区

识别流程清单

  1. 第一步:file命令初判——快速获取文件系统类型和字节序。
  2. 第二步:binwalk深度扫描——获取文件系统偏移、大小、压缩算法。
  3. 第三步:strings辅助验证——搜索文件系统名称字符串,确认是否存在多个文件系统。
  4. 第四步:十六进制检查Magic——对可疑偏移执行xxd,人工确认Magic Number。
  5. 第五步:选择专用工具提取——根据文件系统类型调用对应工具。
  6. 第六步:验证提取结果——检查关键目录(/etc、/bin、/usr/sbin)是否完整。

常见误区与复盘

  • 误区一:binwalk识别不到就认为没有文件系统——binwalk对JFFS2和ext4的识别能力有限,应结合file和strings。
  • 误区二:忽略多文件系统共存——固件可能同时包含Cramfs(内核)和Squashfs(根文件系统),需逐一提取。
  • 误区三:盲目使用binwalk -e自动提取——自动提取可能因压缩算法误判而失败,手动指定偏移和工具更可靠。
  • 误区四:忽略字节序——大端序设备(如某些MIPS路由器)的Magic Number字节序相反,需注意转换。
复盘总结:文件系统识别是固件逆向的基石。建议建立"file + binwalk + strings + xxd"四步识别法,并针对每种文件系统准备专用提取工具。在实际分析中,优先使用binwalk的-e参数自动提取,失败后再手动介入。同时,务必记录文件系统偏移、大小、压缩算法等元数据,为后续的固件解包、漏洞挖掘和固件对比分析奠定基础。