2. 固件解包与文件系统提取

任务目标

给定一个路由器固件镜像(router_fw.bin),使用 binwalk 识别并提取其中嵌入的文件系统(SquashFS),随后验证提取结果的文件类型与目录结构完整性。

环境与依赖

  • 操作系统:Ubuntu 22.04 / Kali Linux(或任何支持 binwalk 的 Linux 发行版)
  • 工具:binwalk(v2.3.3+)、sasquatch(非标准 SquashFS 解包工具)、file、unsquashfs
  • 安装命令:
    sudo apt update && sudo apt install -y binwalk file squashfs-tools
    # 若固件使用非标准 SquashFS(如 D-Link、TP-Link 部分型号),需额外安装:
    git clone https://github.com/devttys0/sasquatch.git && cd sasquatch && sudo ./build.sh

关键完整代码(解包与验证脚本)

#!/bin/bash
# firmware_extract.sh - 固件解包与文件系统提取验证
set -euo pipefail

FW_IMAGE="router_fw.bin"
EXTRACT_DIR="fw_extracted"
SQUASH_OFFSET=""

# 1. 扫描固件中的嵌入式文件签名
echo "[*] 扫描固件签名..."
binwalk "$FW_IMAGE" | tee binwalk_scan.txt

# 2. 自动提取所有可识别文件(含 SquashFS)
echo "[*] 使用 binwalk 自动提取..."
binwalk -e -M -C "$EXTRACT_DIR" "$FW_IMAGE"

# 3. 定位 SquashFS 文件系统偏移量(从扫描结果中解析)
SQUASH_OFFSET=$(grep -i "squashfs" binwalk_scan.txt | head -1 | awk '{print $1}')
if [ -z "$SQUASH_OFFSET" ]; then
    echo "[!] 未检测到 SquashFS,尝试手动搜索..."
    SQUASH_OFFSET=$(binwalk "$FW_IMAGE" | grep -i "filesystem" | head -1 | awk '{print $1}')
fi

if [ -z "$SQUASH_OFFSET" ]; then
    echo "[!] 无法定位文件系统偏移量,退出"
    exit 1
fi
echo "[*] SquashFS 偏移量: 0x${SQUASH_OFFSET}"

# 4. 从原始固件中切割出 SquashFS 镜像
dd if="$FW_IMAGE" of="squashfs_raw.img" bs=1 skip=$((16#$SQUASH_OFFSET)) 2>/dev/null

# 5. 使用 unsquashfs 或 sasquatch 解包
echo "[*] 尝试 unsquashfs 解包..."
if unsquashfs -d "$EXTRACT_DIR/rootfs" squashfs_raw.img 2>&1 | grep -q "ERROR"; then
    echo "[*] unsquashfs 失败,尝试 sasquatch..."
    sasquatch -d "$EXTRACT_DIR/rootfs" squashfs_raw.img
fi

# 6. 验证提取结果
echo ""
echo "[*] 验证文件系统类型:"
file "$EXTRACT_DIR/rootfs/bin/busybox" 2>/dev/null || file "$EXTRACT_DIR/rootfs/bin/sh"

echo ""
echo "[*] 验证关键目录结构:"
for dir in bin etc lib usr var home root tmp; do
    if [ -d "$EXTRACT_DIR/rootfs/$dir" ]; then
        echo "  [✓] /$dir 存在"
    else
        echo "  [✗] /$dir 缺失"
    fi
done

echo ""
echo "[*] 验证关键文件:"
for f in etc/passwd etc/init.d/rcS bin/busybox; do
    if [ -e "$EXTRACT_DIR/rootfs/$f" ]; then
        echo "  [✓] /$f 存在 ($(stat -c%s "$EXTRACT_DIR/rootfs/$f") bytes)"
    else
        echo "  [✗] /$f 缺失"
    fi
done

echo ""
echo "[*] 提取完成。根文件系统位于: $EXTRACT_DIR/rootfs/"

运行方式

chmod +x firmware_extract.sh
./firmware_extract.sh

验证方法与判定标准

脚本执行后,按以下标准判定是否成功:

  • 签名识别:binwalk_scan.txt 中应包含 SquashFS filesystem 或 filesystem 条目,且偏移量非空。
  • 解包结果:fw_extracted/rootfs/ 目录存在且非空。
  • 文件类型:file 命令输出显示 ELF 可执行文件(如 bin/busybox 为 ELF 32-bit ARM 或 MIPS 可执行文件),证明提取的是真实可执行文件系统而非空目录。
  • 目录完整性:脚本输出中 /bin、/etc、/lib、/usr 等关键目录均标记 [✓]。
  • 关键文件:/etc/passwd、/etc/init.d/rcS、/bin/busybox 均存在且大小非零。

若以上条件全部满足,则固件解包与文件系统提取成功,且完整性验证通过。

常见问题

  • binwalk 未识别 SquashFS:部分厂商(如 D-Link)使用非标准 SquashFS 头,需安装 sasquatch 后重新扫描。
  • unsquashfs 报错:若报 ERROR: Superblock magic is wrong,说明偏移量不正确或文件系统被加密/压缩,改用 sasquatch 或手动检查偏移量。
  • 提取后 busybox 无法执行:这是交叉编译固件的正常现象,需使用对应架构的 qemu-arm-static 或 qemu-mips-static 进行 chroot 执行,不影响文件系统提取的完整性验证。