Android 逆向启动 DEX 字节码中的 Activity 组件 ( DEX 文件准备 | 拷贝资源目录下的文件到内置存储区 | 配置清单文件 | 启动 DEX 文件中的组件 | 执行结果 )(代
Posted 韩曙亮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 ComponentInfocom.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)
以上是关于Android 逆向启动 DEX 字节码中的 Activity 组件 ( DEX 文件准备 | 拷贝资源目录下的文件到内置存储区 | 配置清单文件 | 启动 DEX 文件中的组件 | 执行结果 )(代的主要内容,如果未能解决你的问题,请参考以下文章
Android 逆向启动 DEX 字节码中的 Activity 组件 ( 使用 DexClassLoader 获取组件类失败 | 失败原因分析 | 自定义类加载器没有加载组件类的权限 )
Android 逆向启动 DEX 字节码中的 Activity 组件 ( DEX 文件准备 | 拷贝资源目录下的文件到内置存储区 | 配置清单文件 | 启动 DEX 文件中的组件 | 执行结果 )(代
Android 逆向启动 DEX 字节码中的 Activity 组件 ( DEX 文件准备 | 拷贝资源目录下的文件到内置存储区 | 配置清单文件 | 启动 DEX 文件中的组件 | 执行结果 )(代
Android 逆向类加载器 ClassLoader ( 使用 DexClassLoader 动态加载字节码文件 | 拷贝 DEX 文件到内置存储 | 加载并执行 DEX 字节码文件 )
Android 逆向类加载器 ClassLoader ( 使用 DexClassLoader 动态加载字节码文件 | 准备 DEX 字节码文件 )
Android 逆向ART 函数抽取加壳 ② ( 禁用 dex2oat 简介 | TurboDex 中禁用 dex2oat 参考示例 )