From d2dd84640aa6a064ae23dde9bb187e2a1cf690e2 Mon Sep 17 00:00:00 2001 From: canyie Date: Mon, 25 Jan 2021 15:46:24 +0800 Subject: [PATCH] Load XResources's dex data from memory --- .../main/java/top/canyie/dreamland/Main.java | 25 ++++++++++++++++--- .../canyie/dreamland/utils/RuntimeUtils.java | 7 +++--- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/top/canyie/dreamland/Main.java b/app/src/main/java/top/canyie/dreamland/Main.java index bbc58c3..927b100 100644 --- a/app/src/main/java/top/canyie/dreamland/Main.java +++ b/app/src/main/java/top/canyie/dreamland/Main.java @@ -19,6 +19,8 @@ import androidx.annotation.Keep; +import dalvik.system.InMemoryDexClassLoader; +import dalvik.system.PathClassLoader; import de.robv.android.xposed.DexCreator; import de.robv.android.xposed.XposedBridge; import top.canyie.dreamland.core.Dreamland; @@ -35,6 +37,7 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; +import java.nio.ByteBuffer; import mirror.android.app.ActivityThread; import mirror.android.os.ServiceManager; @@ -140,10 +143,11 @@ public static int init() { return 1; } + @SuppressLint("NewApi") private static void initXResources(ClassLoader myCL) throws Exception { Resources res = Resources.getSystem(); - String dexForXResources = ensureSuperDexFor("XResources", res.getClass(), Resources.class); + Class resClass = res.getClass(); Class taClass = TypedArray.class; try { TypedArray ta = res.obtainTypedArray(res.getIdentifier("preloaded_drawables", "array", "android")); @@ -153,10 +157,25 @@ private static void initXResources(ClassLoader myCL) throws Exception { XposedBridge.log(e); } - String dexForXTypedArray = ensureSuperDexFor("XTypedArray", taClass, TypedArray.class); + ClassLoader dummy; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + // Load dex from memory to prevent some detections + RuntimeUtils.makeExtendable(resClass); + RuntimeUtils.makeExtendable(taClass); + ByteBuffer dexForXResources = DexCreator.create("XResources", resClass); + ByteBuffer dexForXTypedArray = DexCreator.create("XTypedArray", taClass); + ByteBuffer[] buffers = new ByteBuffer[] { + dexForXResources, dexForXTypedArray + }; + dummy = new InMemoryDexClassLoader(buffers, myCL.getParent()); + } else { + String dexForXResources = ensureSuperDexFor("XResources", resClass, Resources.class); + String dexForXTypedArray = ensureSuperDexFor("XTypedArray", taClass, TypedArray.class); + dummy = new PathClassLoader(dexForXResources + File.pathSeparator + dexForXTypedArray, myCL.getParent()); + } // Inject a ClassLoader for the created classes as parent of XposedBridge's ClassLoader. - RuntimeUtils.injectDex(myCL, dexForXResources + File.pathSeparator + dexForXTypedArray); + RuntimeUtils.setParent(myCL, dummy); // native initialize resources hook. // this must be executed after XResourcesSuperClass is created, diff --git a/app/src/main/java/top/canyie/dreamland/utils/RuntimeUtils.java b/app/src/main/java/top/canyie/dreamland/utils/RuntimeUtils.java index f101f5b..79df92e 100644 --- a/app/src/main/java/top/canyie/dreamland/utils/RuntimeUtils.java +++ b/app/src/main/java/top/canyie/dreamland/utils/RuntimeUtils.java @@ -3,7 +3,7 @@ import androidx.annotation.NonNull; import java.lang.reflect.Modifier; -import dalvik.system.PathClassLoader; + import top.canyie.dreamland.utils.reflect.Reflection; /** @@ -26,8 +26,7 @@ public static void makeExtendable(Class c) { } } - public static void injectDex(@NonNull ClassLoader target, @NonNull String path) { - PathClassLoader dummy = new PathClassLoader(path, target.getParent()); - parent.setValue(target, dummy); + public static void setParent(@NonNull ClassLoader target, @NonNull ClassLoader newParent) { + parent.setValue(target, newParent); } }