移动安全之Android逆向系列:ARM汇编&IDA动态分析源码
字数 1740 2025-08-09 13:33:32

ARM汇编与IDA动态分析教程

一、ARM指令集基础

1. ARM指令格式

ARM指令基本格式:

<opcode>{<cond>}{S} <Rd>,<Rn>{,<opcode2>}
  • opcode:指令助记符(如LDR, STR等)
  • cond:执行条件(如EQ, NE等)
  • S:是否影响CPSR寄存器的值
  • Rd:目标寄存器
  • Rn:第一个操作数的寄存器
  • opcode2:第二个操作数

2. 条件码

条件码对应于ARM指令格式中的执行条件cond,常见条件码:

条件码 含义 标志位条件
EQ 等于 Z=1
NE 不等于 Z=0
CS/HS 无符号大于等于 C=1
CC/LO 无符号小于 C=0
MI 负数 N=1
PL 正数或零 N=0
VS 溢出 V=1
VC 无溢出 V=0

二、ARM寻址方式

1. 寄存器寻址

操作数的值在寄存器中:

MOV R2, R1  ; 将R1的值赋给R2

2. 立即寻址

操作数是指令中的立即数:

MOV R0, #0xFF00  ; 将0xFF00赋给R0

3. 寄存器偏移寻址

对寄存器值进行移位操作:

MOV R0, R1 LSL #3  ; 将R1的值左移3位后赋给R0

4. 寄存器间接寻址

使用寄存器中的值作为内存地址:

LDR R1, [R2]  ; 读取R2指向的内存内容到R1

三、常见ARM指令详解

1. 跳转指令

(1) B指令

无条件跳转:

B 0x11223344  ; 跳转到0x11223344
B R3          ; 跳转到R3中的地址

(2) BL指令

带链接的跳转(保存返回地址到LR):

BL R3         ; 跳转到R3,下条指令地址存入LR

(3) BX指令

带状态切换的跳转(根据目标地址最低位切换ARM/Thumb模式):

BX R3         ; 跳转到R3中的地址

(4) BLX指令

带链接和状态切换的跳转:

BLX R3        ; 跳转到R3,保存返回地址,切换状态

2. 存储器访问指令

(1) LDR和STR

  • LDR:从内存加载到寄存器
LDR R8, [R9, #4]  ; 读取R9+4地址的内容到R8
  • STR:从寄存器存储到内存
STR R8, [R9, #4]  ; 将R8的值存储到R9+4地址

(2) LDM和STM

批量加载/存储:

LDM R0!, {R1-R3}  ; 从R0指向的内存加载到R1-R3
STM R0!, {R1-R3}  ; 将R1-R3的值存储到R0指向的内存

(3) SWP

交换内存和寄存器内容:

SWP R1, R2, [R0]  ; 读取R0到R1,写入R2到R0

3. 数据传送指令

MOV指令

MOV R0, R1    ; R1→R0
MOV R0, #9    ; 9→R0

4. 逻辑运算指令

(1) 算术运算

ADD R1, R2, R3  ; R2+R3→R1
SUB R1, R2, R3  ; R2-R3→R1

(2) 位运算

AND R1, R2, R3  ; R2&R3→R1
ORR R1, R2, R3  ; R2|R3→R1

5. 比较指令

(1) CMP

比较并设置标志位:

CMP R7, #6  ; R7-6,设置标志位

(2) TST

位测试:

TST R3, #4  ; R3&4,设置标志位

6. 移位指令

(1) 逻辑移位

LSL R0, R1, #3  ; R1左移3位→R0
LSR R0, R1, #3  ; R1右移3位→R0

(2) 算术移位

ASR R0, R1, #3  ; R1算术右移3位(保持符号位)→R0

四、IDA动态分析实战

1. 调试准备

  • 启动IDA调试器
  • 附加到目标进程
  • 定位到JNI_OnLoad函数

2. 逐行分析示例

(1) LDR指令

LDR R3, [R0]  ; 读取R0指向的内存到R3
  • 查看R0的值(如0xF4DB3D20)
  • 查看该地址内存内容(如0xF4DB3D20)
  • 执行后R3=内存内容

(2) MOV指令

MOV R2, #4  ; 4→R2
  • 执行后R2=4

(3) STR指令

STR LR, [SP, #VAR_4]!  ; LR→SP-4,SP=SP-4
  • 将LR保存到栈顶-4的位置
  • 更新SP=SP-4

(4) SUB指令

SUB SP, SP, #0xC  ; SP=SP-0xC
  • 扩展栈空间

(5) ADD指令

ADD R1, SP, R2  ; R1=SP+R2
  • 计算地址偏移

(6) LDR指令

LDR R3, [R3, #0x18]  ; R3=R3+0x18指向的内容
  • 间接寻址加载

(7) MOVT指令

MOVT R2, #1  ; R2高16位=1
  • 修改寄存器高16位

(8) BLX指令

BLX R3  ; 跳转到R3,保存返回地址到LR
  • 跳转到函数
  • LR=下条指令地址
  • 可能切换ARM/Thumb模式

(9) CMP指令

CMP R0, #0  ; R0-0,设置标志位
  • 比较R0与0
  • 影响Z标志位

(10) BNE指令

BNE loc_F3B000B4  ; Z=0时跳转
  • 条件跳转
  • 根据CMP结果决定

五、调试技巧

  1. 断点设置:F2设置/取消断点
  2. 单步执行
    • F7:单步步入(进入函数)
    • F8:单步步过(跳过函数)
  3. 运行到光标:F4运行到当前光标位置
  4. 查看寄存器:在寄存器窗口观察值变化
  5. 查看内存:在Hex窗口右键"Follow in hex dump"
  6. 返回跳转前:ESC返回跳转前的视图
  7. 定位PC:点击PC箭头跳转到当前指令

六、总结

  1. 掌握基本ARM指令格式和寻址方式
  2. 理解常见指令的功能和效果
  3. 熟练使用IDA的调试功能
  4. 关注寄存器变化和标志位影响
  5. 从简单代码开始逐步分析复杂逻辑
  6. 结合静态分析和动态调试验证理解

本教程涵盖了ARM汇编基础和IDA动态调试的核心内容,适合Android逆向初学者建立基本概念和技能。随着实践深入,可进一步学习更复杂的指令和调试技巧。

ARM汇编与IDA动态分析教程 一、ARM指令集基础 1. ARM指令格式 ARM指令基本格式: opcode :指令助记符(如LDR, STR等) cond :执行条件(如EQ, NE等) S :是否影响CPSR寄存器的值 Rd :目标寄存器 Rn :第一个操作数的寄存器 opcode2 :第二个操作数 2. 条件码 条件码对应于ARM指令格式中的执行条件cond,常见条件码: | 条件码 | 含义 | 标志位条件 | |--------|----------------|------------------| | EQ | 等于 | Z=1 | | NE | 不等于 | Z=0 | | CS/HS | 无符号大于等于 | C=1 | | CC/LO | 无符号小于 | C=0 | | MI | 负数 | N=1 | | PL | 正数或零 | N=0 | | VS | 溢出 | V=1 | | VC | 无溢出 | V=0 | 二、ARM寻址方式 1. 寄存器寻址 操作数的值在寄存器中: 2. 立即寻址 操作数是指令中的立即数: 3. 寄存器偏移寻址 对寄存器值进行移位操作: 4. 寄存器间接寻址 使用寄存器中的值作为内存地址: 三、常见ARM指令详解 1. 跳转指令 (1) B指令 无条件跳转: (2) BL指令 带链接的跳转(保存返回地址到LR): (3) BX指令 带状态切换的跳转(根据目标地址最低位切换ARM/Thumb模式): (4) BLX指令 带链接和状态切换的跳转: 2. 存储器访问指令 (1) LDR和STR LDR:从内存加载到寄存器 STR:从寄存器存储到内存 (2) LDM和STM 批量加载/存储: (3) SWP 交换内存和寄存器内容: 3. 数据传送指令 MOV指令 4. 逻辑运算指令 (1) 算术运算 (2) 位运算 5. 比较指令 (1) CMP 比较并设置标志位: (2) TST 位测试: 6. 移位指令 (1) 逻辑移位 (2) 算术移位 四、IDA动态分析实战 1. 调试准备 启动IDA调试器 附加到目标进程 定位到JNI_ OnLoad函数 2. 逐行分析示例 (1) LDR指令 查看R0的值(如0xF4DB3D20) 查看该地址内存内容(如0xF4DB3D20) 执行后R3=内存内容 (2) MOV指令 执行后R2=4 (3) STR指令 将LR保存到栈顶-4的位置 更新SP=SP-4 (4) SUB指令 扩展栈空间 (5) ADD指令 计算地址偏移 (6) LDR指令 间接寻址加载 (7) MOVT指令 修改寄存器高16位 (8) BLX指令 跳转到函数 LR=下条指令地址 可能切换ARM/Thumb模式 (9) CMP指令 比较R0与0 影响Z标志位 (10) BNE指令 条件跳转 根据CMP结果决定 五、调试技巧 断点设置 :F2设置/取消断点 单步执行 : F7:单步步入(进入函数) F8:单步步过(跳过函数) 运行到光标 :F4运行到当前光标位置 查看寄存器 :在寄存器窗口观察值变化 查看内存 :在Hex窗口右键"Follow in hex dump" 返回跳转前 :ESC返回跳转前的视图 定位PC :点击PC箭头跳转到当前指令 六、总结 掌握基本ARM指令格式和寻址方式 理解常见指令的功能和效果 熟练使用IDA的调试功能 关注寄存器变化和标志位影响 从简单代码开始逐步分析复杂逻辑 结合静态分析和动态调试验证理解 本教程涵盖了ARM汇编基础和IDA动态调试的核心内容,适合Android逆向初学者建立基本概念和技能。随着实践深入,可进一步学习更复杂的指令和调试技巧。