1. 固件镜像信息收集与识别

任务目标

给定一个路由器固件镜像文件,通过binwalk提取文件系统,识别目标架构、内核版本及关键组件(如Web服务、telnetd、dropbear等),为后续漏洞分析建立基础信息档案。

环境与依赖

  • 操作系统:Ubuntu 22.04 LTS(或任意Linux发行版)
  • 工具:binwalk、file、strings、readelf(或objdump)
  • 安装命令:sudo apt install binwalk file binutils

固件获取与准备

本案例使用公开的D-Link DIR-859路由器固件作为分析对象(固件版本1.03,可从D-Link官方支持页面下载)。下载后得到文件DIR859Ax_FW103b02.bin,存放于工作目录~/firmware_analysis/下。

关键完整代码(Shell脚本)

以下脚本完成固件信息收集、文件系统提取与关键组件识别的完整流程:

#!/bin/bash
# firmware_info_gather.sh - 固件镜像信息收集与识别
# 用法: ./firmware_info_gather.sh <固件文件路径>

set -e

FIRMWARE="$1"
OUTDIR="firmware_extracted"
BASENAME=$(basename "$FIRMWARE")

if [ -z "$FIRMWARE" ]; then
    echo "用法: $0 <固件文件路径>"
    exit 1
fi

echo "[*] 固件文件基本信息"
file "$FIRMWARE"

echo -e "\n[*] 固件头部/结构扫描"
binwalk "$FIRMWARE" | head -30

echo -e "\n[*] 提取文件系统"
rm -rf "$OUTDIR"
mkdir -p "$OUTDIR"
binwalk -e -M -C "$OUTDIR" "$FIRMWARE" > /dev/null 2>&1

# 定位squashfs根目录
ROOTFS=$(find "$OUTDIR" -type d -name "squashfs-root" | head -1)
if [ -z "$ROOTFS" ]; then
    ROOTFS=$(find "$OUTDIR" -type d -name "*root*" | head -1)
fi

if [ -z "$ROOTFS" ]; then
    echo "[!] 未找到文件系统根目录,尝试手动定位"
    ls -la "$OUTDIR"
    exit 1
fi

echo "[*] 文件系统根目录: $ROOTFS"

echo -e "\n[*] 架构识别"
# 从busybox或任意ELF文件识别架构
BUSYBOX=$(find "$ROOTFS" -name "busybox" -type f | head -1)
if [ -n "$BUSYBOX" ]; then
    file "$BUSYBOX"
    readelf -h "$BUSYBOX" 2>/dev/null | grep -E "Class|Machine|Entry"
else
    # 尝试从任意ELF文件识别
    ELF_FILE=$(find "$ROOTFS" -type f -exec file {} \; | grep "ELF" | head -1 | cut -d: -f1)
    if [ -n "$ELF_FILE" ]; then
        file "$ELF_FILE"
        readelf -h "$ELF_FILE" 2>/dev/null | grep -E "Class|Machine|Entry"
    fi
fi

echo -e "\n[*] 内核版本识别"
# 从内核字符串或版本文件中提取
KERNEL_STR=$(strings "$FIRMWARE" | grep -E "^Linux version [0-9]" | head -1)
if [ -n "$KERNEL_STR" ]; then
    echo "$KERNEL_STR"
else
    # 尝试从文件系统中的内核模块或proc/config中获取
    KVER_FILE=$(find "$ROOTFS" -path "*/proc/version" -o -name "config-*" 2>/dev/null | head -1)
    if [ -n "$KVER_FILE" ]; then
        cat "$KVER_FILE" | head -5
    else
        # 从文件系统中的字符串提取
        strings "$ROOTFS/bin/*" 2>/dev/null | grep -oE "[0-9]+\.[0-9]+\.[0-9]+" | sort -u | head -5
    fi
fi

echo -e "\n[*] 关键组件识别"
echo "--- 网络服务 ---"
ls "$ROOTFS/etc/init.d/" 2>/dev/null | head -20
find "$ROOTFS" -name "*httpd*" -o -name "*lighttpd*" -o -name "*nginx*" 2>/dev/null | head -5
find "$ROOTFS" -name "telnetd" -o -name "dropbear" -o -name "sshd" 2>/dev/null | head -5

echo -e "\n--- Web目录 ---"
ls "$ROOTFS/www" 2>/dev/null | head -20 || echo "无/www目录"
find "$ROOTFS" -type d -name "*web*" 2>/dev/null | head -5

echo -e "\n--- 关键二进制 ---"
find "$ROOTFS" -name "busybox" -o -name "nvram" -o -name "iptables" 2>/dev/null | head -10

echo -e "\n[*] 信息收集完成"
echo "文件系统位置: $ROOTFS"
echo "可执行文件总数: $(find "$ROOTFS" -type f -executable | wc -l)"

运行方式

cd ~/firmware_analysis
chmod +x firmware_info_gather.sh
./firmware_info_gather.sh DIR859Ax_FW103b02.bin

验证方法与判定标准

脚本执行后,按以下标准验证结果是否完整:

  1. 文件系统提取成功:输出中存在squashfs-root目录,且该目录下包含/bin、/etc、/usr等标准Linux目录结构;
  2. 架构识别明确:readelf输出显示Class: ELF32或ELF64,Machine: MIPS或ARM(DIR-859为MIPS架构,预期显示MIPS R3000或类似);
  3. 内核版本获取:输出包含形如Linux version 2.6.36或3.10.x的版本字符串;
  4. 关键组件可见:输出中列出至少一个Web服务器(如httpd)、远程管理服务(telnetd或dropbear)以及busybox的位置。

若以上四项均满足,则说明固件信息收集与识别成功,可进入后续漏洞分析阶段。

常见问题

  • binwalk提取失败:尝试binwalk --dd='.*'强制提取,或使用jefferson(针对JFFS2)等专用工具;
  • 架构识别为空:若文件系统中无busybox,可手动查找任意ELF文件执行readelf -h;
  • 内核版本无法从镜像直接获取:可解压内核镜像(通常为vmlinuz或kernel分区)后使用strings配合grep搜索版本字符串。