我们自己写一个简单的app,java层调用so 方法返回的字符串打印输出,java层和c代码如下
1 2 3 4 5 6 7 8 | public class TestUtil { static { System.loadLibrary( "security" ); } public static native String getSecretPro( int adam); } |
1 2 | #调用jni方法 LogUtil.e( "adam" ,TestUtil.getSecretPro(23)); |
1 2 3 4 5 | #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的基地址方法如下:
1 | 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方法,完整的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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 回复