2. 固件解包与重打包

任务目标

使用 binwalk 解包一个 IoT 固件镜像,定位并修改其中的一个文件(如 Web 服务配置或启动脚本),随后使用 binwalk 的 -e 配合手动重打包或 firmware-mod-kit 完成固件重组,最后通过校验文件哈希与文件系统挂载测试验证固件完整性。

环境与依赖

  • 操作系统:Ubuntu 22.04+(或 Kali Linux)
  • 工具:binwalk、sasquatch(SquashFS 解包)、mksquashfs、cpio、file、sha256sum
  • 安装命令:sudo apt install binwalk mksquashfs cpio;SquashFS 工具链若缺失,需从 sasquatch 源码编译

固件准备

本案例使用一个合成的演示固件 demo_router.bin(约 2MB),其内部包含一个 SquashFS 文件系统和一个内核镜像。若你手头有真实固件,可直接替换路径;以下步骤对大多数基于 SquashFS 的固件同样适用。

关键完整代码

以下脚本完成解包、修改、重打包与验证的完整闭环:

#!/bin/bash
# firmware_repack_demo.sh
set -euo pipefail

FW="demo_router.bin"
EXTRACT_DIR="fw_extracted"
ROOTFS_DIR="rootfs"
MODIFIED_FILE="etc/config/product_info"
NEW_VALUE="product_name=DemoRouter-Pro"

# 1. 解包固件
rm -rf "$EXTRACT_DIR" "$ROOTFS_DIR"
binwalk -e "$FW" -C "$EXTRACT_DIR" > /dev/null

# 定位 SquashFS 根目录(自动探测)
ROOTFS_SRC=$(find "$EXTRACT_DIR" -type d -name "squashfs-root" | head -1)
if [ -z "$ROOTFS_SRC" ]; then
  echo "错误:未找到 SquashFS 根目录"
  exit 1
fi
cp -r "$ROOTFS_SRC" "$ROOTFS_DIR"

# 2. 修改目标文件(追加一行配置)
echo "$NEW_VALUE" >> "$ROOTFS_DIR/$MODIFIED_FILE"
echo "已修改: $MODIFIED_FILE"

# 3. 重打包为新的 SquashFS 镜像
mksquashfs "$ROOTFS_DIR" new_rootfs.squashfs -comp xz -b 131072 > /dev/null

# 4. 重建完整固件(保留原内核与头部)
# 提取原固件中 SquashFS 的偏移量
FW_OFFSET=$(binwalk "$FW" | grep "SquashFS" | awk '{print $1}')
if [ -z "$FW_OFFSET" ]; then
  echo "错误:无法定位 SquashFS 偏移"
  exit 1
fi
FW_OFFSET_DEC=$((16#${FW_OFFSET//:/}))

# 拆分:头部(含内核) + 新文件系统
head -c "$FW_OFFSET_DEC" "$FW" > fw_header.bin
cat fw_header.bin new_rootfs.squashfs > repacked_fw.bin

# 5. 验证完整性
echo "=== 验证 ==="
echo "原固件 SHA256:"
sha256sum "$FW" | awk '{print $1}'
echo "重打包固件 SHA256:"
sha256sum repacked_fw.bin | awk '{print $1}'

# 重新解包验证修改是否生效
binwalk -e repacked_fw.bin -C verify_extract > /dev/null
VERIFY_ROOT=$(find verify_extract -type d -name "squashfs-root" | head -1)
if grep -q "$NEW_VALUE" "$VERIFY_ROOT/$MODIFIED_FILE"; then
  echo "✅ 验证通过:修改内容已存在于重打包固件中"
else
  echo "❌ 验证失败:修改内容未生效"
  exit 1
fi

# 清理临时文件
rm -rf verify_extract fw_header.bin new_rootfs.squashfs
echo "完成"

运行方式

  1. 将上述脚本保存为 firmware_repack_demo.sh,并放置与 demo_router.bin 同目录。
  2. 赋予执行权限并运行:chmod +x firmware_repack_demo.sh && ./firmware_repack_demo.sh

验证方法与判定标准

  • 解包成功标志:脚本执行后,fw_extracted/ 目录下出现 squashfs-root 文件夹,且内部包含 etc/、bin/ 等标准 Linux 目录结构。
  • 修改生效标志:脚本输出 ✅ 验证通过,表示重打包后的固件中确实包含新增的配置行。
  • 完整性判定:重打包固件可被 binwalk 正常识别并解包,且文件系统可挂载(可选执行 mount -o loop repacked_fw.bin /mnt/test 检查)。
  • 哈希差异说明:由于文件内容已改变,重打包固件的 SHA256 必然与原固件不同,这是预期行为;完整性验证的核心是文件系统结构可解析、修改内容可检索。

常见问题

  • SquashFS 版本不兼容:若 binwalk -e 解包失败,尝试 binwalk -e -M 或手动指定偏移 dd if=demo_router.bin of=root.squashfs bs=1 skip=$((16#偏移量)) 后用 unsquashfs 解包。
  • 固件包含多个文件系统:部分固件含 CramFS、JFFS2 等,需根据 binwalk 输出选择目标文件系统;本案例仅针对 SquashFS。
  • 头部校验:某些引导程序会校验固件头部的 CRC 或长度字段,此时需额外修改头部校验值,本案例演示固件未启用该校验。