Native层逆向:ARM汇编与JNI调用分析
1. ARM汇编基础与逆向框架
1.1 ARM指令集核心概念
1.1.1 寄存器体系解析
ARM64寄存器用途速查表:
寄存器 | 别名 | 用途 |
---|---|---|
X0-X7 | 参数寄存器 | 函数参数传递与临时存储 |
X8 | XR | 间接结果寄存器 |
X9-X15 | 临时寄存器 | 局部变量存储 |
X16-X17 | IP0-IP1 | 过程调用临时寄存器 |
X18 | PR | 平台保留寄存器 |
X29 | FP | 帧指针 |
X30 | LR | 返回地址 |
SP | 栈指针 | 栈内存管理 |
1.1.2 常用指令模式
数据操作指令:
MOV X0, X1 // 寄存器间数据传输
ADD X2, X3, #0x10 // 立即数加法运算
LDR X4, [X5, #0x20] // 内存加载(X5+0x20地址的值→X4)
STR X6, [X7], #8 // 内存存储(X6→X7地址,X7+=8)
控制流指令:
CMP X0, #10 // 比较X0与10
B.EQ label // 相等时跳转
BL _printf // 调用函数(保存返回地址到LR)
RET // 从子程序返回(等效MOV PC, LR)
2. JNI调用机制深度解析
2.1 JNI接口架构
Java与Native交互流程:
sequenceDiagram
Java Code->>JNI Bridge: 声明native方法
JNI Bridge->>Native Lib: 动态注册/JNI_OnLoad
Native Lib->>Java VM: 通过JNIEnv调用Java方法
Java VM-->>Native Lib: 返回结果
2.2 动态注册逆向技巧
动态注册代码特征:
JNINativeMethod methods[] = {
{"encrypt", "(Ljava/lang/String;)[B", (void*)nativeEncrypt},
{"decrypt", "([B)Ljava/lang/String;", (void*)nativeDecrypt}
};
env->RegisterNatives(clazz, methods, 2);
逆向定位策略:
-
搜索
RegisterNatives
交叉引用 -
分析
JNI_OnLoad
初始化函数 -
追踪方法签名与实现地址映射
3. 逆向工具链实战
3.1 IDA Pro高级分析
函数识别技巧:
-
使用F5伪代码生成快速定位关键逻辑
-
重命名关键函数(快捷键
N
)提升可读性 -
创建结构体还原复杂数据类型:
struct AES_CTX {
uint32_t round_key[60];
int key_length;
};
3.2 Ghidra脚本开发
自动化字符串解密脚本:
from ghidra.program.util import DefinedDataIterator
def decrypt_xor(data, key):
return bytes([b ^ key for b in data])
for data in DefinedDataIterator.definedStrings(currentProgram()):
if data.length == 16:
encrypted = data.value
decrypted = decrypt_xor(encrypted, 0x5A)
print(f"{data.address}: {decrypted}")
4. Native层Hook技术
4.1 Frida Native Hook
拦截JNI函数调用:
const env = Java.vm.getEnv();
const GetStringUTFChars = env.GetStringUTFChars;
env.GetStringUTFChars = function(str, isCopy) {
const result = GetStringUTFChars.call(this, str, isCopy);
console.log(`GetStringUTFChars: ${result.readCString()}`);
return result;
};
Hook ARM函数实例:
const nativeFunc = Module.findExportByName("libnative.so", "AES_encrypt");
Interceptor.attach(nativeFunc, {
onEnter: function(args) {
this.plaintext = args[0];
this.key = args[1];
console.log(hexdump(this.plaintext, { length: 16 }));
},
onLeave: function(retval) {
console.log(hexdump(retval, { length: 16 }));
}
});
4.2 Inline Hook实战
ARM64指令修补示例:
// 原指令(地址0x1234)
LDR X0, [X1]
// Hook跳转指令
LDR X16, =hook_entry
BR X16
修补代码实现:
void hook_entry() {
// 保存寄存器上下文
asm volatile("STP X0, X1, [SP, #-16]!");
// Hook逻辑处理
log_parameters();
// 恢复执行
asm volatile("LDP X0, X1, [SP], #16");
asm("LDR X0, [X1]"); // 执行原始指令
}
5. 复杂数据结构逆向
5.1 结构体还原技术
内存布局分析:
// 逆向生成的JNI结构体
struct JNIInvokeInterface {
void* reserved0;
void* reserved1;
void* reserved2;
jint (*GetVersion)(JNIEnv*);
jclass (*FindClass)(JNIEnv*, const char*);
// ...其他方法指针
};
IDA结构体定义:
-
Shift+F1
打开结构体窗口 -
创建
JNIEnv
结构并添加方法指针 -
应用结构体到反汇编代码
5.2 多级指针追踪
链表结构逆向案例:
LDR X0, [X19, #0x18] // 加载next指针
LDR W1, [X0, #0x4] // 读取data字段
CMP W1, #0x20
B.EQ found_target
6. 反调试与反逆向对抗
6.1 调试器检测绕过
PTRACE反调试对抗:
// 原始检测代码
if (ptrace(PTRACE_TRACEME, 0, 1, 0) == -1) {
exit(0);
}
// Hook绕过方案
Interceptor.attach(Module.findExportByName("libc.so", "ptrace"), {
onEnter: function(args) {
if (args[0].toInt32() == PTRACE_TRACEME) {
this.bypass = 1;
}
},
onLeave: function(retval) {
if (this.bypass) retval.replace(0);
}
});
6.2 代码混淆对抗
控制流平坦化破解:
-
识别状态分发器函数
-
分析状态转移逻辑
-
重建原始控制流程图
; 混淆后的控制流片段
MOV W0, #0x3A
CMP X1, X2
ADRP X8, #jumptable@PAGE
ADD X8, X8, #jumptable@PAGEOFF
LDR X9, [X8, W0, UXTP#2]
BR X9
7. 企业级实战案例
7.1 视频加密协议逆向
破解流程:
-
定位
libmedia.so
中的decryptFrame
函数 -
分析ARM汇编确定密钥调度逻辑
-
Hook
av_aes_init
获取密钥与IV -
重写FFmpeg解密过滤器
关键代码:
class VideoDecryptor:
def __init__(self, key, iv):
self.cipher = AES.new(key, AES.MODE_CBC, iv)
def decrypt_frame(self, data):
return self.cipher.decrypt(data)
7.2 游戏引擎逆向
Unity IL2CPP分析:
-
提取
global-metadata.dat
-
使用Il2CppDumper恢复符号
-
分析
il2cpp_codegen_raise_exception
异常处理 -
Hook
Physics.Raycast
实现游戏作弊
技术验证清单:
-
完成ARM64基本指令集逆向分析
-
实现JNI动态注册方法追踪
-
开发Ghidra自动化分析脚本
-
构建Frida Native Hook框架
-
复现企业级Native层逆向案例
本章实验需基于ARM64架构设备(如Pixel 6),建议使用开源Native项目(如FFmpeg)作为分析目标。所有Hook操作应限制在测试进程空间内,禁止修改生产环境二进制文件。
关于作者:
15年互联网开发、带过10-20人的团队,多次帮助公司从0到1完成项目开发,在TX等大厂都工作过。当下为退役状态,写此篇文章属个人爱好。本人开发期间收集了很多开发课程等资料,需要可联系我