我在 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>
你知道我错过了什么吗?
您有多个问题:
libnativelib.so
libnativelib.so
时才会加载
com.app.s.Api
。第一次使用此类时会发生这种情况。
最好的方法是挂钩该类的
static {...
部分(这就是方法 <clinit>
)。不幸的是我不知道 Frida 是否支持 hooking clinit 方法,一些旧版本似乎这样做有问题,不确定最近的版本。
因此,我的建议是挂钩 Java 类
java.lang.System
loadLibrary
方法来检查您正在搜索的库何时加载。
加载完成后可以直接安装
target_func
的挂钩。
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'));
}
});
}
}
});