首页
社区
课程
招聘
[原创]Android中JNI方式调用Jar包
发表于: 2013-10-10 10:25 32807

[原创]Android中JNI方式调用Jar包

2013-10-10 10:25
32807
标 题: 【原创】Android中JNI方式调用Jar包
作 者: 蟑螂一号
时 间: 2013-10-10,10:44:03
   最近在研究DexClassLoader加载jar包,在帖子“使用DexClassLoader调用jar包”使用的是Java方式来加载jar包,并调用jar包中的方法,完成相关功能。现在我将通过JNI方式实现动态加载jar的成果和大家分享一下。
  以下为关键代码,经手机测试正常运行:
  ///java调用的jni方法
/*参数说明:
*  path1:       jar存储路径
*  path2:                经过优化后的dex存存放路径
*  className:    需要调用jar包中的类名
*  methodName: 需要调用的类中的静态方法
*  注意:path1 和path2将会作为DexClassLoader构造函数中的第一、第二参数
*  我在java中定义的native方法为:public static native void callHook(String dexPath,String optPath,String className,String methodName);
*/
static void com_mtn_javainject_CopyFile_callHook(JNIEnv *env, jclass,jstring path1, jstring path2, jstring className, jstring methodName) {
        //找到ClassLoader类
        jclass classloaderClass = env->FindClass("java/lang/ClassLoader");
        //找到ClassLoader类中的静态方法getSystemClassLoader
        jmethodID getsysloaderMethod = env->GetStaticMethodID(classloaderClass, "getSystemClassLoader","()Ljava/lang/ClassLoader;");
        //调用ClassLoader中的getSystemClassLoader方法,返回ClassLoader对象
        jobject loader =env->CallStaticObjectMethod(classloaderClass,getsysloaderMethod);

        //jar包存放位置
        jstring dexpath = path1;
        //优化后的jar包存放位置
        jstring dex_odex_path = path2;
        //找到DexClassLoader类
        jclass dexLoaderClass = env->FindClass("dalvik/system/DexClassLoader");
        //获取DexClassLoader的构造函数ID
        jmethodID initDexLoaderMethod =env->GetMethodID(dexLoaderClass, "<init>","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V");
        //新建一个DexClassLoader对象
        jobject dexLoader =env->NewObject(dexLoaderClass,initDexLoaderMethod, dexpath, dex_odex_path, NULL, loader);

        //找到DexClassLoader中的方法findClass
        jmethodID findclassMethod = env->GetMethodID(dexLoaderClass,"findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
        //如果返回空,那就找DexClassLoader的loadClass方法
        //说明:老版本的SDK中DexClassLoader有findClass方法,新版本SDK中是loadClass方法
    if(NULL==findclassMethod)
    {
                //
           findclassMethod = env->GetMethodID(dexLoaderClass,"loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
    }
    //存储需要调用的类
        jstring javaClassName = className;
        //调用DexClassLoader的loadClass方法,加载需要调用的类
        jclass javaClientClass=(jclass)env->CallObjectMethod(dexLoader,findclassMethod,javaClassName);

        //将jstring类型的方法名转换为utf8编码的字符串
        const char* func =env->GetStringUTFChars(methodName, NULL);
    //获取加载的类中的方法
        //
        jmethodID inject_method = env->GetStaticMethodID(javaClientClass, func, "()V");
        //调用加载的类中的静态方法
        env->CallStaticVoidMethod(javaClientClass,inject_method);
}

  在Java层,native调用代码:
CopyFile.callHook(dexInternalStoragePath.getAbsolutePath(), optimizedDexOutputPath.getAbsolutePath(), "com.mtn.binder.HookIPhoneSubInfo", "hook");

  以上封装的方法测试验证通过。

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (14)
雪    币: 76
活跃值: (55)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
思路不错,这样隐藏的更深了
2013-10-10 10:50
0
雪    币: 123
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
很好的教程,值得学习!
2013-10-10 12:00
0
雪    币: 158
活跃值: (196)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
mark一下 ,这个有科技含量
2013-10-13 13:58
0
雪    币: 95
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
那个path2,就是存放目标dex的目录,到那儿就可拿到想要的dex了。Android真挫,破解总是易如反掌。
2013-12-22 01:56
0
雪    币: 77
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
存放的dex可以使加密过的,解密的可以放在so库中做,dex的加载过程也可以使用jni来做而不用java
2013-12-23 09:34
0
雪    币: 16
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
odex_path 可以用getFilesDir().getAbsolutePath()。这也可以用jni来写,不过估计只有主线程可以,其他线程拿不到ContextWrapper 的class
2014-11-6 14:42
0
雪    币: 34
活跃值: (50)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
seandroid 应该没办法通过把?
2014-11-6 16:44
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
你好,我现在想注入zygote后然后在so中加载一个jar包,也是使用你这一样的代码,但是在找class的始终找不到jar包里面的class,而且疏忽jar包也没有被unzip,请大神赐教一下,谢谢
2015-1-30 14:25
0
雪    币: 19
活跃值: (40)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
谢谢呀,标记收藏
2015-1-30 15:17
0
雪    币: 20
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
楼主,jni的和android的接口方法com_mtn_javainject_CopyFile_callHook第二个参数没有jclass没有类型也可以跑起来?第二参数不是固定的obj 吗
2015-1-30 23:16
0
雪    币: 28
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
在本地会保存odex(xxx.dex),好像4.1之前的版本都有这个通病
2015-1-31 20:49
0
雪    币: 228
活跃值: (75)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
13
楼主你好,我想调用Jar中的非静态方法

我用的是C,不是C++,我的代码是
//调用加载的类中的方法
jobject str = (*env)->CallObjectMethod(env,javaClientClass,inject_method);

想调用jar包中的非静态的getHelloWorldStr函数

问题来了,

为什么执行这一句的时候会报错呢?

显示JNI WARNING: can't call xxx;.getHelloWorldStr on instance of Ljava/lang/Class; (CallObjectMethod)

难道这种方案只能调用static方法?
2015-2-2 13:55
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
hook 时 第三方应用如何加载jar 我把路径放到/system/hook 下貌似 不行 chmod777 了
Optimized data directory /system/hook is not owned by the current user.Shared storage cannot protect your application from code injection attacks.
2015-3-24 10:44
0
雪    币: 3
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
楼主,根据如果我需要最终要调用java的实例方法,不是你上面写的静态方法,不知该如何调用,请指点一下,谢谢
2015-12-31 21:05
0
游客
登录 | 注册 方可回帖
返回
//