← 返回目录课程:《Cortex-M0/M3/M4/M7固件逆向工程系统教程》
02

02 Cortex-M启动流程与向量表逆向分析

解析启动文件、向量表结构,定位入口点与中断服务函数地址
章节导航 难度:入门类型:排障定位
本页抓手

把Cortex-M启动流程与向量表逆向分析落到Bootloader升级链路的触发条件、可观察状态和复查材料上,先判断问题从哪里收窄。

判断线索
模块接口配置流程状态
复用位置
代码片段排障表检查清单架构图

查看现场信号与复查材料

  1. 核对Bootloader升级链路的输入条件、变化信号和结果材料
  2. 再把命令、配置、日志和状态结果对应到同一个操作结果
  3. 最后用启动成功率验证结果是否可复现

代码阅读线索

Cortex-M启动流程与向量表逆向分析涉及源码、函数、脚本或 API 时,应先确认代码对象、调用条件和结果信号是否对应。

本节用Bootloader升级链路的真实调用点说明代码变化会影响哪一个操作结果。

启动向量表:从复位序列到入口点定位

Cortex-M启动流程与向量表01🎯启动向量表:从复位明确检查要点02⭐向量表逆向:中断服明确检查要点03⭐技术资产:向量表解明确检查要点04Bootloader明确检查要点05对象边界先定义适用范围06触发条件确认起点与约束

Cortex-M启动流程与向量表逆向分析架构示意

Boot ROM
→
Bootloader
→
App分区
→
回滚记录

Cortex-M启动流程与向量表逆向分析要确认的对象和结果

在固件逆向工程中,定位程序入口点(Entry Point)是第一步,也是最关键的一步。Cortex-M 系列内核(Cortex-M0/M3/M4/M7)的启动流程与传统的 ARM 架构不同,它不依赖 Bootloader 中的跳转指令,而是通过硬件固化的向量表(Vector Table)机制完成初始化。向量表通常位于 Flash 的起始地址(0x08000000 或 0x00000000),其前两个 32 位字分别存储栈顶指针(MSP,Main Stack Pointer)和复位向量(Reset Vector)。复位后,CPU 直接从向量表中加载 MSP 和 PC 指针,从而跳转到固件的 Reset_Handler 函数

实操步骤

使用二进制查看器(如 HxD、010 Editor)打开固件二进制文件,定位到文件偏移 0x0000 处。读取前 4 字节作为 MSP 初始值,再读取第 5-8 字节作为复位向量地址。注意:Cortex-M 使用小端序,地址值需按字节序反转

逆向分析时,我们通常通过向量表偏移(VTOR,Vector Table Offset Register)寄存器来确认向量表基址。在 Cortex-M3/M4/M7 中,VTOR 寄存器(地址 0xE000ED08)允许软件重定位向量表,但复位后默认指向 0x00000000。对于 Cortex-M0,VTOR 是只读的,向量表固定位于 0x00000000。因此,在分析固件时,如果发现 SCB->VTOR 被修改,说明固件可能运行在 Bootloader 跳转后的应用程序中,此时需要根据 VTOR 值重新计算向量表位置

关键判断

若固件文件前 4 字节为 0x20001000 这类 RAM 地址,说明 MSP 指向片内 SRAM;若为 0x10000000 则可能指向 CCM RAM。复位向量地址通常为 0x08000XXX 或 0x00000XXX,若指向奇数地址(如 0x08000101),则需忽略最低位(Thumb 模式标志),实际入口为 0x08000100

向量表逆向:中断服务函数地址与固件结构映射

向量表不仅包含复位向量,还包含所有异常和中断的服务函数地址。逆向分析时,通过解析向量表可以快速定位关键中断服务函数(ISR,Interrupt Service Routine),例如 SysTick、UART、DMA 等。向量表从偏移 0x00 开始,每个表项占 4 字节,共 16 个系统异常(包括复位、NMI、HardFault 等)和最多 240 个外部中断。对于 Cortex-M0,外部中断数量固定为 32 个;Cortex-M3/M4/M7 则支持更多

在逆向工程中,我们通常使用以下方法提取 ISR 地址:首先,根据 VTOR 确定向量表基址;然后,遍历偏移 0x04 到 0x3C(系统异常部分)和 0x40 之后(外部中断部分)。每个表项的值即为对应中断服务函数的入口地址。将这些地址与固件反汇编代码中的函数起始地址比对,可以快速建立中断与功能模块的映射关系。例如,若偏移 0x40 处的值为 0x08001234,则说明外部中断 0(通常对应 GPIO 或定时器)的服务函数位于 0x08001234

真实项目场景

某工业控制器固件升级后频繁死机。通过逆向分析向量表,发现复位向量地址指向了 Flash 中的 Bootloader 区域,而非应用程序入口。进一步检查 VTOR 值,发现 Bootloader 在跳转前未正确更新 VTOR,导致中断向量表指向了错误的 Flash 分区。修复方法:在跳转前强制写入 SCB->VTOR = APP_BASE,并确保向量表前 8 字节(MSP 和复位向量)有效

常见误区

误将向量表中的地址直接作为函数起始地址。Cortex-M 的 ISR 地址最低位必须为 1(Thumb 模式),但实际函数代码从地址 & 0xFFFFFFFE 开始。例如,向量表中存储 0x08000101,实际函数入口为 0x08000100。忽略此位会导致反汇编工具无法正确识别函数边界

技术资产:向量表解析与入口点验证记录

以下是一份从实际固件中提取的向量表解析记录,展示了如何通过 VTOR 和向量表内容定位入口点及中断服务函数。该记录可作为逆向分析时的参考样例

M7固件逆向工程系统教程 相关检查
时间/步骤输入动作输出
0x0000MSP 初始值0x20002000栈顶位于 SRAM 0x20002000
0x0004复位向量0x08000101入口点 Reset_Handler 位于 0x0800…
0x0008NMI 异常0x08000201NMI_Handler 位于 0x08000200
0x000CHardFault 异常0x08000301HardFault_Handler 位于 0x0800…
0x0040外部中断 00x08001001ISR 位于 0x08001000,推测为 UART…

验证动作:使用 arm-none-eabi-objdump -d firmware.elf 反汇编固件,检查上述地址是否对应函数起始。若为裸机固件(无 ELF 信息),则使用 command_check 工具(如 check_vector.py)自动扫描向量表并输出入口点。该脚本会读取二进制文件,解析前 256 字节,生成类似上表的记录,并标记异常地址(如指向 RAM 或无效区域)

# 使用 check_vector.py 验证向量表
python check_vector.py firmware.bin --base 0x08000000 --vtor 0x08000000
# 输出示例:
# [INFO] MSP: 0x20002000 (valid SRAM range)
# [INFO] Reset Vector: 0x08000101 -> Entry: 0x08000100
# [WARN] HardFault Vector: 0x08000301 (check if handler exists)
# [ERROR] External IRQ0: 0x00000000 (invalid, possible padding)

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

复用判断

交付前复查Cortex-M启动流程与向量表逆向分析,重点不是重复步骤,而是确认Cortex-M启动流程与向量表逆向分析、可观察信号和Cortex-M启动流程能不能互相解释。若启动流程与向量表逆向分析、解析启动文件或外部条件变化,原来的结果就要重新验收,不能把旧记录当作新场景的证明。下一步处理可以先锁定向量表结构,再选择补实验、补日志、补参数对照或补一条清晰的失败边界。本节留下的复查锚点是Cortex-M启动流程与向量表逆向分析:启动流程与向量表逆向分析是否还能解释现场判断,再用Cortex-M启动流程核对命令核对到配置验收的变化。第02节的交接重点是命令核对,它决定启动流程与向量表逆向分析是短暂波动还是可复现证据。