← 返回目录课程:《STM32 HAL库固件逆向识别与函数还原实战》
02

02 Cortex-M3/M4启动文件与向量表逆向定位

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

把Cortex-M3落到M4启动文件的触发条件、可观察状态和复查材料上,先判断问题从哪里收窄。

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

查看现场信号与复查材料

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

代码阅读线索

Cortex-M3涉及源码、函数、脚本或 API 时,应先确认代码对象、调用条件和结果信号是否对应。

本节用M4启动文件的真实调用点说明代码变化会影响哪一个操作结果。

启动文件逆向:从复位向量到调用链入口

Cortex-M3中心对象与关键关系01⭐启动文件逆向:从复明确检查要点02🎯向量表定位与复位处明确检查要点03⭐调用链还原:从复位明确检查要点04M4启动文件明确检查要点05对象边界先定义适用范围06触发条件确认起点与约束

M4启动文件的验收口径

在固件逆向工程中,拿到一份未经符号表的 STM32 HAL 库固件(STM32 HAL Library Firmware)二进制文件后,首要任务不是逐行反汇编,而是定位其执行起点。对于 Cortex-M3/M4 定位中断向量表(Interrupt Vector Table, IVT)而言,启动文件(Startup File)是硬件复位后第一条指令的来源,也是整个固件调用链(Call Chain)的根节点。本节将演示如何从裸二进制中逆向定位向量表、提取复位处理函数入口,并验证其与 HAL 初始化流程的衔接关系

实操步骤

拿到 .bin 或 .hex 文件后,第一步:用二进制编辑器检查文件起始的 4 字节——它必须是栈顶指针(MSP 初始值),地址对齐到 0x20000000 或 0x10000000 区域。第二步:检查偏移 0x04 处的 4 字节,它必须是复位向量,指向 Flash 区(0x08000000+)

向量表定位与复位处理函数提取

Cortex-M3/M4 强制要求向量表放置在地址 0x00000000(或通过 VTOR 寄存器重映射)。在 STM32 固件中,Flash 起始地址通常为 0x08000000,但芯片上电后硬件会自动将地址 0x00000000 映射到 Flash 起始区。因此,逆向定位中断向量表的关键检查点在于:验证二进制文件前 16 字节是否符合 Cortex-M 向量表规范

判定条件如下:

当这些条件全部满足时,即可确认向量表起始位置。随后,提取复位向量值,减去 1(清除 Thumb 标志位)得到真正的函数入口地址。该入口即为固件启动文件中的 Reset_Handler,它负责调用 SystemInit(时钟配置)和 main 函数

关键判断

如果复位向量指向 0x08000000 以内的地址但最低位为 0,说明该二进制不是 Cortex-M 目标文件,或者已被加密/混淆。此时应检查文件是否包含头部偏移(如 ISP 协议头)

调用链还原:从复位处理到 HAL 初始化

定位到 Reset_Handler 后,下一步是还原其内部的调用链(Call Chain)。在 STM32 HAL 库固件中,典型的启动调用序列为:

  1. Reset_Handler → 复制 .data 段、清零 .bss 段
  2. 调用 SystemInit(位于 system_stm32xxxx.c)配置时钟树、Flash 等待周期
  3. 调用 main 函数,其中首先执行 HAL_Init(HAL 库初始化),配置 SysTick、NVIC 优先级分组等

逆向还原时,可通过反汇编工具(如 Ghidra、IDA Pro)定位 Reset_Handler 函数体,查找对 SystemInit 和 main 的 BL/BLX 调用指令。以下是一个典型的反汇编片段(ARM Thumb 指令集):

Reset_Handler:
    ldr   r0, =_sidata       ; 加载 .data 加载区起始地址
    ldr   r1, =_sdata        ; 加载 .data 运行区起始地址
    ldr   r2, =_edata        ; 加载 .data 结束地址
    bl    copy_data           ; 调用数据复制函数
    ldr   r0, =_sbss
    ldr   r1, =_ebss
    bl    zero_bss            ; 清零 .bss 段
    bl    SystemInit          ; 时钟初始化
    bl    main                ; 进入主函数
    b     .                   ; 死循环

这段配置属于“问题代码/原始配置”,核对键名、默认值、取值范围和修改后影响的行为。

该代码块验证了启动文件的标准结构。通过追踪 bl SystemInit 的地址,可进一步分析时钟配置参数(如 HSE/LSE 使能、PLL 倍频系数)。而 bl main 后的第一条指令通常为 bl HAL_Init,这是 HAL 库固件逆向识别(HAL Library Firmware Reverse Identification)的核心标志

项目下一步

继续推进Cortex-M3时,先把Cortex-M3对应到工程结构中的入口、依赖和输出,再确认结果材料能不能复现当前结果。如果Cortex-M3/M4或启动文件与向量表逆向定位变化,下一步不是马上改代码,而是先补一条最小验证,观察可观察信号是否还能说明目标达成。交接材料应写清可保留部分、可替换部分和优先复查位置,让项目能从本节自然进入下一轮迭代。保留一条最小证据线:Cortex-M3说明对象,项目成果说明约束,Cortex-M3/M4说明状态,最后用启动文件与向量表逆向定位判断能否继续推进。第02节留下的风险提示是源码结构不要脱离项目成果单独判断,否则容易把现象误当成原因。