首页
社区
课程
招聘
[原创]使用DexClassLoader调用jar包
2013-10-9 17:12 30903

[原创]使用DexClassLoader调用jar包

2013-10-9 17:12
30903
标 题: 【原创】使用DexClassLoader调用jar包
作 者: 蟑螂一号
时 间: 2013-10-09,21:44:41
    最近在研究Android中基于Java虚拟机的拦截技术。需要用到DexClassLoader加载自己写的第三方jar包,例如金山毒霸需要加载ksremote.jar。现在将DexClassLoader加载jar包成果分享一下。
   1.新建Android工程,封装功能java类。
   2.选中需要导出的文件夹,右键选中“Export”->"Java(Jar file)"导出jar文件。
   3.使用dx工具将jar包转换为android 字节码。
      命令:dx  --dex --Output=xx.jar    hello.jar
   4.将dx工具处理的xx.jar拷贝到工程raw目录下。
   5.在工程主Activity的onCreate函数中读取raw下的文件,并存储在当前应用目录。
      我的例子代码:
       InputStream inputStream = getResources().openRawResource(
                                R.raw.mtnbinder);
                dexInternalStoragePath = new File(
                                getDir(APP_JAR, Context.MODE_PRIVATE), DEX_NAME);
                if (!dexInternalStoragePath.exists()) {
                        try {
                                dexInternalStoragePath.createNewFile();
                        } catch (IOException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                        }
                }
               
                        FileOutputStream fileOutputStream = new FileOutputStream(
                                        dexInternalStoragePath);
                        CopyFile.copyFile(inputStream, fileOutputStream);
        6.使用DexClassLoader调用jar包。
          我的例子代码:
           final File optimizedDexOutputPath = getDir(APP_JAR,
                                                Context.MODE_PRIVATE);
                                try {
                                        DexClassLoader classLoader = new DexClassLoader(
                                                        dexInternalStoragePath.getAbsolutePath(),
                                                        optimizedDexOutputPath.getAbsolutePath(), null,
                                                        getClassLoader());
                                        // com.mtn.binder.HookIPhoneSubInfo
                                        Class class1 = classLoader
                                                        .loadClass("com.mtn.binder.HookIPhoneSubInfo");
                                        Method method = class1.getMethod("hook", new Class[] {});
                                        method.invoke(class1, new Object[] {});

             运行之后,就可以看到调用jar包成功。

阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开 发者可享99元/年,续费同价!

收藏
点赞3
打赏
分享
最新回复 (12)
雪    币: 1413
活跃值: (401)
能力值: (RANK:270 )
在线值:
发帖
回帖
粉丝
Claud 6 2013-10-9 18:22
2
0
赞!
有个小疑问,dx --dex转换以后,实际应该就是个DEX文件吧?虽然楼主把它命名成Jar。
雪    币: 1013
活跃值: (1397)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
aihacker 2013-10-9 19:50
3
0
支持学习一下
雪    币: 257
活跃值: (3623)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
蟑螂一号 1 2013-10-9 21:01
4
0
转换之后dex文件就放在jar包里
雪    币: 185
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
whnet 2013-10-10 16:37
5
0
有比较通用的内存加载的技术么、
雪    币: 213
活跃值: (147)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jasonzhou 2013-10-10 22:27
6
0
核心是说用dx把jar编译成dex么
雪    币: 257
活跃值: (3623)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
蟑螂一号 1 2013-10-11 09:22
7
0
差不多吧
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
magicdigua 2014-2-9 21:20
8
0
加载的jar包无法调用apk里面的资源,“爱加密”出来的加密包确可以..
雪    币: 107
活跃值: (311)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Fido 2014-5-24 14:41
9
0
那么按楼主所描述。。

我想问下。。如果已经有一个jar包,是按照楼主所述,内部是DEX格式,但是披着jar的外衣。

有什么办法也就是不用动态加载的方式调用,静态还原解析可以用JD-GUI读取么?
雪    币: 10
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xupang 2014-10-18 17:01
10
0
楼主,根据你帖子中描述的方法进行实践,发现总提示ClassNotFound.
我的java代码如下:
package com.example.testjar;

import java.io.File;

import dalvik.system.DexClassLoader;

import android.R.string;
import android.support.v7.app.ActionBarActivity;
import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends ActionBarActivity {

        public native void callHook(String dexPath,String optPath,String className,String methodName);

            static {  
                System.loadLibrary("loadJar");  
            }       
            public static String APP_JAR="D:\\Android_development\\loadSource";
            public static String DEX_NAME="data@app@com.example.hookentry-2.apk@classes.dex";
           // public static String OPT_DEX="D:\\Android_development\\loadSource\\data@app@com.example.hookentry-2.apk@classes.dex";
            @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                Log.e("two","testjar is running!");       
                File dexInternalStoragePath = new File(
                        getDir(APP_JAR, Context.MODE_PRIVATE), DEX_NAME);
                final File optimizedDexOutputPath = getDir(APP_JAR,
                    Context.MODE_PRIVATE);
                  Log.e("internal",dexInternalStoragePath.getAbsolutePath());
                  Log.e("optimized",optimizedDexOutputPath.getAbsolutePath());
                callHook(dexInternalStoragePath.getAbsolutePath(), optimizedDexOutputPath.getAbsolutePath(), "com.example.hookentry.MainActivity", "test");
       
                       
        }
            

}
求指导。DEX_NAME是从/data/dalvik-cache中或得到的优化后的dex文件
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
DeepNoite 2014-11-3 14:59
11
0
怎么调用资源文件呢?
雪    币: 1185
活跃值: (458)
能力值: ( LV13,RANK:360 )
在线值:
发帖
回帖
粉丝
Ericky 6 2015-1-7 18:57
12
0
楼主的转化是把jar源代码转换成了jar binaries
雪    币: 228
活跃值: (50)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
Colbert仔 2015-2-2 11:56
13
0
我用的是C,不是C++,我的代码是

//调用加载的类中的非静态方法
jobject str = (*env)->CallObjectMethod(env,javaClientClass,inject_method);

想调用jar包中的getHelloWorldStr函数,返回一个String类型
为什么执行这一句的时候会报错呢?

显示JNI WARNING: can't call xxx;.getHelloWorldStr on instance of Ljava/lang/Class; (CallObjectMethod)
游客
登录 | 注册 方可回帖
返回