【Android 逆向】启动 DEX 字节码中的 Activity 组件 ( DEX 文件准备 | 拷贝资源目录下的文件到内置存储区 | 配置清单文件 | 启动 DEX 文件中的组件 | 执行结果 )





一、DEX 字节码文件准备



在 dex_demo 应用 Module 中 , 创建 com.example.dex_demo.MainActivity2 类 ;

在这里插入图片描述

代码主要内容为 :

package com.example.dex_demo;

import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity2 extends AppCompatActivity {
    
    

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        Log.i("MainActivity2", "com.example.dex_demo.MainActivity2 onCreate");
    }
}

编译上述 Module 生成 APK 文件 dex_demo-debug.apk , 解压 APK 文件到 dex_demo-debug 目录中 , 将 dex_demo-debug 目录中的 classes.dex 复制一份 , 重名为 classes2.dex , 这是为了与上一个示例中的文件重名而修改的 ;

在这里插入图片描述





二、拷贝 Assets 目录下的 classes2.dex 字节码文件到内置存储区



将 app\src\main\assets\classes2.dex 文件 , 拷贝到 /data/user/0/com.example.classloader_demo/files/classes2.dex 位置 ;

最终的拷贝结果如下 :
在这里插入图片描述


代码示例 :

    /**
     * 测试调用 Dex 字节码文件中的方法
     * @param context
     * @param dexFilePath
     */
    private void testDex(Context context, String dexFilePath) {
    
    
        // 优化目录
        File optFile = new File(getFilesDir(), "opt_dex");
        // 依赖库目录 , 用于存放 so 文件
        File libFile = new File(getFilesDir(), "lib_path");

        // 初始化 DexClassLoader
        DexClassLoader dexClassLoader = new DexClassLoader(
                dexFilePath,                    // Dex 字节码文件路径
                optFile.getAbsolutePath(),      // 优化目录
                libFile.getAbsolutePath(),      // 依赖库目录
                context.getClassLoader()        // 父节点类加载器
        );

        // 加载 com.example.dex_demo.DexTest 类
        // 该类中有可执行方法 test()
        Class<?> clazz = null;
        try {
    
    
            clazz = dexClassLoader.loadClass("com.example.dex_demo.DexTest");
        } catch (ClassNotFoundException e) {
    
    
            e.printStackTrace();
        }

        // 获取 com.example.dex_demo.DexTest 类 中的 test() 方法
        if (clazz != null) {
    
    
            try {
    
    
                // 获取 test 方法
                Method method = clazz.getDeclaredMethod("test");
                // 获取 Object 对象
                Object object = clazz.newInstance();
                // 调用 test() 方法
                method.invoke(object);
            } catch (NoSuchMethodException e) {
    
    
                e.printStackTrace();
            } catch (IllegalAccessException e) {
    
    
                e.printStackTrace();
            } catch (InstantiationException e) {
    
    
                e.printStackTrace();
            } catch (InvocationTargetException e) {
    
    
                e.printStackTrace();
            }
        }
    }




三、在 AndroidManifest.xml 清单文件中配置组件



com.example.dex_demo.DexTest 组件类配置到 AndroidManifest.xml 清单文件中 ;

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.classloader_demo">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.ClassLoader_Demo">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.example.dex_demo.MainActivity2"/>
    </application>

</manifest>

在这里插入图片描述





四、启动 DEX 文件中的 Activity



初始化 DexClassLoader 类加载器 , 加载 com.example.dex_demo.MainActivity2 类 , 然后直接启动该组件 ;


代码示例 :

    /**
     * 不修改类加载器的前提下
     * @param context
     * @param dexFilePath
     */
    private void startDexActivityWithoutClassLoader(Context context, String dexFilePath) {
    
    
        // 优化目录
        File optFile = new File(getFilesDir(), "opt_dex");
        // 依赖库目录 , 用于存放 so 文件
        File libFile = new File(getFilesDir(), "lib_path");

        // 初始化 DexClassLoader
        DexClassLoader dexClassLoader = new DexClassLoader(
                dexFilePath,                    // Dex 字节码文件路径
                optFile.getAbsolutePath(),      // 优化目录
                libFile.getAbsolutePath(),      // 依赖库目录
                context.getClassLoader()        // 父节点类加载器
        );

        // 加载 com.example.dex_demo.DexTest 类
        // 该类中有可执行方法 test()
        Class<?> clazz = null;
        try {
    
    
            clazz = dexClassLoader.loadClass("com.example.dex_demo.MainActivity2");
        } catch (ClassNotFoundException e) {
    
    
            e.printStackTrace();
        }

        // 启动 com.example.dex_demo.MainActivity2 组件
        if (clazz != null) {
    
    
            context.startActivity(new Intent(context, clazz));
        } 
    }

执行结果 :

2021-12-12 01:02:01.431 25158-25158/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.classloader_demo, PID: 25158
    java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{
    
    com.example.classloader_demo/com.example.dex_demo.MainActivity2}: java.lang.ClassNotFoundException: Didn't find class "com.example.dex_demo.MainActivity2" on path: DexPathList[[zip file "/data/app/com.example.classloader_demo-sAY0kit-c9kqTzgMRXYoBA==/base.apk"],nativeLibraryDirectories=[/data/app/com.example.classloader_demo-sAY0kit-c9kqTzgMRXYoBA==/lib/arm64, /system/lib64]]
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2881)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3086)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6718)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
     Caused by: java.lang.ClassNotFoundException: Didn't find class "com.example.dex_demo.MainActivity2" on path: DexPathList[[zip file "/data/app/com.example.classloader_demo-sAY0kit-c9kqTzgMRXYoBA==/base.apk"],nativeLibraryDirectories=[/data/app/com.example.classloader_demo-sAY0kit-c9kqTzgMRXYoBA==/lib/arm64, /system/lib64]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:69)
        at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:45)
        at android.app.Instrumentation.newActivity(Instrumentation.java:1215)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2869)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3086) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:193) 
        at android.app.ActivityThread.main(ActivityThread.java:6718) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/han1202012/article/details/121881212
今日推荐