ARM Cortex-M 架构基础:寄存器模型、指令集与异常处理

搞嵌入式固件逆向,ARM Cortex-M 是绕不开的坎。我见过太多人一上来就盯着二进制数据猛看,结果连寄存器怎么用都搞不清楚。说白了,不了解处理器架构,逆向就是瞎蒙。这一章,咱们把 Cortex-M 的底裤扒干净。

寄存器模型:逆向工程师的“眼睛”

Cortex-M 的寄存器组,是你分析固件行为的第一手资料。我个人习惯,拿到一个固件样本,先看它用了哪些寄存器,基本就能猜出代码在干什么。

通用寄存器 R0-R12:这些是干活的主力。R0-R3 通常传参数,R4-R11 是局部变量。我在逆向一个 IoT 设备时,发现它大量使用 R4-R7 保存敏感数据,这明显是开发者想避免栈溢出被利用——嗯,有点意思。

堆栈指针 SP (R13):分 MSP 和 PSP。MSP 是主栈,处理异常时用;PSP 是进程栈,跑普通任务时用。调试时看到 SP 突然跳到奇怪地址,十有八九是栈溢出了。

链接寄存器 LR (R14):保存函数返回地址。逆向时,LR 的值能告诉你调用链。我曾经靠 LR 里的地址,追出一个隐藏的后门函数——那家伙藏得真深。

程序计数器 PC (R15):当前执行地址。这个不用多说,断点、单步全靠它。

特殊寄存器:xPSR(程序状态寄存器)、PRIMASK(中断屏蔽)、FAULTMASK(故障屏蔽)、BASEPRI(优先级屏蔽)。这些在安全分析时特别关键——攻击者经常通过篡改它们来绕过保护。

寄存器速查表(逆向必备)

寄存器别名逆向用途
R0-R3参数寄存器看函数调用参数
R4-R11局部变量分析函数内部状态
R13SP判断栈使用情况
R14LR追踪调用链
R15PC定位执行流
xPSR状态寄存器看条件标志、中断状态

指令集概览:Thumb/Thumb-2 的“方言”

Cortex-M 只支持 Thumb 和 Thumb-2 指令集。你想想看,一个 32 位处理器,指令却是 16 位和 32 位混着来——这给逆向增加了不少乐趣。

Thumb 指令(16 位):短小精悍,代码密度高。常见的有 MOV、ADD、SUB、LDR、STR、B、BL 等。逆向时看到 16 位指令,基本就是 Thumb 模式。

Thumb-2 指令(32 位):Thumb 的扩展,能执行更复杂的操作。比如带立即数的 LDR、带偏移的 STR、条件分支等。Thumb-2 让 Cortex-M 既能保持代码密度,又能有接近 ARM 指令的性能。

常见指令模式:

  • 数据处理:MOV、ADD、SUB、AND、ORR、EOR、LSL、LSR——这些是算术逻辑运算,逆向时看它们能猜出算法。
  • 内存访问:LDR(加载)、STR(存储)、LDM(批量加载)、STM(批量存储)——这些是数据搬运,分析数据流的关键。
  • 分支跳转:B(无条件跳转)、BL(带链接跳转)、BX(跳转并切换模式)、BLX(带链接跳转并切换模式)——这些是控制流,逆向时重点关注。
  • 其他:SVC(系统调用)、BKPT(断点)、WFI(等待中断)——这些是特殊操作,安全分析时经常遇到。

避坑指南:我曾经在逆向一个固件时,发现反汇编出来的指令全是 32 位的,但处理器却跑在 Thumb 模式。后来才发现,那个固件用了 Thumb-2 的 32 位指令,但反汇编器默认只识别 16 位。所以,一定要确认反汇编器支持 Thumb-2。

异常处理与中断向量表:固件的“命门”

异常处理是 Cortex-M 的强项,也是逆向分析的重点。攻击者经常通过篡改中断向量表来劫持控制流——你想想看,如果能把一个中断向量指向恶意代码,那系统就彻底沦陷了。

异常类型:

  • 系统异常:复位、NMI、硬故障、内存管理、总线故障、用法故障、SVCall、PendSV、SysTick——这些是内核自带的,优先级固定。
  • 外部中断:IRQ0-IRQn——这些是外设触发的,优先级可配置。

中断向量表:这是异常处理的核心。它是一张表,每个条目对应一个异常处理函数的地址。向量表通常放在固件的起始地址(0x00000000 或 0x08000000)。

向量表结构:

偏移内容说明
0x00初始 SP 值复位后栈指针
0x04复位向量复位后第一条指令地址
0x08NMI 向量不可屏蔽中断处理
0x0C硬故障向量硬故障处理
0x10-0x3C其他系统异常内存管理、总线故障等
0x40+外部中断向量IRQ0-IRQn

异常处理流程:

  1. 异常发生,处理器自动压栈(xPSR、PC、LR、R12、R3-R0)。
  2. 从向量表取出对应处理函数地址。
  3. 跳转到处理函数执行。
  4. 处理函数执行完,执行异常返回指令(BX LR 或 POP {PC})。
  5. 处理器自动出栈,恢复现场。

安全警示:逆向时,一定要检查向量表是否被篡改。我曾经遇到一个固件,它的复位向量被改成了一个 shellcode 地址——攻击者通过一个缓冲区溢出漏洞,把恶意代码写到了向量表区域。所以,向量表保护是安全防护的第一道防线。

知识体系图:Cortex-M 逆向核心

下面这张图,把 Cortex-M 逆向的核心知识点串起来了。你对照着看,心里就有谱了。

ARM Cortex-M 逆向核心知识体系 寄存器模型 指令集 (Thumb/Thumb-2) 异常处理与向量表 R0-R15 通用寄存器 SP/MSP/PSP 堆栈指针 LR/PC 链接与程序计数器 xPSR/PRIMASK 特殊寄存器 16 位 Thumb 指令 32 位 Thumb-2 指令 数据处理/内存访问/分支 SVC/BKPT/WFI 特殊指令 系统异常 (复位/NMI/故障) 外部中断 (IRQ0-IRQn) 向量表结构与保护 异常压栈/出栈流程 核心:寄存器是状态,指令是行为,异常是控制流——三者结合才能看懂固件

嗯,这一章的内容就到这儿。寄存器、指令集、异常处理——这三样东西,是逆向 Cortex-M 固件的三把钥匙。你把这章吃透了,后面分析签名绕过、调试漏洞的时候,心里就有底了。