I started learning Java and I have an app installed on my Android device. The app simply has a MainActivity(com.example.myapplication.MainActivity) only. Inside MainActivity there are a public(doSomething1) and a private(doSomething2) methods. Let's assume that I don't have the source files of the app. What I am going to do is to call those methods from another app(DEX) by using Java Reflection. Here is the code of performing runtime Dex injection.
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;
}
The above code works well without any problem and the method(4th param) got called. Here is the code of Java class in Dex file.
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();
}
}
}
I am not getting the expected result from the above code. Here is the logcat result printed.
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
So questions are
- Is it possible to invoke method in an app from another app by using Java Reflection?
- If not, what is the approach to getting this work?
Could you someone please explain to me?
Thank you in advance
Aucun commentaire:
Enregistrer un commentaire