rea-reverse

Binwalk 3 使用指南:安装 Rust 重写版、提取固件,以及和 v2 的区别

基于 REA 6.4.0更新于 约 8 分钟读完
本页目录

结论先行:Binwalk 3 是这个固件扫描器的 Rust 重写版,当前发布版本是 3.1.0(2024 年 10 月发布到 GitHub 和 crates.io)。安装方式有四种:cargo install binwalk、Homebrew(brew install binwalk)、Kali 的 binwalk3 软件包,或者官方的 Docker 构建。注意 Debian 和 Kali 里叫 binwalk 的那个包仍然是 Python 版 2.4.3,照着任何教程操作前,先跑一下 binwalk --version。提取要靠外部工具:binwalk -e 列出了签名却什么都没写出来,十有八九是缺了 sasquatch 这类辅助程序。

适合谁读:照着老教程敲命令,结果参数对不上、输出不一样,或者提取目录是空的人。

你会了解到:

  • v3 和 v2 的参数差异,包括两个含义变了的字母。
  • 在 Linux、macOS、Kali 上安装 3.1.0,以及每种方式缺了什么。
  • 扫描、提取、递归提取的用法和输出位置。
  • “什么都没解出来”怎么排查。
  • 什么时候该换 Unblob,以及 REA 怎么同时调用两者。

所有命令都在 2026-10-14 跑过,测试对象是开源的 OpenWrt 25.12.5 镜像(openwrt-25.12.5-ath79-generic-tplink_archer-c7-v5-squashfs-sysupgrade.bin,已对照 OpenWrt 的 sha256sums 校验,下文简称 fw.bin)。Binwalk 分别在 macOS(Homebrew)和 Linux(Debian 13 arm64 容器)上运行。v2 软件包和 Docker 构建我没有跑,这两部分来自文中链接的官方页面。

只在你有权分析的固件上使用这些工具:自己的设备、开源镜像或 CTF 文件。参见 REA 的 DISCLAIMER.md。

v3 和 v2 有什么不同

项目 README 的说法是 “re-written in Rust for speed and accuracy”。准确性这一点,wiki 的 Speed and Accuracy 页面讲得很清楚:v3 用解析器校验每一个匹配并算出它的大小,于是可以直接跳过 gzip 或 SquashFS 的数据体,不会再在里面误报 “MySQL”、“Zlib” 之类的结果。在这个 OpenWrt 镜像上,3.1.0 用 7 毫秒报出恰好两个区域:uImage 内核和 SquashFS 根文件系统。

命令行精简了不少。对照 3.1.0 的 binwalk --help 和 Kali binwalk 页面 上的 v2.4.3 帮助:

用途 v2.4.3 v3.1.0
签名扫描 默认,或 -B 默认
提取 -e -e
递归 -M(-d 控制深度) -M(没有深度参数)
输出目录 -C,默认当前目录 -C,默认 extractions
JSON 结果 -f/--log,-c 输出 CSV -l/--log(只有 JSON)
熵 -E,另有 -J、-N 等 -E,保存 PNG
列出签名 无 -L/--list
包含/排除 -y / -x(按描述匹配正则) -y / -x(按签名名称)
自定义切割 -D/--dd、-z 已移除
原始操作码、对比、偏移 -A、-W、-o、-l/--length 已移除

有两个字母换了含义:-l 在 v2 是 --length,在 v3 是 --log;-L 原来是熵的 --low 阈值,现在是 --list。老脚本里的 -l 4096,到了 v3 会写出一个名叫 4096 的 JSON 文件。

还要注意,wiki 跟的是开发分支。它的 Carving File Data 页面写了 --carve,熵那一页提到 --png,但 3.1.0 发布版都没有,binwalk --carve 会返回 error: unexpected argument '--carve' found。文档里的参数用不了时,先查版本,再怀疑安装。

安装 Binwalk 3

Supported Platforms 页面写明,官方只支持 64 位 Linux,Ubuntu 优先,Windows 和 macOS “largely untested”。每种安装方式都能拿到 binwalk 本体,但不一定附带它要调用的提取器。

方式 A:cargo(任意 Linux,macOS 也行)

sudo apt install build-essential libfontconfig1-dev liblzma-dev   # build deps from the wiki
cargo install binwalk --version 3.1.0 --locked
binwalk --version    # binwalk 3.1.0

我在 Debian 13 容器里就是这样编译的(Rust 1.98.1)。Cargo Installation 页面说得很直接:“Cargo will not install external dependencies”。外部依赖要按 Compile From Source 页面克隆仓库后运行 sudo ./binwalk/dependencies/ubuntu.sh,它会装上 7-Zip、lz4、lzop、cpio、device-tree-compiler、onekey-sec 的 sasquatch 等。

方式 B:Homebrew(macOS)

brew install binwalk     # formula: stable 3.1.0, depends on sevenzip

在 Apple 芯片上装出来就是 3.1.0。7-Zip 会一起装上,但 sasquatch 和 dtc 不会,所以我第一次跑 -e,内核解出来了,文件系统失败(见下面的排查)。macOS 上要解 SquashFS,可以 brew install squashfs,再按 从固件 .bin 里提取 SquashFS 手动用 dd 加 unsquashfs。

方式 C:Kali

sudo apt install binwalk3   # Kali package, version 3.1.0; the command is binwalk3

按 Kali binwalk3 页面 的说明,命令名就叫 binwalk3,同一台机器上的 binwalk 仍是 v2。Debian 方面,sources.debian.org 显示 trixie 和 sid 的 binwalk 是 2.4.3,bookworm 是 2.3.4,没有 binwalk3 包。Ubuntu 的软件包来自 Debian,动手前先 apt-cache policy binwalk 看一眼。v2.4.3 的帮助结尾写着:“Binwalk v2.x will reach EOL in 12/12/2025. Please migrate to binwalk v3.x”。

方式 D:Docker(自带全部提取器)

README 说 Docker 是 “the easiest way to install Binwalk and all dependencies”。按 wiki,克隆仓库后用 sudo ./build_docker.sh 构建,然后这样运行:

sudo docker run -t -v "$PWD":/analysis binwalkv3 -Me firmware.bin

这个镜像我没有构建,列出来是因为它是官方推荐的一次装齐所有提取器的方式。

扫描、提取、递归

$ binwalk fw.bin
0           0x0           uImage firmware image, header size: 64 bytes, data size: 2741921 bytes, compression: lzma, ...
2741985     0x29D6E1      SquashFS file system, little endian, version: 4.0, compression: xz, inode count: 1214, ...
Analyzed 1 file for 85 file signatures (187 magic patterns) in 7.0 milliseconds
$ binwalk -e -C bw fw.bin
[+] Extraction of uimage data at offset 0x0 completed successfully
[+] Extraction of squashfs data at offset 0x29D6E1 completed successfully
$ ls bw/fw.bin.extracted
0  29D6E1
$ ls bw/fw.bin.extracted/29D6E1/squashfs-root
bin  dev  etc  init  lib  mnt  overlay  proc  rom  root ...

这次成功是在装了 sasquatch 的 Linux 上。每个区域一个目录,用十六进制偏移命名。在 macOS 上,Binwalk 还会在输出目录里放一个指向输入文件的符号链接。

-M 会对每个解出的文件再扫一遍。同一个镜像用 binwalk -Me,它解压了内核的 LZMA 数据,又在里面找到两个设备树和一个 CPIO 归档。按 wiki 的说法,结果按可信度着色:“file metadata and at least some portions of the file data were checked” 是绿色,只匹配到魔数是红色。

写脚本时用 JSON 日志:

binwalk -q -l results.json fw.bin

每个区域都有 offset、size、name(例如 squashfs)、confidence(这里两个区域都是 250)和 description。每次运行前记得删掉旧文件:3.1.0 会往已有日志里追加第二个数组,文件就不再是合法 JSON,跑两次之后 Python 的 json.load 报 “Extra data”。

binwalk -E fw.bin 会在当前目录生成熵图 fw.bin.png。长段平坦、接近每字节 8 比特的区域,意味着压缩或加密数据。

排查:“binwalk 提取不出东西”

1. 用错了 Binwalk。 binwalk --version 必须输出 binwalk 3.1.0。如果打印的是 v2 帮助或 Binwalk v2.4.3,你用的是 Python 版。Kali 上请用 binwalk3。

2. 缺提取器。 Binwalk 会打印它尝试执行的命令。我在 macOS 上看到的是:

ERROR binwalk::extractors::common] Failed to execute command sasquatch[".../fw.bin.extracted/29D6E1/squashfs_29D6E1.sqsh"]: No such file or directory (os error 2)
[-] Extraction of squashfs data at offset 0x29D6E1 failed!

跑 -Me 时,设备树那一步又因为缺 dtc 失败。binwalk -L 能查到每种格式依赖哪个辅助程序,最容易漏装的是:sasquatch(SquashFS)、jefferson(JFFS2)、ubireader_extract_images / ubireader_extract_files(UBI 和 UBIFS)、7zz(CramFS 和各种归档)、dtc(设备树)。onekey-sec 提供 amd64、arm64、armhf 的 sasquatch .deb 包。我在 macOS 上编译不了,因为它的源码需要 Linux 头文件 sys/sysinfo.h。

3. 输出太少,看不出原因。 错误通过 Rust 的 env_logger 输出到 stderr。按 Errors and Debugging 页面,RUST_LOG=debug binwalk -Me fw.bin 显示全部日志,RUST_LOG=off 全部关掉。

4. 数据是加密的或私有格式。 如果扫描找到一个头,后面全是噪声,就跑一下 -E。一段区域的熵一直接近每字节 8 比特,又没有任何可识别的签名,大概率是加密的,什么提取器都打不开。看看厂商有没有发布未加密的镜像或 GPL 源码。

5. 内存不够。 Limitations 页面写着,Binwalk “requires at least as much free memory as the size of the file(s) being analyzed”。

Binwalk 和 Unblob 怎么选

Unblob(onekey-sec 出品,MIT 许可,PyPI 上的 Python 包,当前 26.6.4)做的是同一件事,只是思路不同。我在同一个 Linux 容器里、用同一个 sasquatch,对同一个 OpenWrt 镜像分别跑了 Unblob 26.6.4 和 Binwalk 3.1.0:

Binwalk 3.1.0 Unblob 26.6.4
思路 签名扫描 + 校验解析器,然后提取 用格式解析器确定每个块的起止,然后提取
认不出的字节 不输出 切成 .unknown 块(这里是 64 字节 uImage 头和 37,383 字节尾部)
递归 加 -M 才开 默认开启,最多 10 层(README)
输出命名 十六进制偏移:29D6E1/squashfs-root 十进制区间:2741985-7368479.squashfs_v4_le_extract
报告 -l 输出 JSON 日志 终端汇总表;--report 输出 JSON 报告
安装 Rust 二进制,提取器另装 pip install unblob,提取器另装(unblob --show-external-dependencies 检查)
文档里的平台 官方支持 64 位 Linux Linux 软件包和 Docker,文档没写 macOS 安装方式

在这个镜像上,两者解出的根文件系统一样。Unblob 的汇总表还列出了递归找到的类型(ELF32、SQUASHFS_V4_LE、LZMA、TAR、GZIP、CPIO),并给出 66.37% 的块识别率,能直观看出这个文件有多少已经被“解释清楚”。实用的分工是:想快速看一眼、拿到偏移,用 Binwalk;想把所有东西都切出来,连没人认识的部分也留着,用 Unblob。截至 2026-10-14,按两者的软件包元数据,都是免费、MIT 许可。在 macOS 上,PyPI 版需要先 brew install libmagic,即便这样,--show-external-dependencies 也只找到 lz4 和 zstd,所以 Unblob 的提取我只在 Linux 上做了。

从 REA 调用两者

REA(morluto 的开源项目)不自带这两个工具。6.4.0 里,rea inspect-firmware-regions 调用你装的 Binwalk(合约里写着 “Binwalk 3.1.x (verified with 3.1.0)”),rea extract-firmware 调用你装的 Unblob(“Unblob 26.6.x (verified with 26.6.4)”)。两者都只支持 Linux,需要 util-linux 的 prlimit、procps 的 ps,路径必须是绝对路径:

export REA_BINWALK_COMMAND=/usr/local/cargo/bin/binwalk
export REA_UNBLOB_COMMAND=/opt/unblob/bin/unblob
rea inspect-firmware-regions /root/fw/fw.bin --format json

在我的 Linux 容器里,它返回同样的两个区域,engine.version 为 3.1.0,还记录了可执行文件的 SHA-256。用它来确认“装上的 Binwalk 就是我想要的那个”很方便。在 macOS 上,两条命令都会以 “This integration requires Linux” 拒绝。完整流程见 REA 固件分析,确认 REA 本身装对了见 验证 REA 安装是否正确。

常见问题

有官方 Windows 版吗? 没有官方版本,wiki 写的是 “largely untested”。用 WSL2 跑 Ubuntu 最接近官方支持的平台。

v2 和 v3 能共存吗? 能。Kali 就是这么做的(binwalk 和 binwalk3)。其他系统上,用 cargo 把 v3 装到 ~/.cargo/bin,用完整路径调用。

为什么 v3 不再报 v2 以前那些 “Zlib”? 那些大多是压缩数据内部的误报。v3 的校验解析器会跳过它认得的数据体。

--dd 去哪了? 3.1.0 没有自定义切割参数。用扫描给出的偏移和大小配合 dd 来切,做法见 SquashFS 提取指南。

授权声明:只对自己拥有或有权分析的固件运行 Binwalk 和 Unblob,例如开源镜像和 CTF 文件。

下一步