← 返回目录课程:《ARM Cortex-M处理器固件逆向核心技术实战》
04

04 Thumb/Thumb-2指令集识别与函数边界推断

通过BL
章节导航 难度:入门类型:概念框架
目标结果

把Thumb落到通信协议状态机的触发条件、可观察状态和复查材料上,先判断问题从哪里收窄。

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

从二进制到函数:Thumb

准备区01⭐从二进制到函数:T明确检查要点02⭐Thumb明确检查要点执行区01⭐栈帧特征:函数边界先定义适用边界02通信协议状态机对齐约束与联调口径验收区01对象边界先定义适用范围02触发条件确认起点与约束

指标对照卡:通信协议状态机

  • 关键对象:串口或总线协议联调现场里的UART/CAN/SPI
  • 问题现象:串口或总线协议联调现场里UART/CAN/SPI一开始改动很快,输入需求增加后日志记录显示状态外泄、循环依赖和接口膨胀。
  • 验证动作:先标出谁持有状态、谁发起调用、谁记录日志和失败返回,再按输入条件、阈值标准和处理动作决定接口是否需要拆分。第04节记录前后变化点时,优先确认帧头、长度、CRC、超时和重试次数、通信成功率和通信协议状态机是否指向同一个原因。
  • 工程判断:调整前后调用方向更清楚,失败返回、日志记录和输出结果可追踪,旧入口仍可回退,才说明边界收住了。

Thumb落地前要同时核对通信协议状态机的接收缓冲区与协议帧、失败路径和解析结果与应答帧。

概念块:Thumb

Thumb用帧边界、状态机、CRC校验连接到通信协议状态机的调试、验证和交付动作。

  • 帧边界
  • 状态机
  • CRC校验
  • 超时重试

通信协议状态机的验收口径

在固件逆向工程中,面对 Cortex-M 系列处理器,首要挑战并非理解每条指令的语义,而是从杂乱的二进制数据中,准确识别出指令集边界与函数起始、结束位置。Cortex-M 处理器仅支持 Thumb/Thumb-2 指令集,这意味着传统的 ARM 模式(32位)指令在固件中不会出现,但 Thumb-2 的变长指令(16位与32位混合)却给反汇编器的同步带来了巨大困难。本节的核心目标,就是掌握如何利用 BL(Branch with Link)和 BX(Branch and Exchange)指令的固定编码模式,结合栈帧(Stack Frame)的典型建立与销毁序列,在反汇编工具中自动或半自动地标记出函数边界,为后续的固件逻辑分析奠定基础

关键判断

函数边界推断的成败,直接决定了反汇编结果的可读性与分析效率。错误的边界会导致反汇编器“跑飞”,将数据误译为指令,产生大量无意义的示例片段。因此,优先识别 BL/BX 指令作为函数调用的“锚点”,是逆向工程中最可靠的第一性原理

Thumb

在 Thumb/Thumb-2 指令集中,BL 指令用于实现函数调用,其编码格式固定为 11110xxxxxxxxxxx(高5位)加上 11x1xxxxxxxxxxxx(高5位),共32位。而 BX 指令(编码 010001110xxx0xxx)则常用于函数返回或间接跳转。在固件二进制中,这些指令的机器码模式具有极高的辨识度,是定位函数调用关系的“信标”

具体操作时,我们可以在反汇编器(如 Ghidra 或 IDA Pro)中,通过脚本或手动搜索这些固定模式。例如,在二进制文件中搜索 BL 指令的机器码序列,其目标地址由指令中的立即数计算得出。一旦找到 BL 指令,其目标地址几乎可以确定是一个函数的起始地址。同时,BX lr(编码 4770)是 Thumb 模式下最标准的函数返回指令,其出现位置通常标志着函数体的结束

实操步骤

在 Ghidra 中,使用 Search -> Program Text 搜索十六进制模式 F0 00 00 F8(一个典型的 BL 指令编码),可以快速定位所有函数调用点。随后,通过交叉引用(XRefs)功能,即可自动生成函数边界

栈帧特征:函数边界的骨架与验证手段

仅依赖 BL/BX 指令推断函数边界,在遇到内联函数、中断向量表或尾调用(Tail Call)优化时,可能会产生遗漏或误判。此时,栈帧的建立与销毁序列成为第二重验证手段。Cortex-M 的 AAPCS(ARM Architecture Procedure Call Standard)规定了函数序言(Prologue)和尾声(Epilogue)的典型模式

典型的函数序言包含 PUSH {r4-r11, lr}(编码 E92D 4xxx 或 B4xx),用于保存非易失性寄存器和返回地址。而函数尾声则通常包含 POP {r4-r11, pc}(编码 E8BD 8xxx 或 BCxx),用于恢复寄存器并返回。通过识别这些连续的、具有固定模式的指令序列,可以精确地勾勒出函数体的范围,尤其是在 BL/BX 指令不明显的场景下(如函数被内联或通过函数指针调用)

检查项标准是否通过
BL 指令目标地址目标地址必须对齐到半字(2字节),且位于代码段内未检查目标地址是否在有效内存范围内,导致将数据区误判为…
BX lr 指令确认 4770 编码后紧跟的指令不是数据,而是下一个函…将 BX lr 后的数据(如字面量池)误认为函数体的一…
PUSH/POP 序列检查序言中 PUSH {lr} 或 PUSH {r4,…忽略了中断服务函数中可能存在的特殊序言(如 MRS 指…
Thumb-2 32位指令对齐确认反汇编器正确识别了 32 位 Thumb-2 指令…

迭代入口

Thumb的下一步可以从风险倒推:哪个模块最可能让Thumb-2指令集识别失效,哪份函数边界推断最能证明问题已经被缩小。扩展时先锁定指标对照卡和Thumb-2指令集识别之间的关系,再决定补数据、补参数、补实验,还是重做通信协议状态机相关的接口或流程。这样留下的是可执行的项目判断,而不是“已经讲完”的总结,后续协作能据此继续开发或验收。本节留下的复查锚点是Thumb:Thumb-2指令集识别是否还能解释Thumb-2指令集识别,再用函数边界推断核对源码结构到项目成果的变化。第04节适合把Thumb-2指令集识别写成一条判断记录,标明触发条件、观察位置和结束标准。