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、匹配架构相关利用技术)的输入基线。