第二章:固件获取与提取——从源头到文件系统

做固件安全分析,第一步就是拿到固件。这事儿听起来简单,但实际操作中坑不少。我刚开始做这行时,光找固件就花了两天,结果发现下载的是个空壳子……嗯,今天咱们就把固件获取和提取这件事彻底讲清楚。

2.1 固件获取的三大渠道

固件从哪来?说白了就三个地方:官网、设备本身、OTA升级包。我个人的习惯是优先从官网下手,因为最省事。但有些厂商的官网做得跟迷宫似的,你得有点耐心。

2.1.1 官网下载

大部分厂商会在官网提供固件下载,通常在「支持」或「下载中心」栏目。但要注意:

  • 有些固件需要注册账号才能下载
  • 部分厂商只提供最新版本,历史版本得自己找
  • 文件名可能被混淆,比如改成 .bin 但实际是 .zip
我的小技巧: 用浏览器的开发者工具(F12)监控网络请求,有时候能直接抓到固件的真实下载链接。我曾经靠这招从一个隐藏的API接口里扒出了三年前的固件版本。

2.1.2 从设备中提取

如果你手头有设备,那直接从设备里读固件是最靠谱的。常见方法有:

  • UART/串口: 设备启动时通过串口输出启动信息,有时能进入uboot或bootloader,直接dump固件
  • JTAG/SWD: 通过调试接口直接读取Flash内容,适合有硬件基础的工程师
  • SPI Flash编程器: 把Flash芯片焊下来,用编程器读取。这招比较暴力,但最彻底
注意: 从设备提取固件可能涉及法律风险,尤其是商业产品。建议只用于自己购买的设备或开源项目。

2.1.3 OTA包捕获

OTA(Over-The-Air)升级包是另一个重要来源。我遇到过不少设备,官网不提供固件,但OTA升级时能抓到包。方法如下:

  1. 在手机或设备上设置代理(比如Burp Suite、Charles)
  2. 触发OTA升级,捕获HTTP/HTTPS请求
  3. 从请求中提取固件下载链接
  4. 如果用了HTTPS,可能需要安装CA证书来解密流量

避坑指南: 我曾经抓一个智能摄像头的OTA包,发现它用了自签名证书,而且证书校验不严格。我直接替换了CA证书,成功抓到了固件。但后来发现厂商已经修复了这个漏洞……嗯,动作要快。

2.2 固件提取的核心工具

拿到固件文件后,下一步就是把它拆开。固件通常是一个大二进制文件,里面包含了文件系统、内核、bootloader等。我们需要用工具把它「解包」。

2.2.1 Binwalk——最常用的固件分析工具

Binwalk 是我用得最多的工具,没有之一。它能自动识别固件中的文件系统、压缩数据、内核镜像等。

# 基本用法:扫描固件中的文件
binwalk firmware.bin

# 提取所有识别到的文件
binwalk -e firmware.bin

# 指定提取目录
binwalk -e -M --dd=".*" firmware.bin

Binwalk 的工作原理是扫描文件中的魔数(Magic Number)。比如 SquashFS 文件系统以 hsqs 开头,JFFS2 以 0x1985 开头。它会把这些片段切出来。

经验之谈: Binwalk 不是万能的。有些固件用了自定义的魔数,或者把文件系统加密了。这时候 Binwalk 就识别不出来。我遇到过一款路由器,它的文件系统被 XOR 加密了,得先解密才能用 Binwalk。

2.2.2 dd——手动切割的瑞士军刀

当 Binwalk 识别不出来时,就得靠 dd 手动切割了。dd 是 Linux 下的一个底层工具,可以按字节精确复制数据。

# 从偏移量 0x100000 开始,读取 4MB 数据
dd if=firmware.bin of=output.bin bs=1 skip=$((0x100000)) count=$((4*1024*1024))

# 常用参数说明
# if:输入文件
# of:输出文件
# bs:块大小(通常设为1,方便按字节操作)
# skip:跳过多少字节
# count:读取多少字节

怎么知道偏移量?通常靠经验或分析固件的启动日志。比如 U-Boot 启动时会打印各分区的起始地址和大小,记下来就能用 dd 切了。

注意: dd 操作的是原始二进制数据,一旦搞错偏移量,切出来的文件就是乱码。建议先用 hexdump 或 010 Editor 查看固件结构,确认偏移量后再动手。

2.2.3 Unblob——新一代固件提取工具

Unblob 是近几年出现的工具,专门解决 Binwalk 处理不了的复杂固件。它支持更多的文件系统类型,而且能处理嵌套压缩的情况。

# 安装
pip install unblob

# 使用
unblob firmware.bin -o output_dir

Unblob 的优势在于:

  • 支持 LZMA、LZ4、Zstd 等现代压缩算法
  • 能自动处理多层嵌套(比如 SquashFS 里面又包了一个 cpio)
  • 对损坏的固件有更好的容错性

我的对比: 有一次分析一个智能门锁的固件,Binwalk 只识别出了内核,文件系统死活找不到。换成 Unblob 后,它直接解出了 SquashFS,还附带了一个隐藏的配置文件。从那以后,我工具箱里就多了 Unblob。

2.3 固件提取的完整流程

下面这张图展示了固件获取与提取的完整流程,我画了个 SVG 方便你理解:

固件获取与提取流程 官网下载 设备提取 OTA包捕获 固件二进制文件 (.bin / .img) Binwalk dd 手动切割 Unblob 提取结果 文件系统 (SquashFS / JFFS2 / ext4) | 内核 | Bootloader | 配置文件

2.4 实战:提取一个典型的路由器固件

咱们拿一个典型的路由器固件练练手。假设你从官网下载了 router_fw.bin,大小约 16MB。

# 第一步:用 Binwalk 扫描
binwalk router_fw.bin

# 输出示例:
# DECIMAL       HEXADECIMAL     DESCRIPTION
# 0             0x0             uImage header, header size: 64 bytes
# 64            0x40            LZMA compressed data, properties: 0x5D
# 1310720       0x140000        SquashFS filesystem, little endian, version 4.0

# 第二步:提取文件系统
binwalk -e router_fw.bin

# 第三步:查看提取结果
ls _router_fw.bin.extracted/
# 应该能看到 squashfs-root 目录,里面就是文件系统

如果 Binwalk 没识别出来,试试 Unblob:

unblob router_fw.bin -o output_dir
ls output_dir/
# 可能看到多个子目录,每个对应一个提取出的组件
避坑指南: 我曾经遇到一个固件,Binwalk 和 Unblob 都识别不出文件系统。后来我用 hexdump 查看,发现文件开头是 0xDEADBEEF——明显是厂商自定义的魔数。我查了芯片手册,发现文件系统其实是标准的 SquashFS,只是头部被改了。手动去掉前 256 字节后,Binwalk 就能正常识别了。

2.5 常见文件系统类型

提取出来的文件系统,常见的有这几种:

文件系统类型 魔数 常见场景 挂载命令
SquashFS hsqs 路由器、IoT设备 mount -t squashfs -o loop file.squashfs /mnt
JFFS2 0x1985 嵌入式Linux设备 mount -t jffs2 -o loop file.jffs2 /mnt
ext4 0xEF53 较新的设备、Android mount -t ext4 -o loop file.ext4 /mnt
cpio 070701 initramfs、内核模块 cpio -idmv < file.cpio
UBIFS UBI# NAND Flash设备 需使用 ubiattach + mount

总结一下: 固件获取与提取是固件安全分析的基础。官网下载最方便,设备提取最彻底,OTA包捕获适合「无官网」场景。工具方面,Binwalk 是首选,dd 用于手动切割,Unblob 处理复杂情况。记住,没有万能工具,多备几把「刀」总没错。

嗯,这一章的内容就到这。下一章咱们会深入文件系统内部,看看怎么分析里面的二进制文件。但那是后话了,先把今天的工具练熟再说。


公众号:蓝海资料掘金营,微信deep3321