3、固件提取工具链:binwalk安装与使用、dd命令、firmware-mod-kit
拿到一个固件文件,第一件事是什么?
不是直接扔进反汇编器,也不是对着十六进制发呆。你得先把它「拆开」,看看里面到底装了些什么。今天咱们就聊聊固件提取的三板斧:binwalk、dd 和 firmware-mod-kit。
核心思路:固件提取的本质就是「逆向打包」。厂商把内核、文件系统、引导程序、配置数据塞进一个二进制文件里,我们要做的就是把这些东西原封不动地掏出来。
3.1 binwalk:固件分析的瑞士军刀
binwalk 是我用得最多的工具,没有之一。它干的事情很简单——扫描固件文件,识别里面嵌入了哪些已知格式的数据块。
3.1.1 安装
我个人习惯用源码安装,因为能拿到最新的签名库。不过用包管理器也完全够用。
# Debian/Ubuntu
sudo apt-get install binwalk
# 或者从 GitHub 拉最新版
git clone https://github.com/ReFirmLabs/binwalk.git
cd binwalk
sudo python3 setup.py install
小提示:如果你打算深度使用,建议装一下 sasquatch 和 jefferson 这两个扩展包。它们能让 binwalk 识别更多类型的 SquashFS 文件系统。我踩过这个坑——没装之前,有个路由器固件死活解不开,装上后一次搞定。
3.1.2 基本用法
先来个最简单的扫描:
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
看到没?它直接告诉你:偏移 0 处是 uImage 头,0x40 开始是 LZMA 压缩数据,0x280000 处有个 SquashFS 文件系统。
要提取的话,加个 -e 参数:
binwalk -e firmware.bin
它会自动把识别出来的每个数据块拆出来,放到 _firmware.bin.extracted 目录里。
3.1.3 我常用的几个参数
| 参数 | 作用 | 说人话版 |
|---|---|---|
-e |
自动提取 | 扫描到啥就拆啥 |
-M |
递归提取 | 拆出来的文件再拆一遍 |
-D |
按类型提取 | 只提取某种格式的文件 |
-T |
显示时间戳 | 看看固件啥时候编译的 |
--dd |
自定义提取规则 | 遇到特定魔数就切一刀 |
注意:binwalk 不是万能的。它依赖签名库,遇到自定义格式或者加密固件就抓瞎了。我曾经遇到过一个工控设备的固件,binwalk 扫出来全是「Data」——说白了就是啥也没认出来。这时候就得靠 dd 手工切了。
3.2 dd:二进制世界的切刀
dd 命令,老牌 Unix 工具,功能就是「从哪读到哪,写到哪里去」。在固件分析里,它用来按偏移量切分二进制文件。
3.2.1 基本语法
dd if=输入文件 of=输出文件 bs=块大小 skip=跳过块数 count=读取块数
举个例子。假设 binwalk 告诉你文件系统在偏移 0x280000 处,大小约 4MB:
dd if=firmware.bin of=rootfs.squashfs bs=1 skip=$((0x280000)) count=$((4*1024*1024))
这样就把从 0x280000 开始的 4MB 数据切出来了。
3.2.2 实战技巧
我一般这么用:先用 binwalk 扫出大概位置,再用 dd 精确切割。为什么?因为 binwalk 的自动提取有时候会多拆或少拆,手工切更可控。
比如,你想看看固件开头 1KB 是什么:
dd if=firmware.bin of=header.bin bs=1 count=1024
或者,你想跳过开头 512 字节,把剩下的全倒出来:
dd if=firmware.bin of=body.bin bs=512 skip=1
经验之谈:bs 设成 1 虽然最精确,但速度慢。如果固件很大(比如几十 MB),我习惯先设 bs=1024 或 bs=4096,然后调整 skip 和 count 的值。算偏移的时候记得换算单位就行。
3.3 firmware-mod-kit:固件修改工具箱
这个工具包,说白了就是帮你「拆开固件 → 修改内容 → 重新打包」的一条龙服务。它主要针对嵌入式 Linux 固件,尤其是那些用 SquashFS 或 CramFS 文件系统的。
3.3.1 安装
git clone https://github.com/rampageX/firmware-mod-kit.git
cd firmware-mod-kit
./setup.sh
装完之后,你会得到一堆脚本。最常用的几个:
extract-firmware.sh— 拆固件build-firmware.sh— 打包固件unsquashfs_all.sh— 批量解压 SquashFS
3.3.2 拆固件
./extract-firmware.sh firmware.bin
它会自动识别固件格式,把内核、文件系统、引导程序分别拆到不同目录。拆完后你会看到类似这样的结构:
fmk/
├── rootfs/ # 解压后的文件系统
├── kernel.bin # 内核镜像
├── image_parts/ # 固件各分区的原始数据
└── config.log # 拆解日志
3.3.3 改固件
拆完之后,你就可以在 rootfs/ 目录里为所欲为了——加后门、改配置、换二进制,随你便。
改完之后,重新打包:
./build-firmware.sh fmk/ new_firmware.bin
坑来了:重新打包的固件大小必须和原来一致,或者至少不能超过 Flash 分区大小。我见过有人改了固件后没注意大小,刷进去直接变砖。嗯,那哥们后来花了一下午焊 SPI Flash 编程器。
3.4 三者的配合套路
在实际项目中,我很少只用其中一个工具。标准流程是这样的:
- binwalk 扫一遍,看看固件里有什么东西,记下关键偏移。
- dd 精确切割,把文件系统、内核等分区单独切出来。
- firmware-mod-kit 拆包,把文件系统解压成目录结构。
- 修改完后,firmware-mod-kit 重新打包。
你想想看,如果只靠 binwalk 的 -e,遇到识别不出来的格式就卡住了。但配合 dd 手工切,再加上 firmware-mod-kit 的打包能力,基本上能覆盖 90% 的固件提取场景。
一句话总结:binwalk 负责「看」,dd 负责「切」,firmware-mod-kit 负责「拆和装」。三个工具各司其职,组合起来就是一套完整的固件提取工具链。
3.5 知识体系图
下面这张图把本章的核心逻辑串起来了:
3.6 避坑指南
最后,分享几个我踩过的坑:
- binwalk 误识别:有时候它会把随机数据当成某种格式。我建议你每次提取后,用
file命令验证一下提取出来的文件类型。 - dd 的 bs 参数:设成 1 虽然精确,但读大文件时慢得让人抓狂。我一般先算好偏移,用
bs=1024配合skip和count来提速。 - firmware-mod-kit 打包失败:最常见的原因是文件系统大小变了。改完文件后,记得检查一下新文件系统的大小,别超出原始固件的分区限制。
- 权限问题:解压出来的文件系统里,设备文件(/dev 下的那些)在普通 Linux 系统上可能无法直接操作。用
sudo或者加--no-devices参数可以绕过。
嗯,工具链就聊到这儿。记住,工具是死的,思路是活的。遇到奇葩固件时,别死磕一个工具,三个轮着上,总有一款能搞定。