移动安全之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结果决定
五、调试技巧
- 断点设置:F2设置/取消断点
- 单步执行:
- F7:单步步入(进入函数)
- F8:单步步过(跳过函数)
- 运行到光标:F4运行到当前光标位置
- 查看寄存器:在寄存器窗口观察值变化
- 查看内存:在Hex窗口右键"Follow in hex dump"
- 返回跳转前:ESC返回跳转前的视图
- 定位PC:点击PC箭头跳转到当前指令
六、总结
- 掌握基本ARM指令格式和寻址方式
- 理解常见指令的功能和效果
- 熟练使用IDA的调试功能
- 关注寄存器变化和标志位影响
- 从简单代码开始逐步分析复杂逻辑
- 结合静态分析和动态调试验证理解
本教程涵盖了ARM汇编基础和IDA动态调试的核心内容,适合Android逆向初学者建立基本概念和技能。随着实践深入,可进一步学习更复杂的指令和调试技巧。