我们自己写一个简单的app,java层调用so 方法返回的字符串打印输出,java层和c代码如下
public class TestUtil {
static {
System.loadLibrary("security");
}
public static native String getSecretPro(int adam);
}#调用jni方法
LogUtil.e("adam",TestUtil.getSecretPro(23));#C方法返回字符串
JNIEXPORT jstring JNICALL Java_com_adam_ndktest_TestUtil_getSecretPro
(JNIEnv *env, jclass jobj, jint val){
return (*env)->NewStringUTF(env,"eveve");
}打包生成apk,安装到手机
把libsecurity.so文件拖入ida分析,

由上图可知,Java_com_adam_ndktest_TestUtil_getSecretPro方法的偏移地址是0x630,字符串便宜地址是0x64f,那么我们用基址+偏移地址就是函数的绝对地址了,frida获取so的基地址方法如下:
var soAddr=Module.findBaseAddress("libsecurity.so");Java_com_adam_ndktest_TestUtil_getSecretPro地址是soAddr+0x630:
var proAddr=soAddr.add(0x630 );
我们要直接hook返回值的话就是soAddr+0x64f地址对应的字符串 ,然后通过Memory.readUtf8String方法读取,更改返回值的话需要用到JNIEnv api的newStringUtf方法,完整的代码如下:
Java.perform(function () {
// Memory.readUtf8String
var mru8s = function(addr) {return Memory.readUtf8String(addr);};
var soAddr=Module.findBaseAddress("libsecurity.so");
console.log("soAddr:"+soAddr);
var proAddr=soAddr.add(0x630);
console.log("proAddr:"+proAddr);
Interceptor.attach(proAddr, {
onEnter: function (args) {
console.log("-----华丽的分割线-----");
},
onLeave: function(retval){
var staddr=soAddr.add(0x64f);
console.log(staddr);
var nat=new NativePointer(staddr);
console.log("nat:"+nat);
console.log("str:"+mru8s(staddr)); //读取返回的字符串
//替换返回字符串
var env = Java.vm.getEnv();
var jstring = env.newStringUtf("lixiaopeng");
retval.replace(ptr(jstring));
send("retval:"+retval);
}
});
});本文为Adamin90原创文章,转载无需和我联系,但请注明来自http://www.lixiaopeng.top
你的糖罐呢:wink~
2019-11-12 15:49:59 回复