3. 固件打包与重打包

任务说明

本案例以典型的嵌入式Linux固件(CramFS根文件系统镜像)为对象,完成一次完整的“解包→修改→重打包→完整性验证”闭环。你将得到一个固件文件,修改其中保存的版本标识文件后重新打包,并通过校验和验证修改已被正确写入且打包过程未损坏其他内容。

环境与依赖

  • Linux系统(或WSL),需具备cramfsck、mkfs.cramfs、file、strings、sha256sum工具
  • 安装命令(Debian/Ubuntu):apt-get install cramfsprogs
  • 需要root权限执行挂载/解包操作

固件准备

首先创建一个最小CramFS固件作为操作对象(实际场景中此处替换为从设备提取的固件文件):

# 创建固件目录结构
mkdir -p fw_root/etc fw_root/usr/bin
echo "version=1.0.0" > fw_root/etc/version.txt
echo "#!/bin/sh" > fw_root/usr/bin/hello.sh
echo 'echo "Hello from firmware"' >> fw_root/usr/bin/hello.sh
chmod +x fw_root/usr/bin/hello.sh

# 生成固件镜像
mkfs.cramfs fw_root firmware.img
file firmware.img   # 确认输出包含 "CramFS" 字样

关键完整代码:解包与重打包

以下脚本完成固件解包、文件修改、重打包及完整性验证的完整流程:

#!/bin/bash
# firmware_repack.sh - 固件解包/修改/重打包/验证
set -euo pipefail

FIRMWARE="firmware.img"
WORKDIR="fw_extracted"
NEW_VERSION="2.0.0"

echo "=== [1/5] 解包固件 ==="
rm -rf "$WORKDIR" && mkdir "$WORKDIR"
# 使用 cramfsck 解包(-x 指定解包目录)
cramfsck -x "$WORKDIR" "$FIRMWARE"
echo "解包完成,文件列表:"
find "$WORKDIR" -type f | sort

echo "=== [2/5] 修改文件 ==="
# 修改版本文件(目标修改点)
echo "version=$NEW_VERSION" > "$WORKDIR/etc/version.txt"
echo "已更新版本为: $(cat "$WORKDIR/etc/version.txt")"

echo "=== [3/5] 重打包固件 ==="
# 生成新固件(保留原固件备份)
mv "$FIRMWARE" "${FIRMWARE}.orig"
mkfs.cramfs "$WORKDIR" "$FIRMWARE"
echo "新固件已生成: $FIRMWARE"

echo "=== [4/5] 验证重打包结果 ==="
# 验证1: 新固件中版本文件已更新
mkdir -p verify_dir
cramfsck -x verify_dir "$FIRMWARE"
echo "重打包后版本内容: $(cat verify_dir/etc/version.txt)"
test "$(cat verify_dir/etc/version.txt)" = "version=$NEW_VERSION" \
    && echo "✓ 版本修改验证通过" || { echo "✗ 版本修改失败"; exit 1; }

# 验证2: 其他文件完整性(对比原固件中未被修改的文件)
echo "=== [5/5] 完整性校验 ==="
# 提取原固件中 hello.sh 的哈希
mkdir -p orig_verify
cramfsck -x orig_verify "${FIRMWARE}.orig"
ORIG_HASH=$(sha256sum orig_verify/usr/bin/hello.sh | awk '{print $1}')
NEW_HASH=$(sha256sum verify_dir/usr/bin/hello.sh | awk '{print $1}')

if [ "$ORIG_HASH" = "$NEW_HASH" ]; then
    echo "✓ 未修改文件(hello.sh)哈希一致,完整性验证通过"
    echo "  SHA256: $NEW_HASH"
else
    echo "✗ 哈希不一致,重打包损坏了文件"
    exit 1
fi

# 清理临时验证目录
rm -rf verify_dir orig_verify
echo ""
echo "=== 固件重打包流程全部完成 ==="
echo "原始固件备份: ${FIRMWARE}.orig"
echo "新固件: $FIRMWARE"

运行方式

chmod +x firmware_repack.sh
sudo ./firmware_repack.sh

验证方法与判定标准

脚本执行成功后,通过以下标准判定案例完成:

  • 退出码为0,且输出包含两处“✓”标记
  • 新固件firmware.img中/etc/version.txt内容为version=2.0.0,证明修改已生效
  • 原固件与重打包固件中/usr/bin/hello.sh的SHA256哈希完全一致,证明重打包未破坏未修改的文件
  • 使用file firmware.img确认输出仍为CramFS格式,且cramfsck firmware.img(不加-x)不报错,证明镜像结构有效

常见问题

  • 解包时提示权限错误:CramFS可能包含设备节点,需root权限执行cramfsck -x
  • 重打包后固件变大:CramFS为压缩只读文件系统,文件修改可能导致压缩率变化,属正常现象
  • 实际固件可能使用SquashFS或JFFS2:本案例方法适用于CramFS;其他格式需替换为对应工具(如unsquashfs/mksquashfs),但解包→修改→重打包→校验的流程完全一致