1. 课程导入与学习路径

做逆向分析,第一件事是什么?

我个人的答案是:搞懂CPU在干什么。你连寄存器都认不全,怎么跟反汇编代码打交道?

ARM64,或者说AArch64,现在几乎统治了移动端、服务器端,甚至苹果的桌面端。咱们这一章就把地基打牢。别急,我不会给你念手册,咱们聊点实在的。

1.1 ARM64发展史:为什么是它?

ARM架构最早是1985年Acorn电脑搞出来的,当时叫Acorn RISC Machine。后来改名叫Advanced RISC Machine。早期是ARMv4、ARMv5,那时候还是32位。

真正的大转折是2011年。ARM发布了ARMv8架构,第一次引入了64位指令集。这就是咱们说的ARM64。苹果是第一个吃螃蟹的,2013年的A7芯片就上了ARM64。我当时还在做嵌入式,看到这个消息就知道——时代变了。

架构版本 发布时间 位宽 关键特性
ARMv7 2005 32位 Cortex-A系列,Thumb-2
ARMv8-A 2011 32/64位 AArch64执行状态,新指令集
ARMv8.1-8.5 2014-2018 64位 原子指令,RAS扩展,预测性分支
ARMv9 2021 64位 CCA机密计算,SVE2

关键认知:ARM64不是ARM32的简单升级。它是全新的执行状态,指令编码、寻址模式、异常模型全都重写了。你拿ARM32的经验直接套,会踩坑。

1.2 ARM32 vs ARM64:核心差异

很多刚转过来的朋友会问:不就是32位变64位吗?地址宽了,寄存器多了,还有啥?

嗯,远不止这些。我列几个你在逆向时一定会碰到的差异:

  • 指令长度固定:ARM32有ARM(4字节)和Thumb(2字节)两种模式,切换起来很烦。ARM64统一4字节,解码简单多了。
  • 寄存器翻倍:通用寄存器从16个(ARM32)变成31个(ARM64)。PC和SP不再是通用寄存器。
  • 条件执行砍掉了:ARM32几乎每条指令都能加条件后缀(EQ/NE/GT...)。ARM64只有少数分支指令支持条件执行。为什么?为了简化流水线。
  • 寻址模式更规整:ARM64的寻址模式比ARM32少,但更一致。写反汇编脚本时你会感谢这个设计。
  • 异常模型重构:ARM64的异常等级(EL0-EL3)比ARM32的处理器模式清晰得多。

避坑指南:我曾经在逆向一个iOS应用时,看到函数开头是 STP X29, X30, [SP,#-0x10]!,下意识以为是ARM32的PUSH。不对。ARM64没有PUSH/POP指令,栈操作全靠STP/LDP。这个思维转换很重要。

1.3 AArch64执行状态

ARMv8架构支持两种执行状态:AArch64和AArch32。咱们这门课只关注AArch64。

AArch64有几个特点:

  • 地址空间:支持64位虚拟地址,但实际实现通常只用48位或52位。高16位必须是符号扩展,否则CPU会抛异常。
  • 异常等级(Exception Levels):EL0(用户态)、EL1(内核态)、EL2(虚拟化)、EL3(安全监控)。每个等级有自己的页表、栈指针和系统寄存器。
  • 执行状态切换:AArch64和AArch32可以在异常等级之间切换。比如EL1跑64位内核,EL0跑32位应用。但同一个异常等级内不能混用。

调试技巧:看异常等级最简单的方法是检查 CurrentEL 系统寄存器。我在做内核调试时经常用它确认当前在哪个特权级。

1.4 寄存器模型

寄存器是逆向分析的第一手资料。你看到的每条指令都在操作它们。咱们一个一个来。

1.4.1 通用寄存器

AArch64有31个通用寄存器,编号X0到X30。每个都是64位宽。访问低32位时用W0到W30。

寄存器 别名/用途 调用约定(AAPCS64)
X0-X7 参数寄存器 传递参数,X0也用于返回值
X8 间接结果寄存器 返回大结构体时用
X9-X15 临时寄存器 调用者保存
X16-X17 IP0, IP1 过程内调用临时寄存器
X18 平台寄存器 OS保留,应用层别碰
X19-X28 被调用者保存 函数内必须恢复原值
X29 FP(帧指针) 指向当前栈帧底部
X30 LR(链接寄存器) 保存函数返回地址
SP 栈指针 独立寄存器,有专用指令操作
PC 程序计数器 不能直接读写,只能通过分支指令修改

实战要点:逆向时看到 MOV X0, XZR,就是把0写入X0。XZR是零寄存器,读出来永远是0,写进去被丢弃。ARM32没有这个,很多人第一次看到会懵。

1.4.2 SIMD与浮点寄存器

ARM64有32个128位的SIMD寄存器,叫V0到V31。它们可以当作不同宽度的向量用:

  • B:8位(字节)
  • H:16位(半字)
  • S:32位(单精度浮点)
  • D:64位(双精度浮点)
  • Q:128位(四字)

举个例子:ADD V0.4S, V1.4S, V2.4S 意思是把V1和V2的四个32位整数分别相加,结果存到V0。

个人经验:做多媒体逆向时,SIMD寄存器是重点。我曾经分析过一个视频编解码库,核心算法全是用NEON指令写的。看不懂V寄存器,就等于没看。

1.4.3 系统寄存器

系统寄存器是ARM64的“控制面板”。它们控制MMU、中断、调试、性能监控等核心功能。访问系统寄存器只能用专用的 MRS(读)和 MSR(写)指令。

常用的系统寄存器:

寄存器 用途 访问等级
CurrentEL 当前异常等级 EL1及以上
DAIF 中断屏蔽位 EL1及以上
TPIDR_EL0 线程指针 EL0可读
VBAR_EL1 异常向量表基址 EL1
PAR_EL1 物理地址寄存器 EL1
PMCCNTR_EL0 性能计数器 EL0

注意:系统寄存器的命名有规律:寄存器名_ELx 表示最低访问等级。比如 TPIDR_EL0 在EL0就能读,但 VBAR_EL1 必须在EL1才能写。逆向内核代码时,看到 MSR VBAR_EL1, X0,就知道这是在设置异常向量表。

1.5 知识结构总览

下面这张图把本章的核心知识点串起来了。你可以把它当作后续调试时的快速参考。

ARM64架构基础核心知识结构 ARM64架构基础核心知识结构 ARM64 (AArch64) 发展史 ARMv7 → ARMv8 2011年引入64位 苹果A7率先商用 与ARM32差异 指令固定4字节 31个通用寄存器 无条件执行 异常等级模型 执行状态 EL0-EL3四级 64位虚拟地址 AArch64/32切换 独立栈指针 寄存器模型 31个通用寄存器 X0-X30 + SP/PC 32个SIMD寄存器 V0-V31 (128位) 系统寄存器(MRS/MSR) 逆向分析的基础:读懂CPU在做什么

1.6 本章小结

ARM64不是ARM32的简单升级。它是全新的架构,有自己的一套规则。做逆向分析,你得先熟悉这些规则:

  • 知道寄存器怎么用,才能看懂反汇编代码
  • 知道异常等级,才能理解内核和应用的分界
  • 知道系统寄存器,才能调试底层问题

我见过太多人一上来就追着反汇编代码看,结果连X29是帧指针都不知道。嗯,先把基础打牢,后面咱们再深入异常处理、性能调优和调试技巧。