3、固件文件系统分析:binwalk工具使用、常见文件系统识别

拿到一个固件,我最想干的事是什么?

说白了,就是看看里面到底装了啥。是Linux内核?是文件系统?还是Bootloader?

这就像拆快递——你得先知道包装里是什么结构,才能下手。

今天我们就聊聊固件文件系统分析。这是逆向工程里最基础、也最核心的一步。

3.1 binwalk:固件分析的瑞士军刀

binwalk这个工具,我用了快十年了。它不是什么黑科技,但确实好用。

它的核心能力就两个:

  • 扫描固件:找出里面嵌入的各种文件、文件系统、压缩包
  • 提取内容:把识别出来的东西拆出来,方便后续分析

我个人习惯,拿到固件第一件事就是跑一遍binwalk。看看里面有没有惊喜。

3.1.1 基本用法

先来个最简单的:

binwalk firmware.bin

这条命令会扫描固件,列出所有它认识的文件签名。输出大概长这样:

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             uImage header, header size: 64 bytes
64            0x40            LZMA compressed data, properties: 0x5D
2621440       0x280000        SquashFS filesystem, little endian, version 4.0

看到没?它直接告诉我:

  • 偏移0x0处是uImage头(Linux内核镜像)
  • 偏移0x40处是LZMA压缩数据
  • 偏移0x280000处是SquashFS文件系统

嗯,这里要注意:binwalk的识别是基于文件签名的。如果固件被加密或者混淆了,它可能什么都认不出来。我在项目中遇到过好几次这种情况——明明知道里面有文件系统,但binwalk就是扫不出来。这时候就得靠手动分析了。

3.1.2 提取文件系统

扫描只是第一步。真正干活的时候,我们需要把文件系统提取出来。

binwalk -e firmware.bin

这条命令会自动提取所有识别到的内容。它会创建一个以固件名命名的文件夹,里面放着拆出来的文件。

如果只想提取特定偏移的内容,可以用:

binwalk -D 'squashfs:0x280000:0x100000' firmware.bin

这个命令的意思是:从偏移0x280000开始,提取0x100000字节的数据,保存为squashfs文件。

我的小技巧: 如果binwalk -e提取失败,试试加上-M参数(匹配模式)。有时候固件里嵌了多个文件系统,默认模式只提取第一个。

3.2 常见文件系统识别

嵌入式设备里,文件系统就那么几种。我总结了一下,最常见的是这三个:

文件系统 特点 常见场景 魔数(Magic Number)
SquashFS 只读、高压缩比 路由器、IoT设备 0x68737173 (hsqs)
JFFS2 可读写、支持磨损均衡 老款路由器、工业设备 0x19851985
CramFS 只读、简单轻量 早期Linux设备 0x28CD3D45

你想想看,为什么SquashFS用得最多?

因为它压缩率高,而且只读——这对固件来说太合适了。固件一般不需要频繁修改,只读还能防止意外损坏。

3.2.1 SquashFS

SquashFS是我遇到最多的文件系统。几乎90%的消费级路由器都在用。

它的魔数是0x68737173,在十六进制编辑器里能看到"hsqs"字样。

提取SquashFS后,挂载它:

sudo mount -t squashfs -o loop extracted_squashfs.bin /mnt/squashfs

挂载成功后,你就能看到完整的文件系统了。包括/bin、/etc、/usr这些目录。

注意: 有些固件会对SquashFS进行加密或自定义魔数。我曾经遇到过一个设备,把魔数改成了0xDEADBEEF,binwalk完全认不出来。最后我是通过分析文件系统的结构特征才找到的。

3.2.2 JFFS2

JFFS2是专门为Flash存储器设计的文件系统。它支持磨损均衡,所以适合频繁写入的场景。

它的魔数是0x19851985。不过要注意,JFFS2的头部结构比SquashFS复杂,有时候binwalk识别不出来。

提取JFFS2后,需要用专门的工具来挂载:

sudo modprobe mtdblock
sudo modprobe jffs2
dd if=extracted_jffs2.bin of=/tmp/jffs2.img
sudo mount -t jffs2 /tmp/jffs2.img /mnt/jffs2 -o loop

嗯,这里步骤有点多。我建议你写个脚本,省得每次手动敲。

3.2.3 CramFS

CramFS是更老的文件系统了。现在新设备基本不用了,但老设备里还能见到。

它的魔数是0x28CD3D45。CramFS的特点是简单,但功能也少——不支持符号链接、不支持设备文件。

挂载CramFS:

sudo mount -t cramfs -o loop extracted_cramfs.bin /mnt/cramfs

我曾经在一个2005年的工业控制器里遇到过CramFS。那设备用的是ARM9处理器,固件才4MB。拆开一看,里面就一个/bin/busybox和几个配置文件。嗯,那个年代的东西确实简单。

3.3 实战:完整分析流程

说了这么多,我们来走一遍完整的流程。假设你拿到了一个路由器固件:

  1. 扫描固件binwalk firmware.bin
  2. 提取内容binwalk -e firmware.bin
  3. 识别文件系统:看输出里的DESCRIPTION列,找到SquashFS/JFFS2/CramFS
  4. 挂载文件系统:用对应的mount命令挂载
  5. 浏览文件系统:看看/etc/passwd、/bin/、/usr/sbin/这些关键目录

就这么简单?嗯,大部分情况是的。但总有些设备不按套路出牌。

避坑指南: 我曾经遇到过一个固件,binwalk扫描出来有SquashFS,但提取后挂载失败。后来发现,固件厂商在文件系统前面加了一个自定义头,偏移了8个字节。解决办法是用dd命令跳过前8个字节:dd if=firmware.bin of=clean_squashfs.bin bs=1 skip=8

3.4 知识体系图

下面这张图,是我自己总结的固件文件系统分析流程。你照着走,基本不会迷路。

固件文件系统分析流程 获取固件 binwalk 扫描 识别文件系统类型 SquashFS JFFS2 CramFS 提取并挂载文件系统

这张图把整个流程串起来了。从获取固件开始,到binwalk扫描,再到识别文件系统类型,最后提取挂载。每一步都有对应的工具和方法。

我个人建议,刚开始做固件分析时,先拿几个常见的路由器固件练手。比如TP-Link、小米、华为的固件,网上都能找到。多跑几遍binwalk,多挂载几次文件系统,慢慢就有感觉了。

最后说一句: 文件系统分析只是第一步。真正有意思的是分析里面的二进制文件、找漏洞、挖后门。但万丈高楼平地起,先把这一步练扎实了再说。

公众号:蓝海资料掘金营,微信deep3321