无法使用frida(android)找到JNI函数

问题描述 投票:0回答:1

我在 Android 应用程序中有以下课程:

package com.app.s;

public final class Api {
    public native int func(String str, String str2);

    ...
    ...
    static {
        try {
            System.loadLibrary("nativelib");
        } catch (UnsatisfiedLinkError e) {
            Log.e("lib", "fail:" + e.getMessage());
        }
    }
}

libnativelib.so
中:函数
Java_com_app_s_Api_func
正在调用
target_func

我正在尝试访问

target_func
变量 但是我无法用 frida 找到加载的模块

我已经和弗里达尝试过以下操作:

尝试 1 - 不打印库名称

var allModules = Process.enumerateModules()
for(var i=0;i<allModules.length;i++){ 
  console.log(allModules[i].name); 
}

尝试 2 - 错误:java.lang.ClassNotFoundException:未找到类“Java_com_app_s_Api”

Java.perform(function() {
  var it = setInterval(function(){
    try{
      var hook = Java.use("Java_com_app_s_Api");
      console.log("info: hooking target class");

      hook.func.overload().implementation = function() {
                console.log("[+] func")

                var ret = this.func()
                console.log("[*] retval: " + ret)
                return ret

      }
    } catch(e) {
      console.log(e);
    }
  },200); // runs every 200milisecods
});

尝试 3 - 尽管正在调用库中的函数,但不打印它们

frida-trace -U -i "Java_*" -f <app>

你知道我错过了什么吗?

android java-native-interface frida
1个回答
0
投票

您有多个问题:

寻找模块
libnativelib.so

仅当加载 Java 类

libnativelib.so

 时才会加载 
com.app.s.Api
。第一次使用此类时会发生这种情况。

最好的方法是挂钩该类的

static {...
部分(这就是方法
<clinit>
)。不幸的是我不知道 Frida 是否支持 hooking clinit 方法,一些旧版本似乎这样做有问题,不确定最近的版本。

因此,我的建议是挂钩 Java 类

java.lang.System
loadLibrary
方法来检查您正在搜索的库何时加载。

加载完成后可以直接安装

target_func
的挂钩。

挂钩 Java_com_app_s_Api

Java_com_app_s_Api
不是一个 Java 类,它是一个本机 JNI 函数的名称,该函数实现了一个可以从 Java 调用的函数,因为它是一个 Java 函数(但事实并非如此)。因此
Java.use("Java_com_app_s_Api")
永远不会起作用。能起作用的是
Java.use("com.app.s.Api")

因此,您可以尝试为 JNI 方法

com.app.s.Api
的类
func(String str, String str2)
创建 Java 挂钩,或者在 C 函数 Java_com_app_s_Api_func 上使用
Interceptor.attach
创建本机挂钩(参见示例 here)。

挂钩
target_func

我假设

target_func
不是库导出的函数。因此,您必须使用识别和使用函数的地址。为此,您需要 Ghidra 或 IDA Pro 等外部工具来获取函数的地址。然后在运行时您可以计算需要挂钩的地址。更多详细信息可以在问题和我的回答中找到frida hook native non Export Functions

示例代码

总的来说,我建议您遵循 frida-snippet JNI 挂钩示例

var moduleName = "libfoo.so"; 
var nativeFuncAddr = 0x1234; // get the address via Ghidra/IDA/...

Interceptor.attach(Module.findExportByName(null, "dlopen"), {
    onEnter: function(args) {
        this.lib = Memory.readUtf8String(args[0]);
        console.log("dlopen called with: " + this.lib);
    },
    onLeave: function(retval) {
        if (this.lib.endsWith(moduleName)) {
            console.log("ret: " + retval);
            var baseAddr = Module.findBaseAddress(moduleName);
            Interceptor.attach(baseAddr.add(nativeFuncAddr), {
                onEnter: function(args) {
                    console.log("[-] hook invoked");
                    console.log(JSON.stringify({
                        a1: args[1].toInt32(),
                        a2: Memory.readUtf8String(Memory.readPointer(args[2])),
                        a3: Boolean(args[3])
                    }, null, '\t'));
                }
            });
        }
    }
});
© www.soinside.com 2019 - 2024. All rights reserved.