Frida无法拦截通过RegisterNatives注册的JNI方法(libnative-lib.so)
Frida无法拦截通过RegisterNatives注册的JNI方法(libnative-lib.so)
我完全懂你现在的困扰——明明已经通过Hook RegisterNatives拿到了目标方法m()的函数指针和偏移,可直接用偏移去Hook却连个日志都打不出来,还确认了方法确实在运行时被调用了。这种情况大概率是几个细节没处理对,我来帮你排查下:
1. 先确认偏移计算是否正确
你用的0x14610c这个偏移,有没有和RegisterNatives里拿到的函数指针做过验证?比如在RegisterNatives的Hook脚本里,输出fnPtr.sub(libBase)的结果,看看是不是和你用的偏移完全一致。
有时候不同架构(arm/arm64)的偏移会不一样,或者你可能误把虚拟地址当成了相对基地址的偏移,这都会导致Hook到错误的地址。
2. 调整Hook的时机,别依赖固定延迟
你用setTimeout(5000)来延迟Hook,很可能赶不上库加载或者方法注册的时机。换成监听库加载事件会更可靠:
Module.load("libnative-lib.so", function() { const libBase = Module.findBaseAddress("libnative-lib.so"); // 先确认这个偏移是正确的 const NATIVE_OFFSET = 0x14610c; const nativeFuncPtr = libBase.add(NATIVE_OFFSET); Interceptor.attach(nativeFuncPtr, { onEnter: function(args) { console.log("[+] Native m() called!"); // 注意JNI方法的参数顺序:第一个是JNIEnv*,第二个是实例的this,之后才是Java层传的参数 console.log(`JNIEnv*: ${args[0]}`); console.log(`this实例: ${args[1]}`); console.log(`context参数: ${args[2]}`); console.log(`p02参数: ${args[3].toInt32()}`); console.log(`p12参数: ${args[4].toInt32()}`); }, onLeave: function(retval) { // 返回值是String,转成可读字符串 console.log(`[+] Native m() returned: ${retval.readUtf8String()}`); } }); });
3. 直接用RegisterNatives拿到的指针Hook,跳过偏移计算
其实最稳妥的方式是在Hook RegisterNatives的时候,直接拿到m()的函数指针并立刻Hook,这样完全不会出错:
let targetMethodPtr = null; // 先Hook RegisterNatives拿到目标方法的指针 Process.enumerateModules().forEach(function (m) { Module.enumerateSymbolsSync(m.name).forEach(function (s) { if (s.name.includes("RegisterNatives") && !s.name.includes("CheckJNI")) { console.log(`找到RegisterNatives: ${m.name} -> ${s.name}`); Interceptor.attach(s.address, { onEnter: function (args) { const nMethods = parseInt(args[3]); const className = Java.vm.tryGetEnv().getClassName(args[1]); // 替换成你实际的类名 if (className === "com/your/app/TargetClass") { const methodsPtr = ptr(args[2]); for (let i = 0; i < nMethods; i++) { const base = methodsPtr.add(i * Process.pointerSize * 3); const methodName = Memory.readCString(Memory.readPointer(base)); if (methodName === "m") { targetMethodPtr = Memory.readPointer(base.add(Process.pointerSize * 2)); console.log(`[+] 找到目标方法m(),地址: ${targetMethodPtr}`); // 拿到指针直接Hook Interceptor.attach(targetMethodPtr, { onEnter: function(args) { console.log("[+] Native m() 被调用了!"); console.log(`JNIEnv*: ${args[0]}`); console.log(`this实例: ${args[1]}`); console.log(`context参数: ${args[2]}`); console.log(`p02: ${args[3].toInt32()}`); console.log(`p12: ${args[4].toInt32()}`); }, onLeave: function(retval) { console.log(`[+] Native m() 返回值: ${retval.readUtf8String()}`); } }); } } } } }); } }); });
4. 排查反调试或进程附加问题
如果上面的方法都不行,要考虑是不是应用有反调试机制,比如检测Frida的存在。可以试试用frida -U -f com.your.app.package --no-pause命令,在应用启动初期就注入脚本,避免反调试逻辑生效。另外也要确认你附加的是正确的进程。
内容来源于stack exchange
相关产品推荐
相关产品推荐

