3、固件解包与文件系统分析:Binwalk工具使用、文件系统挂载、固件结构识别

各位同学好,我是老周。今天咱们聊固件解包和文件系统分析。说实话,这是支付终端安全检测里最基础、也最核心的一步。你拿到的固件是个黑盒子,不拆开它,后面所有分析都无从谈起。

我刚开始做这行的时候,也踩过不少坑。有一次拿到一个POS机的固件,用Binwalk扫了半天啥也没发现,后来才发现是固件头被厂商做了特殊处理。嗯,今天我就把这些经验都抖出来,咱们一步步来。

3.1 固件结构识别——先摸清底细

拿到一个固件文件,别急着解包。我个人的习惯是:先看看它到底是什么结构。说白了,就是搞清楚这个文件是裸的二进制,还是带了个文件系统,或者是多个分区拼起来的。

怎么识别?最直接的办法是用 file 命令。比如:

$ file pos_firmware.bin
pos_firmware.bin: data

如果返回 data,说明文件头被抹掉了,或者是个裸的二进制。这时候就需要用 Binwalk 来扫描了。

核心思路:固件通常由 Bootloader、内核、文件系统、配置数据等部分组成。识别出这些分区的边界,是解包的第一步。

3.2 Binwalk工具使用——我的瑞士军刀

Binwalk 是我最常用的固件分析工具,没有之一。它本质上是个签名扫描器,能识别出固件里嵌入的各种文件系统和压缩数据。

基本用法很简单:

$ binwalk pos_firmware.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             uImage header, header size: 64 bytes, ...
65536         0x10000         SquashFS filesystem, little endian, ...
131072        0x20000         JFFS2 filesystem, little endian, ...

看到没?它把每个分区的偏移地址和类型都列出来了。我个人习惯先看 DECIMAL 这一列,因为后面挂载文件系统的时候,需要用到这个偏移量。

我曾经遇到过一个案例,厂商把文件系统藏在了固件的中间位置,前面塞了一大堆填充数据。Binwalk 一扫描,直接就把 SquashFS 的起始地址给揪出来了。你想想看,要是手动去翻二进制,那得翻到猴年马月去。

3.2.1 常用参数

参数 作用 我的用法
-e 自动提取识别的文件 偷懒的时候用,但有时会漏东西
-M 递归扫描(扫描提取出的文件) 对付多层嵌套的固件很管用
-T 显示文件类型详情 我一般配合 -D 一起用
-D 指定提取类型 比如只提取 SquashFS

小技巧:binwalk -Me pos_firmware.bin 可以一键递归提取。但注意,如果固件很大,可能会生成大量文件,建议先手动分析偏移量再提取。

3.3 文件系统挂载——把固件变成文件夹

提取出文件系统镜像之后,下一步就是挂载它。说白了,就是把那个二进制文件当成一个硬盘分区,挂到 Linux 的某个目录下,然后像操作普通文件夹一样去浏览它。

支付终端里最常见的三种文件系统:SquashFS、CramFS、JFFS2。我一个个说。

3.3.1 SquashFS——只读的压缩文件系统

SquashFS 是 Linux 嵌入式系统里用得最多的只读文件系统。它压缩率高,读取快,适合存放固件里的程序和数据。

挂载命令:

# 假设从固件偏移 0x10000 处提取出了 squashfs.img
$ unsquashfs squashfs.img
# 或者用 mount 挂载
$ mount -t squashfs squashfs.img /mnt/squashfs -o loop

我个人更推荐用 unsquashfs,因为它直接解压到当前目录,方便后续分析。用 mount 的话,记得用完要 umount,不然会占用资源。

注意:有些厂商会对 SquashFS 做自定义修改,比如改了压缩算法或者加了校验。这时候标准工具可能解不开,需要逆向分析它的解压逻辑。我曾经遇到过一家厂商,把 SquashFS 的魔数从 hsqs 改成了 abcd,害我折腾了一整天。

3.3.2 CramFS——老牌嵌入式文件系统

CramFS 比 SquashFS 更老,现在用得少了,但一些老款支付终端还在用。它的特点是简单、轻量,但压缩率不如 SquashFS。

挂载方法:

$ mount -t cramfs cramfs.img /mnt/cramfs -o loop

嗯,这里要注意,CramFS 不支持写操作,所以挂载后只能读。如果你想修改固件内容,得先解压出来,改完再重新打包。

3.3.3 JFFS2——可读写的闪存文件系统

JFFS2 是专门为 NAND Flash 设计的可读写文件系统。支付终端里,它通常用来存放配置数据、日志文件等需要动态修改的内容。

挂载 JFFS2 稍微麻烦一点,因为它需要模拟一个 MTD 设备:

# 先加载 mtdblock 模块
$ modprobe mtdblock
$ modprobe mtdram total_size=65536 erase_size=256

# 把 JFFS2 镜像写入模拟的 MTD 设备
$ dd if=jffs2.img of=/dev/mtdblock0

# 挂载
$ mount -t jffs2 /dev/mtdblock0 /mnt/jffs2

说实话,这个过程有点绕。我建议你写个脚本,把这几步封装起来,省得每次都要敲一遍。

3.4 实战经验——避坑指南

做固件解包这么多年,我总结了几条血泪教训:

  • 先备份,再操作。 我曾经手滑把原始固件覆盖了,结果只能重新下载。浪费时间不说,还差点耽误项目进度。
  • 注意字节序。 ARM 和 MIPS 的固件字节序可能不同,Binwalk 有时候会识别错。如果发现解出来的文件系统打不开,试试加 --big-endian--little-endian 参数。
  • 别迷信自动提取。 Binwalk 的 -e 参数虽然方便,但遇到非标准固件结构时,它可能会漏掉一些分区。我建议先手动分析偏移量,再针对性提取。
  • 检查文件系统完整性。 挂载成功后,先看看有没有 binetcusr 这些标准目录。如果目录结构很奇怪,可能是提取错了分区。

核心总结:固件解包不是目的,目的是拿到里面的可执行文件、配置文件、脚本等,为后续的漏洞分析、后门检测做准备。所以,解包这一步做得越扎实,后面的分析就越顺利。

3.5 知识体系图

下面这张图是我自己画的,把固件解包与文件系统分析的整个流程串起来了。你照着这个思路走,基本不会迷路。

固件解包与文件系统分析流程 固件文件 结构识别(file + Binwalk) 分区提取(dd + Binwalk -e) 文件系统类型判断(SquashFS / CramFS / JFFS2) SquashFS unsquashfs / mount CramFS mount -t cramfs JFFS2 mtdblock + mount

这张图里,从固件文件开始,经过结构识别、分区提取,再到三种文件系统的挂载方式,一目了然。你把它打印出来贴在工位上,干活的时候瞄一眼,效率能提高不少。


好了,这一章就讲到这里。固件解包是个手艺活,多练几次就熟了。下一章咱们聊聊怎么从解包后的文件系统里找漏洞,那才是真正有意思的部分。

专注资料整理