← 返回目录课程:《STM32固件安全审计与漏洞分析基础教程》
04

04 固件二进制分析:Binwalk与Ghidra识别文件系统与分区

使用Binwalk和Ghidra提取固件中的文件系统与分区结构
章节导航 难度:入门类型:概念框架
目标结果

把固件二进制分析落到固件二进制分析的触发条件、可观察状态和复查材料上,先判断问题从哪里收窄。

关键线索
模块接口配置流程状态
交付材料
架构图代码片段排障表检查清单

固件解剖第一步:从二进制盲区到文件系统边界

指标对照卡:固件二进制分析

  • 关键对象:固件二进制分析真实工程现场里的固件二进制分析
  • 问题现象:固件二进制分析真实工程现场里固件二进制分析一开始改动很快,输入需求增加后日志记录显示状态外泄、循环依赖和接口膨胀。
  • 验证动作:先标出谁持有状态、谁发起调用、谁记录日志和失败返回,再按输入条件、阈值标准和处理动作决定接口是否需要拆分。第04节记录前后变化点时,优先确认策略配置、状态记录和固件二进制分析是否指向同一个原因。
  • 工程判断:调整前后调用方向更清楚,失败返回、日志记录和输出结果可追踪,旧入口仍可回退,才说明边界收住了。

固件二进制分析落地前要同时核对固件二进制分析的Ghidra识别文件系统、失败路径和使用Binwalk。

概念块:固件二进制分析

固件二进制分析用固件二进制分析、Ghidra识别文件系统、使用Binwalk连接到固件二进制分析的调试、验证和交付动作。

  • 固件二进制分析
  • Ghidra识别文件系统
  • 使用Binwalk
  • Ghidra提取固件中的文件系统

固件二进制分析的验收口径

固件二进制分析:Binwalk与Ghidra识别文件系统与分区 · 系统架构图
flowchart TB subgraph L0["应用层 / 业务入口"] N0["integration debug"] end subgraph L1["协议与服务层"] N1["Binwalk"] end subgraph L2["驱动与中间件层"] N2["Ghidra"] end subgraph L3["硬件 / 资源层"] N3["定位到校验逻辑中的整数溢出漏洞"] end N0 -->|指向| N1 N1 -->|指向| N2 N2 -->|指向| N3 classDef ns fill:#f8fafc,stroke:#475569,color:#0f172a,stroke-width:1.5px; class N0,N1,N2,N3 ns;

图表解读:对应正文“固件解剖第一步:从二进制盲区到文件系统边界”。这张图以最终 Mermaid 图中的真实节点为准,先观察“固件二进制分析:Binwalk与Ghidra识别文件系统与分区”的主链。读图顺序:应用层 / 业务入口 → integration debug → 协议与服务层 → Binwalk → 驱动与中间件层 → Ghidra

节点说明:【固件二进制分析】表示可观察对象,标出该节点在主线中的位置;检查重点:相关操作、判断条件或常见问题。

固件二进制分析:Binwalk与Ghidra识别文件系统与分区
STM32固件安全审计具象图固件二进制:Binwalk与Ghidra识别观察对象参数变化验证记录BootloadeOTASTM32…教程STM32RACI固件二进制ACIR固件二进制CIRAR 负责 / A 审批…

面对一个未经处理的 STM32 固件二进制文件(通常为 .bin 或 .hex 格式),安全审计的首要任务不是直接反汇编,而是识别其内部的组织结构。固件并非单一的可执行代码块,而是由引导加载程序(Bootloader)、主应用程序、文件系统(如 LittleFS 或 SPIFFS)、配置分区和 OTA 升级预留区等多个逻辑单元拼接而成。如果跳过这一步,后续的漏洞分析将如同在未知地图上寻找地标——所有地址偏移都可能是错误的

核心判断:固件二进制分析(Firmware Binary Analysis) 的目标是定位每个分区的起始地址、大小和类型,从而为 Ghidra 等反汇编工具提供正确的加载基址。本节将围绕 Binwalk 和 Ghidra 这两款工具,演示如何从原始二进制中提取文件系统与分区结构,并交付可验证的分析资产

关键判断

不要依赖单一工具的结果。Binwalk 的熵分析和签名扫描只能给出“可能的分区边界”,必须通过 Ghidra 的交叉引用和字符串定位进行二次验证。错误的基址会导致反汇编代码完全不可读

Binwalk 调试验证:熵图、签名与边界确认

Binwalk 是固件分析中最常用的签名扫描工具。对于 STM32 固件,它能够识别常见的文件系统魔数(Magic Number),例如 LittleFS 的起始标记或 YAFFS 的页结构。但直接运行 binwalk firmware.bin 往往不够,必须结合熵分析(Entropy Analysis)来确认分区边界

实操步骤:使用 binwalk -E firmware.bin 生成熵图。高熵区域(接近 1.0)通常表示加密或压缩数据,而低熵区域(0.5-0.8)可能是未加密的文件系统或代码段。对于 STM32 固件,常见的模式是:起始地址 0x08000000 附近为低熵的向量表,随后在某个偏移处出现熵值突变,这通常就是文件系统的起始点

# 步骤 1:执行签名扫描与熵分析
binwalk -Me firmware.bin
# -M 表示递归扫描,-e 表示自动提取已知文件系统
# 步骤 2:手动验证分区边界(以 LittleFS 为例)
binwalk -E firmware.bin | grep -A 5 "0x" | head -20
# 观察熵值变化,标记熵值从 0.6 跳变到 0.9 的地址

这段命令属于“问题代码/原始配置”,核对参数、目标设备和返回信息,并用状态记录确认动作是否真正生效。

上述命令中,-Me 组合会尝试自动提取所有已知签名匹配的文件系统。但实际项目中,签名库可能不包含私有魔数。此时需要结合 hexdump -C firmware.bin | head -n 50 手动查找文件系统的目录结构特征(如文件名哈希表)。Binwalk 的输出仅作为候选边界,必须通过 Ghidra 的加载验证来最终确认

实操步骤

在 Binwalk 提取出疑似文件系统后,使用 strings 命令检查其中是否包含固件中已知的配置文件名或日志字符串。如果提取出的文件系统内字符串与固件上下文无关,说明分区边界识别错误,需要调整偏移量重新提取

Ghidra 交付物:加载脚本、分区基址与交叉引用验证

Ghidra 在固件安全审计中的核心作用不是自动反编译,而是提供可编程的分析环境。当 Binwalk 给出候选分区地址后,我们需要在 Ghidra 中编写加载脚本(Loader Script),将每个分区以正确的基址导入,并验证代码间的交叉引用是否合理

关键机制:STM32 的向量表位于 Flash 起始地址(通常为 0x08000000),其中前 4 字节为栈顶指针,后 4 字节为复位向量。通过 Ghidra 的 integration_debug 识别文件系统 功能,我们可以将 Binwalk 提取出的文件系统作为原始数据导入,然后手动定义其结构体。例如,对于 LittleFS,需要定义目录项结构(包含文件名、大小、校验和),然后通过 Ghidra 的脚本遍历所有文件

# Ghidra Python 脚本片段:验证分区基址
from ghidra.program.model.listing import Program
from ghidra.util.task import ConsoleTaskMonitor
def get_partition_base(program):
    # 获取当前程序的加载地址
    memory = program.getMemory()
    blocks = memory.getBlocks()
    for block in blocks:
        if block.getName().startswith("FLASH"):
            return block.getStart().getOffset()
    return None
# 在 Ghidra 的 Python 交互窗口中执行
base = get_partition_base(currentProgram)
print("当前分区基址: 0x%X" % base)
# 如果基址与 Binwalk 标记的偏移量不一致,需要重新加载

这段命令属于“推荐实现/重构后接口”,核对参数、目标设备和返回信息,并用状态记录确认动作是否真正生效。

这段脚本验证了 Ghidra 中当前分区的加载基址。如果 Binwalk 标记的文件系统起始地址为 0x08040000,但 Ghidra 中该区域的基址被错误地设置为 0x08000000,那么所有对文件系统的引用都会偏移 0x40000 字节,导致字符串和函数指针全部失效。正确的做法是:在 Ghidra 的 File → Open 时,选择 Binary File 导入方式,并在 Import Options 中手动设置 Base Address 为 Binwalk 计算出的分区起始地址

交付物清单:分区结构表与交叉引用图

完成 Ghidra 加载后,必须输出以下技术资产:

真实项目场景

某 IoT 设备固件升级后频繁死机。通过 Binwalk 熵分析发现,在 0x08020000 处存在一个高熵区域(熵值 0.95),疑似加密的 OTA 分区。但 Ghidra 加载后,发现主代码中有一个函数调用地址恰好指向该区域的起始位置。进一步分析发现,该区域实际上是未加密的配置分区,只是由于数据压缩导致熵值偏高。修正分区类型后,定位到配置校验逻辑中的整数溢出漏洞

问题对照与修正

  1. 常见偏差:把固件二进制分析直接写进主流程,只验证能跑通,留下固件二进制分析边界、状态和验证口径不清。
  2. 修正做法:把固件二进制分析收敛成稳定接口,明确输入条件、状态结果和失败处理。
  3. 验证记录:选一个和固件二进制分析直接相关的失败场景,保留输入、日志、状态结果和状态记录前后变化,让修正是否有效能被复查。

异常信号与处理边界:文件系统识别中的常见陷阱

在固件安全审计的调试验证阶段,文件系统识别错误是导致分析方向偏离的主要原因。以下表格总结了三种常见风险场景及其判断标准:

STM32固件安全审计 相关检查
风险点触发条件影响预防措施
熵值误判将压缩数据(如 LZSS)误判为加密分区跳过文件系统提取,遗漏配置漏洞使用 binwalk -X 检查压缩签名
基址偏移Binwalk 标记的起始地址与向量表偏移不一致Ghidra 反汇编代码全部错位,函数无法识别用 Ghidra 的 Analyze → One Sh…
文件系统魔数冲突多个分区包含相同的魔数(如 0xFFFFFFFF)Binwalk 提取出错误的文件系统内容结合熵图,只提取熵值在 0.5-0.8 之间的区域
常见误区

初学者常直接使用 Binwalk 的 -e 参数自动提取,然后立即将提取出的文件系统导入 Ghidra 进行分析。这种做法忽略了“分区边界验证”环节。正确的流程是:先通过熵图确认分区数量,再用签名扫描定位每个分区的精确偏移,最后在 Ghidra 中逐个加载并验证交叉引用

最终,漏洞分交付物 必须包含一份完整的 固件安全审计调试验证 报告,其中详细记录每个分区的识别过程、Binwalk 与 Ghidra 的验证结果,以及所有交叉引用异常的排查记录。只有经过双向验证的分区结构,才能作为后续静态分析和动态调试的可靠基础

细节补充:

固件二进制分析的细节补充应直接说明可复查对象:先确认现场任务对应的输入、输出和结果材料,再用固件二进制分析解释哪一处条件会影响判断。

固件二进制分析的主要风险来自固件二进制分析边界、状态和验证口径不清;落地前先核对策略配置,并确认例外场景和结果记录。

迭代入口

固件二进制分析的下一步可以从风险倒推:哪个模块最可能让指标对照卡失效,哪份结果材料最能证明问题已经被缩小。扩展时先锁定固件二进制分析和可观察信号之间的关系,再决定补数据、补参数、补实验,还是重做关键对象相关的接口或流程。这样留下的是可执行的项目判断,而不是“已经讲完”的总结,后续协作能据此继续开发或验收。保留一条最小证据线:固件二进制分析说明对象,项目成果说明约束,固件二进制分析说明状态,最后用关键对象判断能否继续推进。第04节只保留一条主线:从固件二进制分析进入,观察源码结构,最后把关键对象交给下一次复查。