From c76c6d3fcabd4afc5f12748ccf5ccff8584b08fa Mon Sep 17 00:00:00 2001 From: LoveSy Date: Fri, 13 Nov 2020 21:09:32 +0800 Subject: [PATCH] Better Hidden --- dalvikdx/.gitignore | 1 + dalvikdx/build.gradle | 34 ++-- dexmaker/.gitignore | 3 +- dexmaker/build.gradle | 34 ++-- edxp-common/build.gradle | 2 +- edxp-common/libs/framework-stub.jar | Bin 0 -> 261 bytes .../edxp/_hooker/impl/OneplusWorkaround.java | 36 ----- .../yahfa/OnePlusWorkAroundHooker.java | 38 ----- .../riru/edxp/config/BaseEdxpConfig.java | 3 + .../riru/edxp/config/ConfigManager.java | 2 + .../riru/edxp/core/BaseEdxpImpl.java | 17 +- .../elderdrivers/riru/edxp/core/EdxpImpl.java | 7 +- .../com/elderdrivers/riru/edxp/core/Main.java | 119 +++++--------- .../entry/yahfa/AppBootstrapHookInfo.java | 2 - .../entry/yahfa/SysBootstrapHookInfo.java | 2 - .../edxp/entry/yahfa/WorkAroundHookInfo.java | 10 -- .../riru/edxp/proxy/BaseRouter.java | 41 +---- .../riru/edxp/proxy/BlackWhiteListProxy.java | 139 ---------------- .../riru/edxp/proxy/NormalProxy.java | 29 +--- .../elderdrivers/riru/edxp/proxy/Router.java | 10 +- edxp-core/build.gradle | 49 +++++- .../src/main/cpp/main/include/JNIHelper.h | 23 ++- edxp-core/src/main/cpp/main/include/config.h | 51 +++--- edxp-core/src/main/cpp/main/include/logging.h | 2 +- edxp-core/src/main/cpp/main/include/utils.h | 15 ++ .../src/main/cpp/main/src/config_manager.cpp | 78 +++------ .../src/main/cpp/main/src/config_manager.h | 57 ++++--- .../src/main/cpp/main/src/edxp_context.cpp | 151 ++++++++---------- .../src/main/cpp/main/src/edxp_context.h | 50 ++++-- .../cpp/main/src/jni/edxp_config_manager.cpp | 14 +- edxp-sandhook/build.gradle | 19 +++ .../hooker/OnePlusWorkAroundHooker.java | 53 ------ edxp-whale/build.gradle | 19 +++ edxp-yahfa/build.gradle | 19 +++ edxp-yahfa/proguard-rules.pro | 2 +- .../riru/edxp/yahfa/core/YahfaEdxpImpl.java | 6 - gradle/wrapper/gradle-wrapper.properties | 4 +- .../riru/edxp/config/EdxpConfig.java | 2 + .../de/robv/android/xposed/XposedInit.java | 28 +--- 39 files changed, 458 insertions(+), 713 deletions(-) create mode 100644 edxp-common/libs/framework-stub.jar delete mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/OneplusWorkaround.java delete mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/OnePlusWorkAroundHooker.java delete mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/WorkAroundHookInfo.java delete mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java create mode 100644 edxp-core/src/main/cpp/main/include/utils.h delete mode 100644 edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/OnePlusWorkAroundHooker.java diff --git a/dalvikdx/.gitignore b/dalvikdx/.gitignore index 796b96d1c..8b8c3dc1b 100644 --- a/dalvikdx/.gitignore +++ b/dalvikdx/.gitignore @@ -1 +1,2 @@ /build +dex diff --git a/dalvikdx/build.gradle b/dalvikdx/build.gradle index c31ce47ac..a8b47c1ef 100644 --- a/dalvikdx/build.gradle +++ b/dalvikdx/build.gradle @@ -23,21 +23,31 @@ task findDx { } } -task dexInJar(type: Jar) { +task makeDex(type: Exec) { dependsOn jar dependsOn findDx - doFirst { - exec { - workingDir jar.destinationDir - if (OperatingSystem.current().isWindows()){ - executable "dx.bat" - args "--dex", "--output", "classes.dex", "${jar.archiveName}" - } else { - executable "bash" - args rootProject.ext.dxPath.trim(), "--dex", "--output", "classes.dex", "${jar.archiveName}" - } - } + def dexName = "classes.dex" + workingDir jar.destinationDir + if (OperatingSystem.current().isWindows()) { + executable "dx.bat" + args "--dex", "--output", dexName, "${jar.archiveName}" + } else { + executable "bash" + args rootProject.ext.dxPath.trim(), "--dex", "--output", dexName, "${jar.archiveName}" } +} + +task dex(type: Copy) { + dependsOn makeDex + from (jar.destinationDir) { + include "classes.dex" + rename "classes.dex", "eddalvikdx.dex" + } + destinationDir new File(projectDir, "dex") +} + +task dexInJar(type: Jar) { + dependsOn makeDex from "${jar.destinationDir}/classes.dex" destinationDir jar.destinationDir baseName "eddalvikdx" diff --git a/dexmaker/.gitignore b/dexmaker/.gitignore index 42afabfd2..8b8c3dc1b 100644 --- a/dexmaker/.gitignore +++ b/dexmaker/.gitignore @@ -1 +1,2 @@ -/build \ No newline at end of file +/build +dex diff --git a/dexmaker/build.gradle b/dexmaker/build.gradle index 9d4bc9205..7e615282e 100644 --- a/dexmaker/build.gradle +++ b/dexmaker/build.gradle @@ -14,20 +14,30 @@ dependencies { compileOnly project(':dalvikdx') } -task dexInJar(type: Jar) { +task makeDex(type: Exec) { dependsOn jar - doFirst { - exec { - workingDir jar.destinationDir - if (OperatingSystem.current().isWindows()){ - executable "dx.bat" - args "--dex", "--output", "classes.dex", "${jar.archiveName}" - } else { - executable "bash" - args rootProject.ext.dxPath.trim(), "--dex", "--output", "classes.dex", "${jar.archiveName}" - } - } + def dexName = "classes.dex" + workingDir jar.destinationDir + if (OperatingSystem.current().isWindows()) { + executable "dx.bat" + args "--dex", "--output", dexName, "${jar.archiveName}" + } else { + executable "bash" + args rootProject.ext.dxPath.trim(), "--dex", "--output", dexName, "${jar.archiveName}" + } +} + +task dex(type: Copy) { + dependsOn makeDex + from (jar.destinationDir) { + include "classes.dex" + rename "classes.dex", "eddexmaker.dex" } + destinationDir new File(projectDir, "dex") +} + +task dexInJar(type: Jar) { + dependsOn makeDex from "${jar.destinationDir}/classes.dex" destinationDir jar.destinationDir baseName "eddexmaker" diff --git a/edxp-common/build.gradle b/edxp-common/build.gradle index f501d3551..3b139a4dc 100644 --- a/edxp-common/build.gradle +++ b/edxp-common/build.gradle @@ -23,7 +23,7 @@ dependencies { compileOnly project(':hiddenapi-stubs') api project(':xposed-bridge') compileOnly project(':dexmaker') - api "androidx.annotation:annotation:1.1.0-rc01" + compileOnly 'com.android.support:support-annotations:28.0.0' } diff --git a/edxp-common/libs/framework-stub.jar b/edxp-common/libs/framework-stub.jar new file mode 100644 index 0000000000000000000000000000000000000000..1c5002cc6f184961bdf1c14ad47750f3a453de7e GIT binary patch literal 261 zcmWIWW@h1HVBp|j5LlKQ$N&UPAOZ+Df!NnI#8KDN&rP41Apk|;rh2A#(m(~0KrDi+ z(AUw=)6F$FM9 edxpImplRef = new AtomicReference<>(null); static { @@ -37,67 +30,37 @@ public static void forkAndSpecializePre(int uid, int gid, int[] gids, int debugF String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir) { - final EdxpImpl edxp = getEdxpImpl(); - if (edxp == null || !edxp.isInitialized()) { - return; - } - if (logEnabled) { - forkAndSpecializePramsStr = String.format( - "Zygote#forkAndSpecialize(%d, %d, %s, %d, %s, %d, %s, %s, %s, %s, %s, %s, %s)", - uid, gid, Arrays.toString(gids), debugFlags, Arrays.toString(rlimits), - mountExternal, seInfo, niceName, Arrays.toString(fdsToClose), - Arrays.toString(fdsToIgnore), startChildZygote, instructionSet, appDataDir); - } - - if (ConfigManager.isBlackWhiteListEnabled()) { - edxp.getBlackWhiteListProxy().forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits, - mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, - instructionSet, appDataDir); - } else { - edxp.getNormalProxy().forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits, mountExternal, - seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, instructionSet, - appDataDir); - } + // won't be loaded +// final EdxpImpl edxp = getEdxpImpl(); +// if (edxp == null || !edxp.isInitialized()) { +// return; +// } +// +// if (ConfigManager.isBlackWhiteListEnabled()) { +// edxp.getBlackWhiteListProxy().forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits, +// mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, +// instructionSet, appDataDir); +// } else { +// edxp.getNormalProxy().forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits, mountExternal, +// seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, instructionSet, +// appDataDir); +// } } public static void forkAndSpecializePost(int pid, String appDataDir, String niceName) { final EdxpImpl edxp = getEdxpImpl(); if (edxp == null || !edxp.isInitialized()) { + Utils.logE("Not started up"); return; } if (pid == 0) { - if (logEnabled) { - Utils.logI(forkAndSpecializePramsStr + " = " + Process.myPid()); - } - if (ConfigManager.isBlackWhiteListEnabled()) { - edxp.getBlackWhiteListProxy().forkAndSpecializePost(pid, appDataDir, niceName); - } else { - edxp.getNormalProxy().forkAndSpecializePost(pid, appDataDir, niceName); - } - } else { - // in zygote process, res is child zygote pid - // don't print log here, see https://github.com/RikkaApps/Riru/blob/77adfd6a4a6a81bfd20569c910bc4854f2f84f5e/riru-core/jni/main/jni_native_method.cpp#L55-L66 + edxp.getNormalProxy().forkAndSpecializePost(pid, appDataDir, niceName); } } public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) { - final EdxpImpl edxp = getEdxpImpl(); - if (edxp == null || !edxp.isInitialized()) { - return; - } - if (logEnabled) { - forkSystemServerPramsStr = String.format("Zygote#forkSystemServer(%d, %d, %s, %d, %s, %d, %d)", - uid, gid, Arrays.toString(gids), debugFlags, Arrays.toString(rlimits), - permittedCapabilities, effectiveCapabilities); - } - if (ConfigManager.isBlackWhiteListEnabled()) { - edxp.getBlackWhiteListProxy().forkSystemServerPre(uid, gid, gids, debugFlags, rlimits, - permittedCapabilities, effectiveCapabilities); - } else { - edxp.getNormalProxy().forkSystemServerPre(uid, gid, gids, debugFlags, rlimits, - permittedCapabilities, effectiveCapabilities); - } + // Won't load } public static void forkSystemServerPost(int pid) { @@ -106,17 +69,7 @@ public static void forkSystemServerPost(int pid) { return; } if (pid == 0) { - if (logEnabled) { - Utils.logI(forkSystemServerPramsStr + " = " + Process.myPid()); - } - if (ConfigManager.isBlackWhiteListEnabled()) { - edxp.getBlackWhiteListProxy().forkSystemServerPost(pid); - } else { - edxp.getNormalProxy().forkSystemServerPost(pid); - } - } else { - // in zygote process, res is child zygote pid - // don't print log here, see https://github.com/RikkaApps/Riru/blob/77adfd6a4a6a81bfd20569c910bc4854f2f84f5e/riru-core/jni/main/jni_native_method.cpp#L55-L66 + edxp.getNormalProxy().forkSystemServerPost(pid); } } @@ -134,19 +87,21 @@ public static synchronized int getEdxpVariant() { } private static void loadEdxpImpls() { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - Iterator iterator = ServiceLoader.load( - EdxpImpl.class, Main.class.getClassLoader()).iterator(); - try { - while (iterator.hasNext()) { - iterator.next(); - } - } catch (Throwable t) { - Utils.logE("error when loadEdxpImpls", t); - } - return null; - } - }); + // We don't have Manifest now, so we have to load manually. + try { + Class.forName("com.elderdrivers.riru.edxp.sandhook.core.SandHookEdxpImpl"); + }catch(Throwable ignored) { + Utils.logD("not using sandhook"); + } + try { + Class.forName("com.elderdrivers.riru.edxp.yahfa.core.YahfaEdxpImpl"); + }catch(Throwable ignored) { + Utils.logD("not using yahfa"); + } + try { + Class.forName("com.elderdrivers.riru.edxp.whale.core.WhaleEdxpImpl"); + }catch(Throwable ignored) { + Utils.logD("not found whale"); + } } } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/AppBootstrapHookInfo.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/AppBootstrapHookInfo.java index c76b47afc..8fb6d7598 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/AppBootstrapHookInfo.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/AppBootstrapHookInfo.java @@ -3,12 +3,10 @@ import com.elderdrivers.riru.common.KeepMembers; import com.elderdrivers.riru.edxp._hooker.yahfa.HandleBindAppHooker; import com.elderdrivers.riru.edxp._hooker.yahfa.LoadedApkConstructorHooker; -import com.elderdrivers.riru.edxp._hooker.yahfa.OnePlusWorkAroundHooker; public class AppBootstrapHookInfo implements KeepMembers { public static String[] hookItemNames = { HandleBindAppHooker.class.getName(), LoadedApkConstructorHooker.class.getName(), - OnePlusWorkAroundHooker.class.getName() }; } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/SysBootstrapHookInfo.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/SysBootstrapHookInfo.java index 68656961d..fb50926ca 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/SysBootstrapHookInfo.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/SysBootstrapHookInfo.java @@ -3,7 +3,6 @@ import com.elderdrivers.riru.common.KeepMembers; import com.elderdrivers.riru.edxp._hooker.yahfa.HandleBindAppHooker; import com.elderdrivers.riru.edxp._hooker.yahfa.LoadedApkConstructorHooker; -import com.elderdrivers.riru.edxp._hooker.yahfa.OnePlusWorkAroundHooker; import com.elderdrivers.riru.edxp._hooker.yahfa.SystemMainHooker; public class SysBootstrapHookInfo implements KeepMembers { @@ -11,6 +10,5 @@ public class SysBootstrapHookInfo implements KeepMembers { HandleBindAppHooker.class.getName(), SystemMainHooker.class.getName(), LoadedApkConstructorHooker.class.getName(), - OnePlusWorkAroundHooker.class.getName() }; } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/WorkAroundHookInfo.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/WorkAroundHookInfo.java deleted file mode 100644 index ecf36e5e8..000000000 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/WorkAroundHookInfo.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.elderdrivers.riru.edxp.entry.yahfa; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp._hooker.yahfa.OnePlusWorkAroundHooker; - -public class WorkAroundHookInfo implements KeepMembers { - public static String[] hookItemNames = { - OnePlusWorkAroundHooker.class.getName() - }; -} diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BaseRouter.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BaseRouter.java index 996843e77..4c8ef5853 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BaseRouter.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BaseRouter.java @@ -7,19 +7,16 @@ import com.elderdrivers.riru.edxp._hooker.impl.HandleBindApp; import com.elderdrivers.riru.edxp._hooker.impl.LoadedApkCstr; -import com.elderdrivers.riru.edxp._hooker.impl.OneplusWorkaround; import com.elderdrivers.riru.edxp._hooker.impl.StartBootstrapServices; import com.elderdrivers.riru.edxp._hooker.impl.SystemMain; import com.elderdrivers.riru.edxp._hooker.yahfa.HandleBindAppHooker; import com.elderdrivers.riru.edxp._hooker.yahfa.LoadedApkConstructorHooker; -import com.elderdrivers.riru.edxp._hooker.yahfa.OnePlusWorkAroundHooker; import com.elderdrivers.riru.edxp._hooker.yahfa.StartBootstrapServicesHooker; import com.elderdrivers.riru.edxp._hooker.yahfa.SystemMainHooker; import com.elderdrivers.riru.edxp.core.yahfa.HookMain; import com.elderdrivers.riru.edxp.entry.yahfa.AppBootstrapHookInfo; import com.elderdrivers.riru.edxp.entry.yahfa.SysBootstrapHookInfo; import com.elderdrivers.riru.edxp.entry.yahfa.SysInnerHookInfo; -import com.elderdrivers.riru.edxp.entry.yahfa.WorkAroundHookInfo; import com.elderdrivers.riru.edxp.util.Utils; import com.elderdrivers.riru.edxp.util.Versions; @@ -33,14 +30,11 @@ public abstract class BaseRouter implements Router { - protected volatile boolean forkCompleted = false; - protected volatile AtomicBoolean bootstrapHooked = new AtomicBoolean(false); protected static boolean useXposedApi = false; public void initResourcesHook() { - startWorkAroundHook(); // for OnePlus devices XposedBridge.initXResources(); } @@ -49,18 +43,6 @@ public void prepare(boolean isSystem) { XposedInit.startsSystemServer = isSystem; } - public void onForkStart() { - forkCompleted = false; - } - - public void onForkFinish() { - forkCompleted = true; - } - - public boolean isForkCompleted() { - return forkCompleted; - } - public void installBootstrapHooks(boolean isSystem) { // Initialize the Xposed framework try { @@ -75,10 +57,9 @@ public void installBootstrapHooks(boolean isSystem) { } } - public void loadModulesSafely(boolean isInZygote, boolean callInitZygote) { + public void loadModulesSafely(boolean callInitZygote) { try { - // FIXME some coredomain app can't reading modules.list - XposedInit.loadModules(isInZygote, callInitZygote); + XposedInit.loadModules(callInitZygote); } catch (Exception exception) { Utils.logE("error loading module list", exception); } @@ -145,22 +126,4 @@ public void startSystemServerHook() { SysInnerHookInfo.class.getName()); } } - - @ApiSensitive(Level.LOW) - public void startWorkAroundHook() { - ClassLoader classLoader = BaseRouter.class.getClassLoader(); - if (useXposedApi) { - try { - XposedHelpers.findAndHookMethod(OnePlusWorkAroundHooker.className, - classLoader, OnePlusWorkAroundHooker.methodName, - int.class, String.class, new OneplusWorkaround()); - } catch (Throwable ignored) { - } - } else { - HookMain.doHookDefault( - BaseRouter.class.getClassLoader(), - classLoader, - WorkAroundHookInfo.class.getName()); - } - } } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java deleted file mode 100644 index 0ff1f1346..000000000 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.elderdrivers.riru.edxp.proxy; - -import android.text.TextUtils; - -import com.elderdrivers.riru.edxp.config.ConfigManager; -import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter; -import com.elderdrivers.riru.edxp.util.ProcessUtils; -import com.elderdrivers.riru.edxp.util.Utils; - -import de.robv.android.xposed.XposedBridge; - -import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix; - -/** - * 1. Non dynamic mode - * - system_server is whitelisted - * * for all child processes of main zygote - * What've been done in main zygote pre-forking system_server - * 1) non dynamic flag set (no need to reset) - * 2) boot image methods deopted (no need to redo) - * 3) startSystemServer flag set to true (need to reset) - * 4) workaround hooks installed (need to redo) - * 5) module list loaded and initZygote called (no need to redo) - * 6) close all fds (no need to redo because of 5)) - * * for all child processes of secondary zygote - * 1) do the same things pre-forking first child process - * - system_server is blacklisted: - * * for all child processes of both main zygote and secondary zygote - * 1) do the same things pre-forking first child process - * 2. Dynamic mode: - * to be continued - */ -public class BlackWhiteListProxy extends BaseProxy { - - public BlackWhiteListProxy(Router router) { - super(router); - } - - public void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags, - int[][] rlimits, int mountExternal, String seInfo, - String niceName, int[] fdsToClose, int[] fdsToIgnore, - boolean startChildZygote, String instructionSet, - String appDataDir) { - final boolean isDynamicModulesMode = ConfigManager.isDynamicModulesEnabled(); - if (isDynamicModulesMode) { - onForkPreForDynamicMode(false); - } else { - onForkPreForNonDynamicMode(false); - } - } - - public void forkAndSpecializePost(int pid, String appDataDir, String niceName) { - onForkPostCommon(false, appDataDir, niceName); - } - - public void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, - int[][] rlimits, long permittedCapabilities, - long effectiveCapabilities) { - final boolean isDynamicModulesMode = ConfigManager.isDynamicModulesEnabled(); - if (isDynamicModulesMode) { - onForkPreForDynamicMode(true); - } else { - onForkPreForNonDynamicMode(true); - } - } - - public void forkSystemServerPost(int pid) { - onForkPostCommon(true, getDataPathPrefix() + "android", "system_server"); - } - - private void onForkPreForDynamicMode(boolean isSystemServer) { - mRouter.onForkStart(); - mRouter.initResourcesHook(); - mRouter.prepare(isSystemServer); - mRouter.loadModulesSafely(true, false); - } - - /** - * Some details are different between main zygote and secondary zygote. - */ - private void onForkPreForNonDynamicMode(boolean isSystemServer) { - mRouter.onForkStart(); - mRouter.initResourcesHook(); - // set startsSystemServer flag used when loadModules - mRouter.prepare(isSystemServer); - // deoptBootMethods once for all child processes of zygote - PrebuiltMethodsDeopter.deoptBootMethods(); - // we never install bootstrap hooks here in black/white list mode except workaround hooks - // because installed hooks would be propagated to all child processes of zygote - mRouter.startWorkAroundHook(); - // loadModules once for all child processes of zygote - mRouter.loadModulesSafely(true, false); - } - - private void onForkPostCommon(boolean isSystemServer, String appDataDir, String niceName) { - ConfigManager.appDataDir = appDataDir; - ConfigManager.niceName = niceName; - final boolean isDynamicModulesMode = ConfigManager.isDynamicModulesEnabled(); - mRouter.onEnterChildProcess(); - if (!checkNeedHook(appDataDir, niceName)) { - // if is blacklisted, just stop here - mRouter.onForkFinish(); - return; - } - if (isDynamicModulesMode) { - mRouter.initResourcesHook(); - } - mRouter.prepare(isSystemServer); - PrebuiltMethodsDeopter.deoptBootMethods(); - mRouter.installBootstrapHooks(isSystemServer); - - // under dynamic modules mode, don't call initZygote when loadModule - // cuz loaded module won't has that chance to do it - if (isDynamicModulesMode) { - mRouter.loadModulesSafely(false, false); - } - // call all initZygote callbacks - XposedBridge.callInitZygotes(); - - mRouter.onForkFinish(); - } - - private boolean checkNeedHook(String appDataDir, String niceName) { - boolean needHook; - if (TextUtils.isEmpty(appDataDir)) { - Utils.logE("niceName:" + niceName + ", procName:" - + ProcessUtils.getCurrentProcessName(ConfigManager.appProcessName) + ", appDataDir is null, blacklisted!"); - needHook = false; - } else { - // FIXME some process cannot read app_data_file because of MLS, e.g. bluetooth - needHook = ConfigManager.isAppNeedHook(appDataDir); - } - if (!needHook) { - // clean up the scene - onBlackListed(); - } - return needHook; - } -} diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/NormalProxy.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/NormalProxy.java index 54b0d0521..92d262529 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/NormalProxy.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/NormalProxy.java @@ -18,8 +18,9 @@ public void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags, String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir) { - // mainly for secondary zygote - mRouter.onForkStart(); + } + + public void forkAndSpecializePost(int pid, String appDataDir, String niceName) { SELinuxHelper.initOnce(); mRouter.initResourcesHook(); // call this to ensure the flag is set to false ASAP @@ -27,18 +28,15 @@ public void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags, PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for secondary zygote // install bootstrap hooks for secondary zygote mRouter.installBootstrapHooks(false); - // only load modules for secondary zygote - mRouter.loadModulesSafely(true, true); - } - - public void forkAndSpecializePost(int pid, String appDataDir, String niceName) { // TODO consider processes without forkAndSpecializePost being called forkPostCommon(pid, false, appDataDir, niceName); } public void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) { - mRouter.onForkStart(); + } + + public void forkSystemServerPost(int pid) { SELinuxHelper.initOnce(); mRouter.initResourcesHook(); // set startsSystemServer flag used when loadModules @@ -48,13 +46,6 @@ public void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, in // in case we miss some processes not forked via forkAndSpecialize // for instance com.android.phone mRouter.installBootstrapHooks(true); - // loadModules have to be executed in zygote even isDynamicModules is false - // because if not global hooks installed in initZygote might not be - // propagated to processes not forked via forkAndSpecialize - mRouter.loadModulesSafely(true, true); - } - - public void forkSystemServerPost(int pid) { // in system_server process forkPostCommon(pid, true, getDataPathPrefix() + "android", "system_server"); @@ -66,13 +57,7 @@ private void forkPostCommon(int pid, boolean isSystem, String appDataDir, String ConfigManager.niceName = niceName; mRouter.prepare(isSystem); mRouter.onEnterChildProcess(); - // reload module list if dynamic mode is on - if (ConfigManager.isDynamicModulesEnabled()) { - // FIXME this could be error-prone because hooks installed inside old versions - // of initZygote instances of same module are not unhooked - mRouter.loadModulesSafely(false, true); - } - mRouter.onForkFinish(); + mRouter.loadModulesSafely(true); } } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/Router.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/Router.java index 1467bcf3a..63fcd31f9 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/Router.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/Router.java @@ -10,21 +10,13 @@ public interface Router { void installBootstrapHooks(boolean isSystem); - void loadModulesSafely(boolean isInZygote, boolean callInitZygote); + void loadModulesSafely(boolean callInitZygote); void startBootstrapHook(boolean isSystem); void startSystemServerHook(); - void startWorkAroundHook(); - - void onForkStart(); - - void onForkFinish(); - void onEnterChildProcess(); void injectConfig(); - - boolean isForkCompleted(); } diff --git a/edxp-core/build.gradle b/edxp-core/build.gradle index 8368c27df..e27c93217 100644 --- a/edxp-core/build.gradle +++ b/edxp-core/build.gradle @@ -78,6 +78,28 @@ android { } } +task copyDalvikdxDex { + def dexTask = tasks.getByPath(':dalvikdx:dex') + dependsOn dexTask + doLast { + copy { + from dexTask + into jar_dest_dir + } + } +} + +task copyDexmakerDex { + def dexTask = tasks.getByPath(':dexmaker:dex') + dependsOn dexTask + doLast { + copy { + from dexTask + into jar_dest_dir + } + } +} + task copyDalvikdxJar { def jarTask = tasks.getByPath(':dalvikdx:dexInJar') dependsOn jarTask @@ -125,8 +147,8 @@ afterEvaluate { def magiskModuleId = property("${backendLowered}" + "_module_id") def prepareJarsTask = task("prepareJars${backendCapped}${variantCapped}") { - dependsOn cleanTemplate, copyDalvikdxJar, copyDexmakerJar - dependsOn tasks.getByPath(":edxp-${backendLowered}:makeAndCopy${variantCapped}") + dependsOn cleanTemplate, copyDalvikdxDex, copyDexmakerDex + dependsOn tasks.getByPath(":edxp-${backendLowered}:copyDex${variantCapped}") } def prepareMagiskFilesTask = task("prepareMagiskFiles${backendCapped}${variantCapped}", type: Delete) { @@ -195,7 +217,28 @@ afterEvaluate { workingDir "${projectDir}/release" def commands = ["adb", "push", "${module_name}-${backend}-${project.version}-${variantLowered}.zip", - "/sdcard/"] + "/data/local/tmp/"] + if (is_windows) { + commandLine 'cmd', '/c', commands.join(" ") + } else { + commandLine commands + } + } + task("flash${backendCapped}${variantCapped}", type: Exec) { + dependsOn tasks.getByPath("push${backendCapped}${variantCapped}") + workingDir "${projectDir}/release" + def commands = ["adb", "shell", "su", "-c", + "magisk --install-module /data/local/tmp/${module_name}-${backend}-${project.version}-${variantLowered}.zip"] + if (is_windows) { + commandLine 'cmd', '/c', commands.join(" ") + } else { + commandLine commands + } + } + task("flashAndReboot${backendCapped}${variantCapped}", type: Exec) { + dependsOn tasks.getByPath("flash${backendCapped}${variantCapped}") + workingDir "${projectDir}/release" + def commands = ["adb", "shell", "reboot"] if (is_windows) { commandLine 'cmd', '/c', commands.join(" ") } else { diff --git a/edxp-core/src/main/cpp/main/include/JNIHelper.h b/edxp-core/src/main/cpp/main/include/JNIHelper.h index ccee86ba6..f90162e1b 100644 --- a/edxp-core/src/main/cpp/main/include/JNIHelper.h +++ b/edxp-core/src/main/cpp/main/include/JNIHelper.h @@ -4,7 +4,7 @@ #include #include "logging.h" -#define JNI_START JNIEnv *env, jclass clazz +#define JNI_START JNIEnv *env, [[maybe_unused]] jclass clazz ALWAYS_INLINE static void JNIExceptionClear(JNIEnv *env) { if (env->ExceptionCheck()) { @@ -126,8 +126,29 @@ class JUTFString { if (env_ && jstr_) env_->ReleaseStringUTFChars(jstr_, cstr_); } + JUTFString(JUTFString &&other) + : env_(std::move(other.env_)), jstr_(std::move(other.jstr_)), + cstr_(std::move(other.cstr_)) { + other.cstr_ = nullptr; + } + + JUTFString & + operator=(JUTFString &&other) { + if (&other != this) { + env_ = std::move(other.env_); + jstr_ = std::move(other.jstr_); + cstr_ = std::move(other.cstr_); + other.cstr_ = nullptr; + } + return *this; + } + private: JNIEnv *env_; jstring jstr_; const char *cstr_; + + JUTFString(const JUTFString &) = delete; + + JUTFString &operator=(const JUTFString &) = delete; }; diff --git a/edxp-core/src/main/cpp/main/include/config.h b/edxp-core/src/main/cpp/main/include/config.h index 436d180c0..e755ecf8b 100644 --- a/edxp-core/src/main/cpp/main/include/config.h +++ b/edxp-core/src/main/cpp/main/include/config.h @@ -6,6 +6,7 @@ #include #include "art/base/macros.h" #include "android_build.h" +#include "utils.h" namespace edxp { @@ -18,30 +19,32 @@ namespace edxp { # define LP_SELECT(lp32, lp64) (lp32) #endif - static constexpr auto kInjectDexPath = "/system/framework/edxp.jar:" - "/system/framework/eddalvikdx.jar:" - "/system/framework/eddexmaker.jar"; - - static constexpr auto kEntryClassName = "com.elderdrivers.riru.edxp.core.Main"; - static constexpr auto kClassLinkerClassName = "com.elderdrivers.riru.edxp.art.ClassLinker"; - static constexpr auto kSandHookClassName = "com.swift.sandhook.SandHook"; - static constexpr auto kSandHookNeverCallClassName = "com.swift.sandhook.ClassNeverCall"; - static constexpr auto kXposedBridgeClassName = "de.robv.android.xposed.XposedBridge"; - - static constexpr auto kLibArtName = "libart.so"; - static constexpr auto kLibFwkName = "libandroid_runtime.so"; - static constexpr auto kLibFwName = "libandroidfw.so"; - static constexpr auto kLibWhaleName = "libwhale.edxp.so"; - static constexpr auto kLibSandHookName = "libsandhook.edxp.so"; - static constexpr auto kLibDlName = "libdl.so"; - static constexpr auto kLibSandHookNativeName = "libsandhook-native.so"; - - static const auto kLibBasePath = std::string( - LP_SELECT("/system/lib/", - "/system/lib64/")); - static const auto kLinkerPath = std::string( - LP_SELECT("/apex/com.android.runtime/bin/linker", - "/apex/com.android.runtime/bin/linker64")); + static const auto kInjectDexPath = "/system/framework/edxp.dex:" + "/system/framework/eddalvikdx.dex:" + "/system/framework/eddexmaker.dex"_str; + + static const auto kEntryClassName = "com.elderdrivers.riru.edxp.core.Main"_str; + static const auto kClassLinkerClassName = "com.elderdrivers.riru.edxp.art.ClassLinker"; + static const auto kSandHookClassName = "com.swift.sandhook.SandHook"_str; + static const auto kSandHookNeverCallClassName = "com.swift.sandhook.ClassNeverCall"_str; + static const auto kXposedBridgeClassName = "de.robv.android.xposed.XposedBridge"_str; + + static const auto kLibArtName = "libart.so"_str; + static const auto kLibFwkName = "libandroid_runtime.so"_str; + static const auto kLibFwName = "libandroidfw.so"_str; + static const auto kLibWhaleName = "libwhale.edxp.so"_str; + static const auto kLibSandHookName = "libsandhook.edxp.so"_str; + static const auto kLibDlName = "libdl.so"_str; + static const auto kLibSandHookNativeName = "libsandhook-native.so"_str; + + static const auto kLibBasePath = + LP_SELECT("/system/lib/"_str, + "/system/lib64/"_str); + + static const auto kLinkerPath = + LP_SELECT("/apex/com.android.runtime/bin/linker"_str, + "/apex/com.android.runtime/bin/linker64"_str); + static const auto kLibDlPath = kLibBasePath + kLibDlName; static const auto kLibArtLegacyPath = kLibBasePath + kLibArtName; diff --git a/edxp-core/src/main/cpp/main/include/logging.h b/edxp-core/src/main/cpp/main/include/logging.h index 4a009af28..01e381848 100644 --- a/edxp-core/src/main/cpp/main/include/logging.h +++ b/edxp-core/src/main/cpp/main/include/logging.h @@ -17,7 +17,7 @@ #define LOGW(...) #define LOGE(...) #else -#ifdef DEBUG +#ifndef NDEBUG #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) #else #define LOGD(...) diff --git a/edxp-core/src/main/cpp/main/include/utils.h b/edxp-core/src/main/cpp/main/include/utils.h new file mode 100644 index 000000000..2222c2163 --- /dev/null +++ b/edxp-core/src/main/cpp/main/include/utils.h @@ -0,0 +1,15 @@ +// +// Created by loves on 11/13/2020. +// + +#ifndef EDXPOSED_UTILS_H +#define EDXPOSED_UTILS_H + +#include + +namespace edxp{ +inline const std::string operator ""_str(const char *str, std::size_t size) { + return {str, size}; +} +} +#endif //EDXPOSED_UTILS_H diff --git a/edxp-core/src/main/cpp/main/src/config_manager.cpp b/edxp-core/src/main/cpp/main/src/config_manager.cpp index bb3f59ba1..6c60c5def 100644 --- a/edxp-core/src/main/cpp/main/src/config_manager.cpp +++ b/edxp-core/src/main/cpp/main/src/config_manager.cpp @@ -14,8 +14,9 @@ #include #include -#include +#include #include +#include #include "art/runtime/native/native_util.h" #include "config_manager.h" @@ -27,15 +28,15 @@ namespace edxp { std::string ConfigManager::RetrieveInstallerPkgName() const { std::string data_test_path = data_path_prefix_ + kPrimaryInstallerPkgName; if (access(data_test_path.c_str(), F_OK) == 0) { - LOGI("using installer %s", kPrimaryInstallerPkgName); + LOGI("using installer %s", kPrimaryInstallerPkgName.c_str()); return kPrimaryInstallerPkgName; } data_test_path = data_path_prefix_ + kLegacyInstallerPkgName; if (access(data_test_path.c_str(), F_OK) == 0) { - LOGI("using installer %s", kLegacyInstallerPkgName); + LOGI("using installer %s", kLegacyInstallerPkgName.c_str()); return kLegacyInstallerPkgName; } - LOGE("no supported installer app found, using default: %s", kPrimaryInstallerPkgName); + LOGE("no supported installer app found, using default: %s", kPrimaryInstallerPkgName.c_str()); return kPrimaryInstallerPkgName; } @@ -135,8 +136,8 @@ namespace edxp { app_data_dir.c_str()); use_white_list = use_white_list_snapshot_; } - if (strcmp(package_name, kPrimaryInstallerPkgName) == 0 - || strcmp(package_name, kLegacyInstallerPkgName) == 0) { + if (package_name == kPrimaryInstallerPkgName + || package_name == kLegacyInstallerPkgName) { // always hook installer apps return true; } @@ -166,58 +167,27 @@ namespace edxp { } } - ALWAYS_INLINE bool ConfigManager::IsBlackWhiteListEnabled() const { - return black_white_list_enabled_; - } - - ALWAYS_INLINE bool ConfigManager::IsDynamicModulesEnabled() const { - return dynamic_modules_enabled_; - } - - ALWAYS_INLINE bool ConfigManager::IsNoModuleLogEnabled() const { - return no_module_log_enabled_; - } - - ALWAYS_INLINE bool ConfigManager::IsResourcesHookEnabled() const { - return resources_hook_enabled_; - } - - ALWAYS_INLINE bool ConfigManager::IsDeoptBootImageEnabled() const { - return deopt_boot_image_enabled_; - } - - ALWAYS_INLINE bool ConfigManager::IsHiddenAPIBypassEnabled() const { - return hidden_api_bypass_enabled_; - } - - ALWAYS_INLINE std::string ConfigManager::GetInstallerPackageName() const { - return installer_pkg_name_; - } - - ALWAYS_INLINE std::string ConfigManager::GetXposedPropPath() const { - return kXposedPropPath; - } - - ALWAYS_INLINE std::string ConfigManager::GetLibSandHookName() const { - return kLibSandHookName; - } - - ALWAYS_INLINE std::string ConfigManager::GetLibWhaleName() const { - return kLibWhaleName; - } - - ALWAYS_INLINE std::string ConfigManager::GetDataPathPrefix() const { - return data_path_prefix_; - } - - ALWAYS_INLINE std::string ConfigManager::GetConfigPath(const std::string &suffix) const { - return data_path_prefix_ + installer_pkg_name_ + "/conf/" + suffix; - }; - ConfigManager::ConfigManager() { use_prot_storage_ = GetAndroidApiLevel() >= __ANDROID_API_N__; last_user_ = 0; UpdateConfigPath(last_user_); } + bool ConfigManager::UpdateModuleList() { + if (LIKELY(modules_list_) && !IsDynamicModulesEnabled()) + return true; + auto global_modules_list = GetConfigPath("modules.list"); + if(access(global_modules_list.c_str(), F_OK) != 0) { + LOGE("Cannot access path %s", global_modules_list.c_str()); + return false; + } + ifstream ifs(global_modules_list); + if (!ifs.good()) { + LOGE("Cannot access path %s", global_modules_list.c_str()); + return false; + } + modules_list_ = std::make_unique(std::istreambuf_iterator(ifs), std::istreambuf_iterator()); + return true; + } + } \ No newline at end of file diff --git a/edxp-core/src/main/cpp/main/src/config_manager.h b/edxp-core/src/main/cpp/main/src/config_manager.h index cc05405a4..59aaef3b4 100644 --- a/edxp-core/src/main/cpp/main/src/config_manager.h +++ b/edxp-core/src/main/cpp/main/src/config_manager.h @@ -4,53 +4,63 @@ #include #include #include +#include #include namespace edxp { - static constexpr const char *kPrimaryInstallerPkgName = "org.meowcat.edxposed.manager"; - static constexpr const char *kLegacyInstallerPkgName = "de.robv.android.xposed.installer"; - static constexpr auto kXposedPropPath = "/system/framework/edconfig.jar"; + static const std::string kPrimaryInstallerPkgName = "org.meowcat.edxposed.manager"; + static const std::string kLegacyInstallerPkgName = "de.robv.android.xposed.installer"; + static const std::string kXposedPropPath = "/system/framework/edconfig.jar"; class ConfigManager { public: - static ConfigManager *GetInstance() { - if (instance_ == 0) { - instance_ = new ConfigManager(); + inline static ConfigManager *GetInstance() { + if (!instance_) { + instance_ = std::make_unique(); } - return instance_; + return instance_.get(); } - bool IsBlackWhiteListEnabled() const; + inline static std::unique_ptr ReleaseInstance() { + return std::move(instance_); + } + + inline auto IsBlackWhiteListEnabled() const { return black_white_list_enabled_; } - bool IsDynamicModulesEnabled() const; + inline auto IsDynamicModulesEnabled() const { return dynamic_modules_enabled_; } - bool IsResourcesHookEnabled() const; + inline auto IsResourcesHookEnabled() const { return resources_hook_enabled_; } - bool IsDeoptBootImageEnabled() const; + inline auto IsDeoptBootImageEnabled() const { return deopt_boot_image_enabled_; } - bool IsNoModuleLogEnabled() const; + inline auto IsNoModuleLogEnabled() const { return no_module_log_enabled_; } - bool IsHiddenAPIBypassEnabled() const; + inline auto IsHiddenAPIBypassEnabled() const { return hidden_api_bypass_enabled_; } - std::string GetInstallerPackageName() const; + inline auto GetInstallerPackageName() const { return installer_pkg_name_; } - std::string GetXposedPropPath() const; + inline auto GetXposedPropPath() const { return kXposedPropPath; } - std::string GetLibSandHookName() const; + inline auto GetLibSandHookName() const { return kLibSandHookName; } - std::string GetLibWhaleName() const; + inline auto GetLibWhaleName() const { return kLibWhaleName; } - std::string GetDataPathPrefix() const; + inline auto GetDataPathPrefix() const { return data_path_prefix_; } - std::string GetConfigPath(const std::string &suffix) const; + inline auto GetConfigPath(const std::string &suffix) const { + return data_path_prefix_ + installer_pkg_name_ + "/conf/" + suffix; + } + + inline auto GetModulesList() const { return modules_list_.get(); } bool IsAppNeedHook(const std::string &app_data_dir); - bool hidden_api_bypass_enabled_ = false; + bool UpdateModuleList(); + private: - inline static ConfigManager *instance_; + inline static std::unique_ptr instance_ = nullptr; uid_t last_user_ = false; bool use_prot_storage_ = true; std::string data_path_prefix_; @@ -68,6 +78,9 @@ namespace edxp { bool use_white_list_snapshot_ = false; std::vector white_list_default_; std::vector black_list_default_; + bool hidden_api_bypass_enabled_ = false; + + std::unique_ptr modules_list_ = nullptr; ConfigManager(); @@ -76,6 +89,8 @@ namespace edxp { void SnapshotBlackWhiteList(); std::string RetrieveInstallerPkgName() const; + + friend std::unique_ptr std::make_unique(); }; } // namespace edxp diff --git a/edxp-core/src/main/cpp/main/src/edxp_context.cpp b/edxp-core/src/main/cpp/main/src/edxp_context.cpp index 9ca3deac1..7280d2dff 100644 --- a/edxp-core/src/main/cpp/main/src/edxp_context.cpp +++ b/edxp-core/src/main/cpp/main/src/edxp_context.cpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include "edxp_context.h" #include "config_manager.h" @@ -53,7 +55,28 @@ namespace edxp { CallPostFixupStaticTrampolinesCallback(class_ptr, post_fixup_static_mid_); } - void Context::LoadDexAndInit(JNIEnv *env, const char *dex_path) { + void Context::PreLoadDex(JNIEnv *env, const std::string &dex_path) { + if (LIKELY(!dexes.empty())) return; + std::vector paths; + { + std::istringstream is(dex_path); + std::string path; + while (std::getline(is, path, ':')) { + paths.emplace_back(std::move(path)); + } + } + for (const auto &path: paths) { + std::ifstream is(path, std::ios::binary); + if (!is.good()) { + LOGE("Cannot load path %s", path.c_str()); + } + dexes.emplace_back(std::istreambuf_iterator(is), + std::istreambuf_iterator()); + LOGI("Loaded %s %d", path.c_str(), dexes.back().size()); + } + } + + void Context::InjectDexAndInit(JNIEnv *env) { if (LIKELY(initialized_)) { return; } @@ -63,21 +86,34 @@ namespace edxp { env, classloader, "getSystemClassLoader", "()Ljava/lang/ClassLoader;"); jobject sys_classloader = JNI_CallStaticObjectMethod(env, classloader, getsyscl_mid); if (UNLIKELY(!sys_classloader)) { - LOG(ERROR) << "getSystemClassLoader failed!!!"; + LOGE("getSystemClassLoader failed!!!"); return; } - jclass path_classloader = JNI_FindClass(env, "dalvik/system/PathClassLoader"); - jmethodID initMid = JNI_GetMethodID(env, path_classloader, "", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V"); - jobject my_cl = JNI_NewObject(env, path_classloader, initMid, env->NewStringUTF(dex_path), - nullptr, sys_classloader); - + jclass in_memory_classloader = JNI_FindClass(env, "dalvik/system/InMemoryDexClassLoader"); + jmethodID initMid = JNI_GetMethodID(env, in_memory_classloader, "", + "([Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V"); + jclass byte_buffer_class = JNI_FindClass(env, "java/nio/ByteBuffer"); + jmethodID byte_buffer_wrap = JNI_GetStaticMethodID(env, byte_buffer_class, "wrap", + "([B)Ljava/nio/ByteBuffer;"); + auto buffer_array = env->NewObjectArray(dexes.size(), byte_buffer_class, nullptr); + for (size_t i = 0; i != dexes.size(); ++i) { + const auto dex = dexes.at(i); + auto byte_array = env->NewByteArray(dex.size()); + env->SetByteArrayRegion(byte_array, 0, dex.size(), + dex.data()); + auto buffer = JNI_CallStaticObjectMethod(env, byte_buffer_class, byte_buffer_wrap, + byte_array); + env->SetObjectArrayElement(buffer_array, i, buffer); + } + jobject my_cl = env->NewObject(in_memory_classloader, initMid, + buffer_array, sys_classloader); env->DeleteLocalRef(classloader); env->DeleteLocalRef(sys_classloader); - env->DeleteLocalRef(path_classloader); + env->DeleteLocalRef(in_memory_classloader); + env->DeleteLocalRef(byte_buffer_class); if (UNLIKELY(my_cl == nullptr)) { - LOG(ERROR) << "PathClassLoader creation failed!!!"; + LOGE("InMemoryDexClassLoader creation failed!!!"); return; } @@ -142,7 +178,7 @@ namespace edxp { } jclass - Context::FindClassFromLoader(JNIEnv *env, jobject class_loader, const char *class_name) const { + Context::FindClassFromLoader(JNIEnv *env, jobject class_loader, const char *class_name) { jclass clz = JNI_GetObjectClass(env, class_loader); jmethodID mid = JNI_GetMethodID(env, clz, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); @@ -157,57 +193,17 @@ namespace edxp { return (jclass) target; } } else { - LOG(ERROR) << "No loadClass/findClass method found"; + LOGE("No loadClass/findClass method found"); } - LOG(ERROR) << "Class %s not found: " << class_name; + LOGE("Class %s not found", class_name); return ret; } - jclass Context::FindClassFromLoader(JNIEnv *env, const char *className) const { - return FindClassFromLoader(env, GetCurrentClassLoader(), className); - } inline void Context::PrepareJavaEnv(JNIEnv *env) { - LoadDexAndInit(env, kInjectDexPath); - } - - void Context::ReleaseJavaEnv(JNIEnv *env) { - if (UNLIKELY(!instance_)) return; - - auto xposed_bridge_class = FindClassFromLoader(env, inject_class_loader_, kXposedBridgeClassName); - if(LIKELY(xposed_bridge_class)){ - jmethodID clear_all_callbacks_method = JNI_GetStaticMethodID(env, xposed_bridge_class, "clearAllCallbacks", - "()V"); - if(LIKELY(clear_all_callbacks_method)) { - JNI_CallStaticVoidMethod(env, xposed_bridge_class, clear_all_callbacks_method); - } - } - - initialized_ = false; - if (entry_class_) { - env->DeleteGlobalRef(entry_class_); - entry_class_ = nullptr; - } - if (class_linker_class_) { - env->DeleteGlobalRef(class_linker_class_); - class_linker_class_ = nullptr; - } - if (inject_class_loader_) { - env->DeleteGlobalRef(inject_class_loader_); - inject_class_loader_ = nullptr; - } - app_data_dir_ = nullptr; - nice_name_ = nullptr; - vm_ = nullptr; - pre_fixup_static_mid_ = nullptr; - post_fixup_static_mid_ = nullptr; - - auto systemClass = env->FindClass("java/lang/System"); - auto systemGCMethod = env->GetStaticMethodID(systemClass, "gc", "()V"); - env->CallStaticVoidMethod(systemClass, systemGCMethod); + InjectDexAndInit(env); } - inline void Context::FindAndCall(JNIEnv *env, const char *method_name, const char *method_sig, ...) const { if (UNLIKELY(!entry_class_)) { @@ -226,16 +222,14 @@ namespace edxp { } void - Context::OnNativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t uid, gid_t gid, + Context::OnNativeForkSystemServerPre(JNIEnv *env, [[maybe_unused]] jclass clazz, uid_t uid, + gid_t gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities, jlong effective_capabilities) { - app_data_dir_ = env->NewStringUTF(SYSTEM_SERVER_DATA_DIR); - PrepareJavaEnv(env); - // jump to java code - FindAndCall(env, "forkSystemServerPre", "(II[II[[IJJ)V", uid, gid, gids, runtime_flags, - rlimits, permitted_capabilities, effective_capabilities); + app_data_dir_ = env->NewStringUTF(SYSTEM_SERVER_DATA_DIR.c_str()); + PreLoadDex(env, kInjectDexPath); } @@ -251,15 +245,13 @@ namespace edxp { return 0; } - std::tuple Context::ShouldSkipInject(JNIEnv *env, jstring nice_name, jstring data_dir, jint uid, + bool Context::ShouldSkipInject(JNIEnv *env, jstring nice_name, jstring data_dir, jint uid, jboolean is_child_zygote) { const auto app_id = uid % PER_USER_RANGE; const JUTFString package_name(env, nice_name, "UNKNOWN"); bool skip = false; - bool release = true; if (is_child_zygote) { skip = true; - release = false; // In Android R, calling XposedBridge.clearAllCallbacks cause crashes. LOGW("skip injecting into %s because it's a child zygote", package_name.get()); } @@ -267,17 +259,17 @@ namespace edxp { (app_id >= FIRST_APP_ZYGOTE_ISOLATED_UID && app_id <= LAST_APP_ZYGOTE_ISOLATED_UID) || app_id == SHARED_RELRO_UID) { skip = true; - release = false; // In Android R, calling XposedBridge.clearAllCallbacks cause crashes. LOGW("skip injecting into %s because it's isolated", package_name.get()); } const JUTFString dir(env, data_dir); - if(!dir || !ConfigManager::GetInstance()->IsAppNeedHook(dir)) { + if (auto cm = ConfigManager::GetInstance(); + !dir || (cm->IsBlackWhiteListEnabled() && !cm->IsAppNeedHook(dir))) { skip = true; LOGW("skip injecting xposed into %s because it's whitelisted/blacklisted", package_name.get()); } - return {skip, release}; + return skip; } void Context::OnNativeForkAndSpecializePre(JNIEnv *env, jclass clazz, @@ -293,32 +285,29 @@ namespace edxp { jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir) { - std::tie(skip_, release_) = ShouldSkipInject(env, nice_name, app_data_dir, uid, is_child_zygote); + skip_ = ShouldSkipInject(env, nice_name, app_data_dir, uid, + is_child_zygote); + skip_ = skip_ || !ConfigManager::GetInstance()->UpdateModuleList(); app_data_dir_ = app_data_dir; nice_name_ = nice_name; - PrepareJavaEnv(env); - if(!skip_) { - FindAndCall(env, "forkAndSpecializePre", - "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;)V", - uid, gid, gids, runtime_flags, rlimits, - mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, - is_child_zygote, instruction_set, app_data_dir); - } + PreLoadDex(env, kInjectDexPath); } - int Context::OnNativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) { + int + Context::OnNativeForkAndSpecializePost(JNIEnv *env, [[maybe_unused]]jclass clazz, jint res) { if (res == 0) { - const JUTFString package_name(env, nice_name_); + const JUTFString process_name(env, nice_name_); if (!skip_) { PrepareJavaEnv(env); + LOGD("Done prepare"); FindAndCall(env, "forkAndSpecializePost", "(ILjava/lang/String;Ljava/lang/String;)V", res, app_data_dir_, nice_name_); - LOGD("injected xposed into %s", package_name.get()); + LOGD("injected xposed into %s", process_name.get()); } else { - if(release_) - ReleaseJavaEnv(env); - LOGD("skipped %s", package_name.get()); + auto config_manager = ConfigManager::ReleaseInstance(); + auto context = Context::ReleaseInstance(); + LOGD("skipped %s", process_name.get()); } } else { // in zygote process, res is child zygote pid diff --git a/edxp-core/src/main/cpp/main/src/edxp_context.h b/edxp-core/src/main/cpp/main/src/edxp_context.h index 974300daa..63d74af37 100644 --- a/edxp-core/src/main/cpp/main/src/edxp_context.h +++ b/edxp-core/src/main/cpp/main/src/edxp_context.h @@ -1,13 +1,15 @@ #pragma once +#include #include -#include +#include +#include +#include +#include "utils.h" namespace edxp { - -#define SYSTEM_SERVER_DATA_DIR "/data/user/0/android" - + static const auto SYSTEM_SERVER_DATA_DIR = "/data/user/0/android"_str; enum Variant { NONE = 0, YAHFA = 1, @@ -18,11 +20,15 @@ namespace edxp { class Context { public: - inline static auto GetInstance() { - if (instance_ == nullptr) { - instance_ = new Context(); + inline static Context *GetInstance() { + if (!instance_) { + instance_ = std::make_unique(); } - return instance_; + return instance_.get(); + } + + inline static std::unique_ptr ReleaseInstance() { + return std::move(instance_); } inline auto GetCurrentClassLoader() const { return inject_class_loader_; } @@ -45,7 +51,13 @@ namespace edxp { inline auto GetNiceName() const { return nice_name_; } - jclass FindClassFromLoader(JNIEnv *env, const char *className) const; + inline jclass FindClassFromLoader(JNIEnv *env, const std::string &className) const { + return FindClassFromLoader(env, className.c_str()); + }; + + inline jclass FindClassFromLoader(JNIEnv *env, const char *className) const { + return FindClassFromLoader(env, GetCurrentClassLoader(), className); + } void OnNativeForkAndSpecializePre(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, @@ -68,7 +80,7 @@ namespace edxp { inline auto GetVariant() const { return variant_; }; private: - inline static Context *instance_; + inline static std::unique_ptr instance_; bool initialized_ = false; Variant variant_ = NONE; jobject inject_class_loader_ = nullptr; @@ -80,22 +92,28 @@ namespace edxp { jmethodID pre_fixup_static_mid_ = nullptr; jmethodID post_fixup_static_mid_ = nullptr; bool skip_ = false; - bool release_ = true; + std::vector> dexes; Context() {} - ~Context() {} + void PreLoadDex(JNIEnv *env, const std::string &dex_path); - void LoadDexAndInit(JNIEnv *env, const char *dex_path); + void InjectDexAndInit(JNIEnv *env); + + inline jclass FindClassFromLoader(JNIEnv *env, jobject class_loader, + const std::string &class_name) const { + return FindClassFromLoader(env, class_loader, class_name.c_str()); + } - jclass FindClassFromLoader(JNIEnv *env, jobject class_loader, const char *class_name) const; + static jclass + FindClassFromLoader(JNIEnv *env, jobject class_loader, const char *class_name); void CallPostFixupStaticTrampolinesCallback(void *class_ptr, jmethodID mid); - static std::tuple ShouldSkipInject(JNIEnv *env, jstring nice_name, jstring data_dir, jint uid, + static bool ShouldSkipInject(JNIEnv *env, jstring nice_name, jstring data_dir, jint uid, jboolean is_child_zygote); - void ReleaseJavaEnv(JNIEnv *env); + friend std::unique_ptr std::make_unique(); }; } diff --git a/edxp-core/src/main/cpp/main/src/jni/edxp_config_manager.cpp b/edxp-core/src/main/cpp/main/src/jni/edxp_config_manager.cpp index 21983d4c1..6e8ba9e35 100644 --- a/edxp-core/src/main/cpp/main/src/jni/edxp_config_manager.cpp +++ b/edxp-core/src/main/cpp/main/src/jni/edxp_config_manager.cpp @@ -61,6 +61,16 @@ namespace edxp { return result; } + static jstring ConfigManager_getModulesList(JNI_START) { + if (auto module_list = ConfigManager::GetInstance()->GetModulesList(); module_list) { + LOGD("module list: %s", module_list->c_str()); + return env->NewStringUTF(module_list->c_str()); + } else { + LOGW("Empty modules list"); + return env->NewStringUTF(""); + } + } + static JNINativeMethod gMethods[] = { NATIVE_METHOD(ConfigManager, isBlackWhiteListEnabled, "()Z"), NATIVE_METHOD(ConfigManager, isDynamicModulesEnabled, "()Z"), @@ -72,8 +82,10 @@ namespace edxp { NATIVE_METHOD(ConfigManager, getLibSandHookName, "()Ljava/lang/String;"), NATIVE_METHOD(ConfigManager, getLibWhaleName, "()Ljava/lang/String;"), NATIVE_METHOD(ConfigManager, getDataPathPrefix, "()Ljava/lang/String;"), - NATIVE_METHOD(ConfigManager, getInstallerConfigPath, "(Ljava/lang/String;)Ljava/lang/String;"), + NATIVE_METHOD(ConfigManager, getInstallerConfigPath, + "(Ljava/lang/String;)Ljava/lang/String;"), NATIVE_METHOD(ConfigManager, isAppNeedHook, "(Ljava/lang/String;)Z"), + NATIVE_METHOD(ConfigManager, getModulesList, "()Ljava/lang/String;"), }; void RegisterConfigManagerMethods(JNIEnv *env) { diff --git a/edxp-sandhook/build.gradle b/edxp-sandhook/build.gradle index f1e426488..93a034902 100644 --- a/edxp-sandhook/build.gradle +++ b/edxp-sandhook/build.gradle @@ -59,6 +59,25 @@ afterEvaluate { def myTemplatePath = "${projectDir}/template_override/" + task("copyDex${variantNameCapped}", type: Copy) { + dependsOn "assemble${variantNameCapped}" + dependsOn tasks.getByPath(":edxp-common:copyCommonProperties") + def dexOutPath = variant.name.contains("release") ? + "${buildDir}/intermediates/transforms/dexMerger/${variantNameLowered}/0/" : + "${buildDir}/intermediates/dex/${variantNameLowered}/mergeDex${variantNameCapped}/out/" + from (dexOutPath){ + rename("classes.dex", "edxp.dex") + } + from "${projectDir}/src/main/resources/" + destinationDir file(myTemplatePath + "system/framework/") + doLast { + copy { + from file(myTemplatePath) + into file(templateRootPath) + } + } + } + task("makeAndCopy${variantNameCapped}", type: Jar, dependsOn: "assemble${variantNameCapped}") { dependsOn tasks.getByPath(":edxp-common:copyCommonProperties") def dexOutPath = variant.name.contains("release") ? diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/OnePlusWorkAroundHooker.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/OnePlusWorkAroundHooker.java deleted file mode 100644 index 92089ad6f..000000000 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/OnePlusWorkAroundHooker.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.elderdrivers.riru.edxp.sandhook.hooker; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp._hooker.impl.OneplusWorkaround; -import com.elderdrivers.riru.edxp.core.yahfa.HookMain; -import com.swift.sandhook.SandHook; -import com.swift.sandhook.annotation.HookClass; -import com.swift.sandhook.annotation.HookMethod; -import com.swift.sandhook.annotation.HookMethodBackup; -import com.swift.sandhook.annotation.SkipParamCheck; - -import java.lang.reflect.Method; - -import dalvik.system.BaseDexClassLoader; -import de.robv.android.xposed.XC_MethodHook; -import de.robv.android.xposed.annotation.ApiSensitive; -import de.robv.android.xposed.annotation.Level; - -// TODO check HOS / OOS ver.11 when available -@ApiSensitive(Level.MIDDLE) -@HookClass(BaseDexClassLoader.class) -public class OnePlusWorkAroundHooker implements KeepMembers { - - static { - HookMain.addHookItemWhiteList(OnePlusWorkAroundHooker.class.getName()); - } - - public static String className = "dalvik.system.BaseDexClassLoader"; - public static String methodName = "inCompatConfigList"; - public static String methodSig = "(ILjava/lang/String;)Z"; - - @HookMethodBackup("inCompatConfigList") - @SkipParamCheck - static Method backup; - - @HookMethod("inCompatConfigList") - public static boolean hook(int type, String packageName) throws Throwable { - final XC_MethodHook methodHook = new OneplusWorkaround(); - final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); - param.thisObject = null; - param.args = new Object[]{type, packageName}; - methodHook.callBeforeHookedMethod(param); - if (!param.returnEarly) { - param.setResult(backup(type, packageName)); - } - methodHook.callAfterHookedMethod(param); - return (boolean) param.getResult(); - } - - public static boolean backup(int type, String packageName) throws Throwable { - return (boolean) SandHook.callOriginByBackup(backup, null, type, packageName); - } -} \ No newline at end of file diff --git a/edxp-whale/build.gradle b/edxp-whale/build.gradle index 76a1d7fb2..f74928035 100644 --- a/edxp-whale/build.gradle +++ b/edxp-whale/build.gradle @@ -58,6 +58,25 @@ afterEvaluate { def myTemplatePath = "${projectDir}/template_override/" + task("copyDex${variantNameCapped}", type: Copy) { + dependsOn "assemble${variantNameCapped}" + dependsOn tasks.getByPath(":edxp-common:copyCommonProperties") + def dexOutPath = variant.name.contains("release") ? + "${buildDir}/intermediates/transforms/dexMerger/${variantNameLowered}/0/" : + "${buildDir}/intermediates/dex/${variantNameLowered}/mergeDex${variantNameCapped}/out/" + from (dexOutPath){ + rename("classes.dex", "edxp.dex") + } + from "${projectDir}/src/main/resources/" + destinationDir file(myTemplatePath + "system/framework/") + doLast { + copy { + from file(myTemplatePath) + into file(templateRootPath) + } + } + } + task("makeAndCopy${variantNameCapped}", type: Jar, dependsOn: "assemble${variantNameCapped}") { dependsOn tasks.getByPath(":edxp-common:copyCommonProperties") def dexOutPath = variant.name.contains("release") ? diff --git a/edxp-yahfa/build.gradle b/edxp-yahfa/build.gradle index f142309c1..1a1debab7 100644 --- a/edxp-yahfa/build.gradle +++ b/edxp-yahfa/build.gradle @@ -58,6 +58,25 @@ afterEvaluate { def myTemplatePath = "${projectDir}/template_override/" + task("copyDex${variantNameCapped}", type: Copy) { + dependsOn "assemble${variantNameCapped}" + dependsOn tasks.getByPath(":edxp-common:copyCommonProperties") + def dexOutPath = variant.name.contains("release") ? + "${buildDir}/intermediates/transforms/dexMerger/${variantNameLowered}/0/" : + "${buildDir}/intermediates/dex/${variantNameLowered}/mergeDex${variantNameCapped}/out/" + from (dexOutPath){ + rename("classes.dex", "edxp.dex") + } + from "${projectDir}/src/main/resources/" + destinationDir file(myTemplatePath + "system/framework/") + doLast { + copy { + from file(myTemplatePath) + into file(templateRootPath) + } + } + } + task("makeAndCopy${variantNameCapped}", type: Jar, dependsOn: "assemble${variantNameCapped}") { dependsOn tasks.getByPath(":edxp-common:copyCommonProperties") def dexOutPath = variant.name.contains("release") ? diff --git a/edxp-yahfa/proguard-rules.pro b/edxp-yahfa/proguard-rules.pro index c600fee6c..95a1c0b83 100644 --- a/edxp-yahfa/proguard-rules.pro +++ b/edxp-yahfa/proguard-rules.pro @@ -32,4 +32,4 @@ -keepclasseswithmember class * { native ; -} \ No newline at end of file +} diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/YahfaEdxpImpl.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/YahfaEdxpImpl.java index 8a05b27dc..628dbde6c 100644 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/YahfaEdxpImpl.java +++ b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/YahfaEdxpImpl.java @@ -8,7 +8,6 @@ import com.elderdrivers.riru.edxp.core.Proxy; import com.elderdrivers.riru.edxp.core.Yahfa; import com.elderdrivers.riru.edxp.core.yahfa.HookMethodResolver; -import com.elderdrivers.riru.edxp.proxy.BlackWhiteListProxy; import com.elderdrivers.riru.edxp.proxy.NormalProxy; import com.elderdrivers.riru.edxp.proxy.Router; @@ -35,11 +34,6 @@ public void init() { setInitialized(); } - @Override - protected Proxy createBlackWhiteListProxy() { - return new BlackWhiteListProxy(getRouter()); - } - @Override protected Proxy createNormalProxy() { return new NormalProxy(getRouter()); diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 797f6b0cd..208ce983c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sat Apr 20 12:28:06 CST 2019 +#Fri Nov 13 15:00:57 CST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip diff --git a/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/config/EdxpConfig.java b/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/config/EdxpConfig.java index a8959cfd9..58e6d3410 100644 --- a/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/config/EdxpConfig.java +++ b/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/config/EdxpConfig.java @@ -21,4 +21,6 @@ public interface EdxpConfig { boolean isResourcesHookEnabled(); boolean isBlackWhiteListMode(); + + String getModulesList(); } diff --git a/xposed-bridge/src/main/java/de/robv/android/xposed/XposedInit.java b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedInit.java index 51169f4d0..3d63c66a6 100644 --- a/xposed-bridge/src/main/java/de/robv/android/xposed/XposedInit.java +++ b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedInit.java @@ -17,10 +17,12 @@ import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal; import java.io.BufferedReader; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.StringBufferInputStream; import java.lang.ref.WeakReference; import java.lang.reflect.Method; import java.util.ArrayList; @@ -307,38 +309,21 @@ private static boolean needsToCloseFilesForFork() { private static final Object moduleLoadLock = new Object(); // @GuardedBy("moduleLoadLock") private static final ArraySet loadedModules = new ArraySet<>(); - // @GuardedBy("moduleLoadLock") - private static long lastModuleListModifiedTime = -1; - public static boolean loadModules(boolean isInZygote, boolean callInitZygote) throws IOException { + public static boolean loadModules(boolean callInitZygote) throws IOException { boolean hasLoaded = !modulesLoaded.compareAndSet(false, true); if (hasLoaded && !EdXpConfigGlobal.getConfig().isDynamicModulesMode()) { return false; } synchronized (moduleLoadLock) { - final String filename = EdXpConfigGlobal.getConfig().getInstallerConfigPath("modules.list"); - BaseService service = SELinuxHelper.getAppDataFileService(); - if (!service.checkFileExists(filename)) { - Log.e(TAG, "Cannot load any modules because " + filename + " was not found"); - // FIXME module list is cleared but never could be reload again - // when using dynamic-module-list under multi-user environment - clearAllCallbacks(); - return false; - } - - long moduleListModifiedTime = service.getFileModificationTime(filename); - if (lastModuleListModifiedTime == moduleListModifiedTime) { - // module list has not changed - return false; - } - ClassLoader topClassLoader = XposedBridge.BOOTCLASSLOADER; ClassLoader parent; while ((parent = topClassLoader.getParent()) != null) { topClassLoader = parent; } - InputStream stream = service.getFileInputStream(filename); + String moduleList = EdXpConfigGlobal.getConfig().getModulesList(); + InputStream stream = new ByteArrayInputStream(moduleList.getBytes()); BufferedReader apks = new BufferedReader(new InputStreamReader(stream)); ArraySet newLoadedApk = new ArraySet<>(); String apk; @@ -358,9 +343,6 @@ public static boolean loadModules(boolean isInZygote, boolean callInitZygote) th // refresh callback according to current loaded module list pruneCallbacks(loadedModules); - - lastModuleListModifiedTime = moduleListModifiedTime; - } return true; }