是否可以通过使用Java Reflection从注入的DEX中获取app的类对象?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了是否可以通过使用Java Reflection从注入的DEX中获取app的类对象?相关的知识,希望对你有一定的参考价值。
我开始学习Java,我在我的android设备上安装了一个应用程序,这个应用程序只有一个MainActivity(com.example.myapplication.MainActivity)。这个app只有一个MainActivity(com.example.myapplication.MainActivity)。在MainActivity里面有一个public(doSomething1)和一个private(doSomething2)方法。假设我没有应用程序的源文件。我要做的是通过使用Java Reflection从另一个应用程序(DEX)调用这些方法。下面是执行运行时Dex注入的代码。
JNIEnv* (*getJNIEnv)();
/**
* Inject the DEX file and execute the method.
* @param dexPath: The dex file to inject
* @param dexOptDir: Cache path
* @param className: Class name to be executed after injection
* @param methodName: Method name to execute
* @param argc: number of arguments
* @param argv: arguments
* @return
*/
int invoke_dex_method(const char* dexPath, const char* dexOptDir, const char* className, const char* methodName, int argc, char *argv[])
LOGD("dexPath = %s, dexOptDir = %s, className = %s, methodName = %s\n", dexPath, dexOptDir, className, methodName);
// Acquisition of JNIEnv
void* handle = dlopen("/system/lib/libandroid_runtime.so", RTLD_NOW);
LOGD("dlopen = %x, %s\n", handle, strerror(errno));
getJNIEnv = dlsym(handle, "_ZN7android14AndroidRuntime9getJNIEnvEv");
LOGD("dlsym = %x, %s\n", getJNIEnv, strerror(errno));
JNIEnv* env = getJNIEnv();
LOGD("JNIEnv = %x\n", env);
// Call getSystemClassLoader of ClassLoader to get ClassLoader of current process
jclass classloaderClass = (*env)->FindClass(env,"java/lang/ClassLoader");
jmethodID getsysloaderMethod = (*env)->GetStaticMethodID(env,classloaderClass, "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
jobject loader = (*env)->CallStaticObjectMethod(env, classloaderClass, getsysloaderMethod);
LOGD("loader = %x\n", loader);
// Read the dex file with DexClassLoader for processing with the current ClassLoader
jstring dexpath = (*env)->NewStringUTF(env, dexPath);
jstring dex_odex_path = (*env)->NewStringUTF(env,dexOptDir);
jclass dexLoaderClass = (*env)->FindClass(env,"dalvik/system/DexClassLoader");
jmethodID initDexLoaderMethod = (*env)->GetMethodID(env, dexLoaderClass, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V");
jobject dexLoader = (*env)->NewObject(env, dexLoaderClass, initDexLoaderMethod,dexpath,dex_odex_path,NULL,loader);
LOGD("dexLoader = %x\n", dexLoader);
// Load code to execute using DexClassLoader
jmethodID findclassMethod = (*env)->GetMethodID(env,dexLoaderClass,"findClass","(Ljava/lang/String;)Ljava/lang/Class;");
jstring javaClassName = (*env)->NewStringUTF(env,className);
jclass javaClientClass = (*env)->CallObjectMethod(env,dexLoader,findclassMethod,javaClassName);
if (!javaClientClass)
LOGD("Failed to load target class %s\n", className);
printf("Failed to load target class %s\n", className);
return -1;
// Get the method to inject
jmethodID start_inject_method = (*env)->GetStaticMethodID(env, javaClientClass, methodName, "()V");
if (!start_inject_method)
LOGD("Failed to load target method %s\n", methodName);
printf("Failed to load target method %s\n", methodName);
return -1;
// Execute method (this method must be a public static void method)
(*env)->CallStaticVoidMethod(env,javaClientClass,start_inject_method);
return 0;
上面的代码工作得很好,没有任何问题,方法(第4个param)被调用了。下面是Dex文件中Java类的代码。
public class HookTool
public static final String TAG = "INJECT";
public static void dexInject() throws ClassNotFoundException, IllegalAccessException
Log.d(TAG, "This is dex code. Start hooking process in Java world.");
try
Class<?> activityClass = Class.forName("com.example.myapplication.MainActivity");
Method method2 = activityClass.getMethod("doSomething1");
Method method1 = activityClass.getDeclaredMethod("doSomething2");
catch (ClassNotFoundException | NoSuchMethodException e)
e.printStackTrace();
从上面的代码中我没有得到预期的结果。下面是打印的logcat结果。
D/INJECT (15393): This is dex code. Start hooking process in Java world.
W/System.err(15393): java.lang.ClassNotFoundException: com.example.myapplication.MainActivity
W/System.err(15393): at java.lang.Class.classForName(Native Method)
W/System.err(15393): at java.lang.Class.forName(Class.java:309)
W/System.err(15393): at java.lang.Class.forName(Class.java:273)
W/System.err(15393): at net.cimadai.hookerApp.HookTool.dexInject(HookTool.java:43)
W/System.err(15393): at android.os.MessageQueue.nativePollOnce(Native Method)
W/System.err(15393): at android.os.MessageQueue.next(MessageQueue.java:143)
W/System.err(15393): at android.os.Looper.loop(Looper.java:122)
W/System.err(15393): at android.app.ActivityThread.main(ActivityThread.java:5254)
W/System.err(15393): at java.lang.reflect.Method.invoke(Native Method)
W/System.err(15393): at java.lang.reflect.Method.invoke(Method.java:372)
W/System.err(15393): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
W/System.err(15393): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
W/System.err(15393): Caused by: java.lang.ClassNotFoundException: Didn't find class "com.example.myapplication.MainActivity" on path: DexPathList[[zip file "/data/local/tmp/app-debug.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
W/System.err(15393): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
W/System.err(15393): at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
W/System.err(15393): at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
W/System.err(15393): ... 12 more
W/System.err(15393): Suppressed: java.lang.ClassNotFoundException: Didn't find class "com.example.myapplication.MainActivity" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
W/System.err(15393): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
W/System.err(15393): at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
W/System.err(15393): at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
W/System.err(15393): ... 13 more
W/System.err(15393): Suppressed: java.lang.ClassNotFoundException: com.example.myapplication.MainActivityW/System.err(15393): at java.lang.Class.classForName(Native Method)
W/System.err(15393): at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
W/System.err(15393): at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
W/System.err(15393): at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
W/System.err(15393): ... 14 more
W/System.err(15393): Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available
所以问题是
- 是否可以通过使用Java Reflection从另一个应用中调用方法?
- 如果不可以,有什么方法可以让这个工作顺利进行?
你能不能有人给我解释一下?
先谢谢你
答案
我找到了dex注入后获得顶级活动的方法。下面是代码。
public static Activity getTopActivity()
Activity topActivity = null;
try
@SuppressLint("PrivateApi") Class activityThreadClass = Class.forName("android.app.ActivityThread");
@SuppressLint("DiscouragedPrivateApi") Method getATMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");
Field activitiesField = activityThreadClass.getDeclaredField("mActivities");
Object activityThread = getATMethod.invoke(null);
activitiesField.setAccessible(true);
Object activityClientRecord;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
ArrayMap activities = (ArrayMap) activitiesField.get(activityThread);
activityClientRecord = activities.valueAt(0);
else
HashMap activities = (HashMap) activitiesField.get(activityThread);
activityClientRecord = activities.values();
@SuppressLint("PrivateApi") Class activityClientRecordClass = Class.forName("android.app.ActivityThread$ActivityClientRecord");
Field activityField = activityClientRecordClass.getDeclaredField("activity");
activityField.setAccessible(true);
topActivity = (Activity) activityField.get(activityClientRecord);
catch (ClassNotFoundException e)
e.printStackTrace();
catch (NoSuchMethodException e)
e.printStackTrace();
catch (InvocationTargetException e)
e.printStackTrace();
catch (IllegalAccessException e)
e.printStackTrace();
catch (NoSuchFieldException e)
e.printStackTrace();
return topActivity;
上面的代码会给你最顶级的活动的实例。
以上是关于是否可以通过使用Java Reflection从注入的DEX中获取app的类对象?的主要内容,如果未能解决你的问题,请参考以下文章