版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/
RegisterNatives
RegisterNatives 是 JNI(Java Native Interface)的一部分,用于在 Java 类和本地 C/C++ 代码之间注册本地方法。其原型如下:
jint RegisterNatives(JNIEnv* env, jclass clazz, const JNINativeMethod* methods, jint method_count);
参数说明:
-
env:JNIEnv 指针。
-
clazz:Java 类的 jclass 句柄。
-
methods:指向 JNINativeMethod 结构体数组的指针。
-
method_count:要注册的方法数量。
其中,methods 结构体的定义如下:
typedef struct {
const char* name; // 方法名称(指向字符串)
const char* signature; // 方法签名(指向字符串)
void* fnPtr; // 方法的本地实现(指向本地函数)
} JNINativeMethod;
可以看到,每个 JNINativeMethod 结构体由 三个指针 组成:
-
name(方法名指针)
-
signature(方法签名指针)
-
fnPtr(本地方法指针)
一般会有两个 RegisterNatives 函数,CheckJNI 版本只有在调试选项打开时才会调用,我们一般用 JNI 的那个就行。
[+] Found RegisterNatives symbol: _ZN3art12_GLOBAL__N_18CheckJNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi at 0x780d7757a8
[+] Found RegisterNatives symbol: _ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi at 0x780d7eed10
通过 hook RegisterNatives 实现监控 app 中动态注册的 JNI 函数。代码如下:
RegisterNatives.js
// 查找 libart.so 中的 RegisterNatives 地址
function findRegisterNativesAddr() {
let symbols = Module.enumerateSymbolsSync("libart.so");
let addrRegisterNatives = null;
// 遍历所有符号,查找非 CheckJNI 版本的 RegisterNatives
for (let i = 0; i < symbols.length; i++) {
let symbol = symbols[i];
// 确认符合 RegisterNatives 标准的符号(非 CheckJNI 版本)
if (symbol.name.indexOf("CheckJNI") < 0 &&
symbol.name.indexOf("RegisterNatives") >= 0) {
addrRegisterNatives = symbol.address;
console.log("[+] Found RegisterNatives symbol: " + symbol.name + " at " + symbol.address);
break; // 找到第一个匹配的符号即可
}
}
// 如果没有找到 RegisterNatives 地址,返回 null
if (addrRegisterNatives === null) {
console.log("[!] No non-CheckJNI RegisterNatives symbol found!");
}
return addrRegisterNatives;
}
// Hook RegisterNatives 函数,打印方法相关信息
function hookRegisterNatives(addrRegisterNatives) {
if (addrRegisterNatives !== null) {
// 使用 Interceptor 附加到 RegisterNatives 地址
Interceptor.attach(addrRegisterNatives, {
onEnter: function (args) {
// 获取 java 类和方法列表
let javaClass = args[1];
let className = Java.vm.tryGetEnv().getClassName(javaClass); // 获取类名
// 打印 RegisterNatives 的方法参数
let methodsPtr = ptr(args[2]);
let methodCount = args[3].toInt32();
console.log("[RegisterNatives] method_count:", methodCount);
// 遍历注册的每个 JNI 方法
for (let i = 0; i < methodCount; i++) {
let methodPtr = methodsPtr.add(i * Process.pointerSize * 3); // 获取每个方法的指针
// 读取每个方法的名称、签名和函数指针
let namePtr = Memory.readPointer(methodPtr);
let sigPtr = Memory.readPointer(methodPtr.add(Process.pointerSize));
let fnPtr = Memory.readPointer(methodPtr.add(Process.pointerSize * 2));
let name = Memory.readCString(namePtr); // 方法名称
let sig = Memory.readCString(sigPtr

最低0.47元/天 解锁文章
2597

被折叠的 条评论
为什么被折叠?



