深入理解 ARM 汇编:从指令编码到函数还原

从 ARM 指令编码原理出发,结合真实反编译案例,演示如何快速理解未知 ARM 二进制。

为什么 ARM 值得深入理解

ARM 架构在移动设备、嵌入式系统、Apple Silicon、甚至服务器领域占据主导地位。理解 ARM 汇编是逆向工程 IoT 固件、移动应用、Apple M 系列芯片程序的基础。

本文从指令编码讲起,配合 binforge 反编译实例,帮助你建立系统化的 ARM 二进制分析能力。

ARM 指令编码基础

三种主要模式

模式 说明 应用场景
ARM 32 位定长指令 早期 ARMv7 设备
Thumb 16 位压缩指令 节省空间的代码段
Thumb-2 16/32 位混合 ARMv7 主流模式
A64 64 位固定指令 ARMv8 / ARM64

关键识别技巧:ARM 模式指令末两位为 00,Thumb 模式末两位不固定。

常见指令助记

mov r0, #42      @ r0 = 42
add r1, r2, r3   @ r1 = r2 + r3
ldr r4, [r5]     @ r4 = *r5 (从内存加载)
str r6, [r7, #8] @ *(r7 + 8) = r6 (存到内存)
bl sub_400abc    @ 调用函数并保存返回地址到 lr
bx lr            @ 从函数返回

真实反编译实例

下面是一段 ARM 函数在 binforge 中的反编译输出:

输入(汇编)

0x400abc:  push {r4, r5, lr}
0x400ac0:  mov r4, r0
0x400ac4:  mov r5, r1
0x400ac8:  mov r0, #0
0x400ad0:  bl malloc
0x400ad4:  mov r1, r4
0x400ad8:  mov r2, r5
0x400adc:  mov r3, #0
0x400ae0:  bl memcpy
0x400ae4:  mov r0, r4
0x400ae8:  pop {r4, r5, pc}

输出(反编译 C)

void* copy_buffer(void* src, size_t len) {
  void* dst = malloc(len);
  memcpy(dst, src, len);
  free(src);  // ⚠️ 注意:源指针被释放
  return dst;
}

三个关键识别技巧

1. 区分代码与数据

二进制文件中代码段和数据段混排。识别错误的"代码"会导致分析失败。

  • 使用 binforge 的启发式扫描:自动识别 ARM/Thumb 切换
  • 关注对齐:ARM 代码通常 4 字节对齐,Thumb 通常 2 字节
  • 看字符串引用:被引用的字符串周围通常是数据

2. 还原调用约定

ARM ABI(EABI)规定:

  • 前 4 个参数通过 r0-r3 传递
  • 第 5+ 参数通过栈传递
  • 返回值通过 r0(64 位用 r0-r1)
  • r0-r3 是 caller-saved,r4-r11 是 callee-saved

实战技巧:看到函数序言 push {r4-r11, lr} 就知道它会保存 8 个寄存器。

3. 跟踪控制流

ARM 没有 x86 那样明显的 call/ret,但有等价模式:

模式 含义
bl func 调用函数(保存 lr)
bx lr 从函数返回
b func 无条件跳转
bne label 条件跳转(Z=0 时)

binforge 自动把这些模式转换为 C 代码中的 if/while/for,让你专注于业务逻辑。

binforge 的 ARM 增强能力

相比传统工具,binforge 在 ARM 分析上有几个独特优势:

  1. 库函数识别:自动识别 __libc_start_main、malloc 等标准库调用
  2. 结构体推断:通过连续内存访问模式,自动还原 C 结构体定义
  3. NEON SIMD 识别:AArch64 的 SIMD 指令被识别并向量化展示
  4. 交叉引用图:可视化函数间的调用关系

实战练习建议

  1. 用 arm-none-eabi-gcc 编译一个简单的 C 程序
  2. 用 objdump -d 看汇编
  3. 把二进制喂给 binforge,看反编译输出
  4. 对比两者,理解每个 C 语句对应哪些汇编指令

小结

ARM 汇编看似复杂,但只要抓住几个核心模式:

  • 指令编码:理解 Thumb/ARM 切换
  • 调用约定:明确参数和返回值传递
  • 控制流:识别 bl/bx/b 模式

配合现代反编译工具(如 binforge),即使是大型 ARM 二进制也能在数小时内完成初步分析。

下一步

  • 想了解 ARM64 (AArch64) 的差异?关注我们后续的 ARM64 实战篇
  • 想看真实 IoT 固件分析案例?参考 客户案例
  • 想试用 binforge 反编译引擎?访问 bindeep.cn/decompile