From c44086bd0b2b8df927154dcc2d57bba16aa3af62 Mon Sep 17 00:00:00 2001 From: solohsu Date: Tue, 12 Mar 2019 16:47:25 +0800 Subject: [PATCH] Fix IncompatibleClassChangeError when invoking original method --- .../com/elderdrivers/riru/xposed/Main.java | 4 +++- .../riru/xposed/dexmaker/HookerDexMaker.java | 5 +++++ Core/jni/main/java_hook/java_hook.cpp | 19 +++++++++++++++++-- Core/jni/main/yahfa/HookMain.c | 5 ++++- Core/jni/main/yahfa/HookMain.h | 2 ++ 5 files changed, 31 insertions(+), 4 deletions(-) diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java index 0ac415f4..2d535039 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java @@ -10,6 +10,7 @@ import com.elderdrivers.riru.xposed.proxy.yahfa.BlackWhiteListProxy; import com.elderdrivers.riru.xposed.proxy.yahfa.NormalProxy; import com.elderdrivers.riru.xposed.util.Utils; +import java.lang.reflect.Member; import java.lang.reflect.Method; import java.util.Arrays; @@ -19,7 +20,6 @@ public class Main implements KeepAll { public static String appDataDir = ""; public static String niceName = ""; public static String appProcessName = ""; - public static long closedFdTable = 0; private static String forkAndSpecializePramsStr = ""; private static String forkSystemServerPramsStr = ""; @@ -105,6 +105,8 @@ public class Main implements KeepAll { public static native boolean backupAndHookNative(Object target, Method hook, Method backup); + public static native void setMethodNonCompilable(Object member); + public static native void ensureMethodCached(Method hook, Method backup); // JNI.ToReflectedMethod() could return either Method or Constructor diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/HookerDexMaker.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/HookerDexMaker.java index 163ca26a..7b2bcb60 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/HookerDexMaker.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/dexmaker/HookerDexMaker.java @@ -1,7 +1,10 @@ package com.elderdrivers.riru.xposed.dexmaker; +import android.annotation.TargetApi; +import android.os.Build; import android.text.TextUtils; +import com.elderdrivers.riru.xposed.Main; import com.elderdrivers.riru.xposed.core.HookMain; import java.io.File; @@ -178,6 +181,7 @@ public class HookerDexMaker { doMake(); } + @TargetApi(Build.VERSION_CODES.O) private void doMake() throws Exception { mDexMaker = new DexMaker(); // Generate a Hooker class. @@ -208,6 +212,7 @@ public class HookerDexMaker { mHookMethod = mHookClass.getMethod(METHOD_NAME_HOOK, mActualParameterTypes); mBackupMethod = mHookClass.getMethod(METHOD_NAME_BACKUP, mActualParameterTypes); mCallBackupMethod = mHookClass.getMethod(METHOD_NAME_CALL_BACKUP, mActualParameterTypes); + Main.setMethodNonCompilable(mCallBackupMethod); HookMain.backupAndHook(mMember, mHookMethod, mBackupMethod); } diff --git a/Core/jni/main/java_hook/java_hook.cpp b/Core/jni/main/java_hook/java_hook.cpp index 8841acaa..889a2a17 100644 --- a/Core/jni/main/java_hook/java_hook.cpp +++ b/Core/jni/main/java_hook/java_hook.cpp @@ -59,6 +59,19 @@ int waitForGcToComplete(JNIEnv *, jclass, jlong thread) { return gcType; } +void setMethodNonCompilable(JNIEnv *env, jclass, jobject member) { + if (!member) { + LOGE("setNonCompilableNative: member is null"); + return; + } + void *artMethod = env->FromReflectedMethod(member); + if (!artMethod) { + LOGE("setNonCompilableNative: artMethod is null"); + return; + } + setNonCompilable(artMethod); +} + static JNINativeMethod hookMethods[] = { { "init", @@ -70,6 +83,9 @@ static JNINativeMethod hookMethods[] = { "(Ljava/lang/Object;Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;)Z", (void *) Java_lab_galaxy_yahfa_HookMain_backupAndHookNative }, + { + "setMethodNonCompilable", "(Ljava/lang/Object;)V", (void *) setMethodNonCompilable + }, { "findMethodNative", "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;", @@ -116,7 +132,6 @@ void loadDexAndInit(JNIEnv *env, const char *dexPath) { if (isInited) { return; } -// install_inline_hooks(); jclass clzClassLoader = env->FindClass("java/lang/ClassLoader"); LOGD("java/lang/ClassLoader: %p", clzClassLoader); jmethodID mdgetSystemClassLoader = env->GetStaticMethodID(clzClassLoader, @@ -147,7 +162,7 @@ void loadDexAndInit(JNIEnv *env, const char *dexPath) { jclass entry_class = findClassFromLoader(env, myClassLoader, ENTRY_CLASS_NAME); if (NULL != entry_class) { LOGD("HookEntry Class %p", entry_class); - env->RegisterNatives(entry_class, hookMethods, 14); + env->RegisterNatives(entry_class, hookMethods, 15); isInited = true; LOGD("RegisterNatives succeed for HookEntry."); } else { diff --git a/Core/jni/main/yahfa/HookMain.c b/Core/jni/main/yahfa/HookMain.c index 9c65e053..ac317049 100644 --- a/Core/jni/main/yahfa/HookMain.c +++ b/Core/jni/main/yahfa/HookMain.c @@ -113,7 +113,10 @@ void Java_lab_galaxy_yahfa_HookMain_init(JNIEnv *env, jclass clazz, jint sdkVers setupTrampoline(); } -static void setNonCompilable(void *method) { +void setNonCompilable(void *method) { + if (SDKVersion < ANDROID_N) { + return; + } int access_flags = read32((char *) method + OFFSET_access_flags_in_ArtMethod); LOGI("setNonCompilable: access flags is 0x%x", access_flags); access_flags |= kAccCompileDontBother; diff --git a/Core/jni/main/yahfa/HookMain.h b/Core/jni/main/yahfa/HookMain.h index 5768d79b..2aff8bee 100644 --- a/Core/jni/main/yahfa/HookMain.h +++ b/Core/jni/main/yahfa/HookMain.h @@ -16,6 +16,8 @@ void Java_lab_galaxy_yahfa_HookMain_ensureMethodCached(JNIEnv *env, jclass clazz jobject hook, jobject backup); +void setNonCompilable(void *method); + static void* getResolvedMethodsAddr(JNIEnv*, jobject); #endif // HOOK_MAIN_H \ No newline at end of file