2. 固件解包与内核识别

任务说明

本案例以某品牌路由器固件为例,完成固件解包、文件系统提取、内核版本与CPU架构识别。目标是为后续固件漏洞分析建立可操作的基线信息,包括:内核版本号、内核编译时间、目标架构、文件系统格式与根目录结构。

环境与依赖

  • 操作系统:Ubuntu 22.04 LTS(或兼容Linux发行版)
  • 工具:binwalk、jefferson(JFFS2解包)、sasquatch(SquashFS解包)、file、strings、readelf(交叉工具链可选)
  • 安装命令:sudo apt install binwalk;pip install jefferson;sasquatch需从GitHub源码编译

固件获取与准备

本案例使用公开固件库中的示例固件(如TP-Link TL-WR841N V14固件)。下载后校验文件完整性:

sha256sum wr841nv14_eu_3_16_9_up_boot\(160909\).bin

关键完整代码:固件解包与内核识别脚本

以下脚本自动完成固件结构扫描、文件系统提取、内核版本与架构识别:

#!/bin/bash
# firmware_analyze.sh - 固件解包与内核识别
# 用法: ./firmware_analyze.sh <固件文件>

set -euo pipefail

FIRMWARE="${1:?用法: $0 <固件文件>}"
WORKDIR="firmware_extract_$(date +%s)"
mkdir -p "$WORKDIR"
cd "$WORKDIR"

echo "[*] 固件结构扫描..."
binwalk -e "../$FIRMWARE" > binwalk_scan.log 2>&1 || true

# 定位文件系统镜像
FS_IMAGE=$(find . -type f \( -name "*.squashfs" -o -name "*.jffs2" -o -name "*.cpio" \) | head -1)
if [[ -z "$FS_IMAGE" ]]; then
    # 尝试从binwalk输出中识别文件系统偏移
    FS_OFFSET=$(grep -E "Squashfs|JFFS2|gzip" binwalk_scan.log | head -1 | awk '{print $1}')
    if [[ -n "$FS_OFFSET" ]]; then
        dd if="../$FIRMWARE" of=fs_image.bin bs=1 skip=$((FS_OFFSET)) 2>/dev/null
        FS_IMAGE="fs_image.bin"
    fi
fi

if [[ -z "$FS_IMAGE" ]]; then
    echo "[!] 未找到文件系统镜像"
    exit 1
fi

echo "[*] 文件系统镜像: $FS_IMAGE"
file "$FS_IMAGE"

# 根据文件系统类型解包
case "$(file -b "$FS_IMAGE")" in
    *Squashfs*)
        echo "[*] 使用sasquatch解包SquashFS..."
        sasquatch "$FS_IMAGE" -d rootfs 2>/dev/null || unsquashfs -d rootfs "$FS_IMAGE"
        ;;
    *JFFS2*)
        echo "[*] 使用jefferson解包JFFS2..."
        jefferson "$FS_IMAGE" -d rootfs
        ;;
    *gzip*)
        echo "[*] 解压gzip镜像..."
        mkdir rootfs && tar -xzf "$FS_IMAGE" -C rootfs
        ;;
    *)
        echo "[!] 未知文件系统类型,尝试binwalk递归解包"
        binwalk -e "$FS_IMAGE" -C rootfs 2>/dev/null || true
        ;;
esac

# 内核版本与架构识别
echo ""
echo "[*] 内核信息提取..."
KERNEL_IMAGE=$(find . -name "vmlinux*" -o -name "kernel*" -o -name "zImage*" | head -1)

if [[ -n "$KERNEL_IMAGE" ]]; then
    echo "[*] 内核镜像: $KERNEL_IMAGE"
    strings "$KERNEL_IMAGE" | grep -E "Linux version" | head -1
    strings "$KERNEL_IMAGE" | grep -E "^[0-9]+\.[0-9]+\.[0-9]+" | head -5
else
    # 从rootfs中提取版本信息
    if [[ -d "rootfs" ]]; then
        echo "[*] 从rootfs /proc/version 或 /etc/ 提取信息..."
        find rootfs -name "version" -path "*/proc/*" -exec cat {} \; 2>/dev/null | head -1
        cat rootfs/etc/openwrt_release 2>/dev/null || true
        cat rootfs/etc/os-release 2>/dev/null || true
    fi
fi

# 架构识别
echo ""
echo "[*] 架构信息..."
if [[ -d "rootfs" ]]; then
    # 检查rootfs中的动态链接器
    find rootfs -name "ld-*.so" -exec file {} \; 2>/dev/null | head -1
    # 检查busybox
    find rootfs -name "busybox" -exec file {} \; 2>/dev/null | head -1
fi

echo ""
echo "[*] 分析完成。关键结果:"
echo "    文件系统类型: $(file -b "$FS_IMAGE" | cut -d, -f1)"
echo "    根目录结构: $(ls rootfs/ 2>/dev/null | tr '\n' ' ')"
echo "    输出目录: $WORKDIR"

运行方式

chmod +x firmware_analyze.sh
./firmware_analyze.sh wr841nv14_eu_3_16_9_up_boot\(160909\).bin

验证方法与判定标准

执行后检查以下输出以确认分析成功:

  • 文件系统解包成功:rootfs/目录存在且包含bin/、etc/、usr/等标准Linux目录结构;
  • 内核版本识别:输出包含形如Linux version 3.10.14的版本字符串(具体版本取决于固件);
  • 架构识别:file命令输出显示MIPS、ARM或x86等架构标识;
  • 可验证性:使用readelf -h检查rootfs中任意可执行文件(如/bin/busybox),确认其机器类型与脚本输出一致。

预期输出示例

[*] 文件系统镜像: squashfs-root/../fs_image.bin
[*] 使用sasquatch解包SquashFS...
[*] 内核信息提取...
Linux version 3.10.14 (builduser@buildhost) (gcc version 4.8.3 (OpenWrt/Linaro GCC 4.8-2014.04) ) #1 Wed Sep 9 15:42:11 CST 2016
[*] 架构信息...
rootfs/bin/busybox: ELF 32-bit MSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, stripped

以上输出中,Linux version 3.10.14为内核版本,MIPS为CPU架构,#1 Wed Sep 9 15:42:11 CST 2016为内核编译时间。这些信息即为后续漏洞分析(如搜索对应内核CVE、匹配架构相关利用技术)的输入基线。