4、二进制文件分析基础:file命令、binwalk、strings、hexdump、熵分析

拿到一个固件,第一件事是什么?

我个人的习惯是——先别急着拆,先看看它到底是什么东西。就像你收到一个快递,总得先看看包装上的标签吧?二进制文件分析,就是给固件「验明正身」的过程。

4.1 file命令:三秒看穿文件本质

file 命令是我用得最多的工具,没有之一。它不依赖文件扩展名,而是通过检查文件头部的魔数(Magic Number)来判断文件类型。

核心原理:每个文件格式都有独特的头部签名。比如 ELF 文件以 7f 45 4c 46 开头,JPEG 以 ff d8 ff 开头。file 命令就是靠这些签名来识别的。

# 基本用法
$ file firmware.bin
firmware.bin: data

# 如果固件是已知格式
$ file u-boot.bin
u-boot.bin: u-boot legacy uImage, Linux Kernel Image, ...

# 查看压缩包
$ file rootfs.squashfs
rootfs.squashfs: Squashfs filesystem, little endian, version 4.0

我在项目中遇到过好几次,甲方给的固件后缀是 .bin,但用 file 一看,其实是 ZIP 压缩包。你想想看,如果直接当二进制去逆向,那得多走多少弯路?

小技巧:file -k 可以强制显示所有匹配的类型,有时候一个文件可能包含多层结构。

4.2 binwalk:固件拆解瑞士军刀

binwalk 是我做固件逆向时离不开的工具。它不仅能识别文件类型,还能帮你把固件里的各个组件拆出来。

说白了,binwalk 就是 file 命令的「超级增强版」。它会扫描整个二进制文件,寻找已知的文件签名,然后告诉你:这里有个 LZMA 压缩块,那里有个 Squashfs 文件系统。

# 扫描固件中的文件签名
$ binwalk firmware.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             u-boot legacy uImage, Linux Kernel Image
64            0x40            LZMA compressed data
131072        0x20000         Squashfs filesystem, little endian, version 4.0

# 提取所有识别到的文件
$ binwalk -e firmware.bin

# 只提取特定偏移的文件
$ binwalk -D 'squashfs:rootfs:squashfs' firmware.bin

我曾经接手过一个路由器固件,用 binwalk 一扫描,发现里面嵌套了 3 层压缩:先是 gzip,然后是 LZMA,最后才是真正的文件系统。如果没有 binwalk,手动找这些边界点会非常痛苦。

注意:binwalk 的签名数据库不是万能的。遇到自定义加密或混淆的固件,它可能什么都识别不出来。这时候就需要结合熵分析来人工判断了。

4.3 strings:从二进制中捞取文本信息

strings 命令看似简单,但用好了能挖出不少线索。它会从二进制文件中提取可打印的字符串序列。

# 提取所有长度 >= 4 的字符串
$ strings firmware.bin

# 提取所有字符串(包括短字符串)
$ strings -n 2 firmware.bin

# 同时显示偏移地址
$ strings -t x firmware.bin

# 结合 grep 快速定位关键信息
$ strings firmware.bin | grep -i "version\|model\|build"

嗯,这里要注意:strings 只能提取连续的 ASCII 或 Unicode 字符串。如果固件用了简单的 XOR 加密,字符串就看不到了。我遇到过一些 IoT 设备,厂商会把关键字符串做异或处理,这时候 strings 就抓瞎了。

实战经验:我习惯先用 strings 看看固件里有没有文件路径、IP 地址、版本号这些信息。这些往往是逆向的突破口。比如看到 /etc/config/network,基本就能确定这是 OpenWrt 系的固件。

4.4 hexdump:二进制文件的「X光片」

hexdump(或 xxd、od)能让你看到二进制文件的原始字节。虽然看起来是一堆十六进制数字,但经验丰富的工程师能从中读出很多信息。

# 查看文件头部(前 64 字节)
$ hexdump -C firmware.bin | head -n 4

00000000  7f 45 4c 46 01 02 01 00  00 00 00 00 00 00 00 00  |.ELF............|
00000010  02 00 03 00 01 00 00 00  54 80 04 08 34 00 00 00  |........T...4...|

# 查看指定偏移
$ hexdump -s 0x20000 -n 128 firmware.bin

# 用 xxd 更方便
$ xxd firmware.bin | head -n 10

为什么还要学 hexdump?因为有些时候,binwalk 和 file 都认不出来的东西,你用手动看头部字节反而能发现规律。比如我看到 1f 8b 08 就知道是 gzip 压缩,看到 89 50 4e 47 就知道是 PNG 图片。

需要记住的常见魔数:

魔数(十六进制)文件类型
7f 45 4c 46ELF
1f 8b 08gzip
42 5a 68bzip2
89 50 4e 47PNG
ff d8 ffJPEG
55 aaMBR 引导扇区

4.5 熵分析:识别加密与压缩的利器

熵(Entropy)这个概念,说白了就是衡量数据「混乱程度」的指标。纯文本的熵值较低(大约 4-5),而加密或压缩后的数据熵值接近 8(最大值)。

为什么这个重要?因为固件里经常有加密的代码段或压缩的数据块。用肉眼很难看出来,但熵分析能一目了然。

# 使用 binwalk 的熵分析功能
$ binwalk -E firmware.bin

# 输出会生成一个 ASCII 图表,显示每个区域的熵值
# 高熵区域(接近 8.0)通常是加密或压缩数据
# 低熵区域(接近 4.0)通常是明文代码或数据

我记得有一次分析一个工控设备的固件,binwalk 什么都没扫出来。但我用熵分析一看,发现 0x10000 到 0x20000 这段区域的熵值高达 7.9,明显是加密或压缩数据。后来手动分析发现,厂商把文件系统做了 XOR 加密,密钥就藏在固件的另一段低熵区域里。

实用技巧:我经常把熵分析和 binwalk 结合起来用。先用熵分析找出可疑的高熵区域,再用 binwalk 去针对性扫描这些区域。这样能大大提高识别成功率。

4.6 综合实战:一个完整的分析流程

说了这么多,我们来走一遍完整的流程。假设你拿到一个叫 fw_update.bin 的文件:

  1. 第一步:file 命令 — 看看文件类型,结果是 data,说明不是标准格式。
  2. 第二步:strings 快速扫描 — 发现 U-Bootkernelrootfs 等关键词,确认是嵌入式固件。
  3. 第三步:binwalk 扫描 — 识别出 uImage 头部、LZMA 压缩数据、Squashfs 文件系统。
  4. 第四步:熵分析 — 确认各区域的熵值分布,验证 binwalk 的识别结果。
  5. 第五步:hexdump 验证 — 手动查看关键偏移处的字节,确认魔数是否正确。
  6. 第六步:binwalk -e 提取 — 拆解固件,得到内核镜像和文件系统。

避坑指南:我曾经遇到过一个固件,binwalk 识别出了 Squashfs,但提取后挂载失败。后来用 hexdump 一看,发现文件系统的魔数被厂商篡改了一个字节。这种「反逆向」手段在商业固件中并不少见。

4.7 知识体系总览

下面这张图总结了二进制文件分析的核心工具和它们之间的关系:

二进制文件分析工具体系 固件二进制文件 file 命令 魔数匹配,3秒识别 strings 命令 提取文本线索 hexdump 原始字节查看 binwalk 签名扫描 + 自动提取 熵分析 识别加密/压缩区域 输出:文件类型 / 组件边界 / 提取的文件 / 加密区域定位

这五个工具,说白了就是固件逆向的「五件套」。先用 file 和 strings 快速摸底,再用 hexdump 验证细节,最后用 binwalk 和熵分析做深度拆解。这套流程我用了快十年,基本没失手过。

核心要点回顾:

  • file 看类型,strings 找线索,hexdump 看细节
  • binwalk 是固件拆解的主力,但别完全依赖它
  • 熵分析能发现加密和压缩区域,是逆向的「透视眼」
  • 五个工具配合使用,才能全面掌握固件结构

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