diff --git a/build.gradle b/build.gradle index 5db8a85be..48da868cd 100644 --- a/build.gradle +++ b/build.gradle @@ -7,8 +7,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.4.0' - + classpath 'com.android.tools.build:gradle:4.1.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files 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..3d07b3003 100644 --- a/edxp-common/build.gradle +++ b/edxp-common/build.gradle @@ -17,13 +17,14 @@ android { } } + ndkVersion androidCompileNdkVersion } 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 000000000..1c5002cc6 Binary files /dev/null and b/edxp-common/libs/framework-stub.jar differ diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/OneplusWorkaround.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/OneplusWorkaround.java deleted file mode 100644 index cccc23e26..000000000 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/OneplusWorkaround.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.elderdrivers.riru.edxp._hooker.impl; - -import com.elderdrivers.riru.edxp.core.Main; -import com.elderdrivers.riru.edxp.util.Hookers; - -import dalvik.system.BaseDexClassLoader; -import de.robv.android.xposed.XC_MethodHook; -import de.robv.android.xposed.XposedBridge; - -/** - * On OnePlus stock roms (Android Pie), {@link BaseDexClassLoader#findClass(String)} - * will open /dev/binder to communicate with PackageManagerService to check whether - * current package name inCompatConfigList, which is an OnePlus OEM feature enabled only when - * system prop "persist.sys.oem.region" set to "CN".(detail of related source code: - * https://gist.github.com/solohsu/ecc07141759958fc096ba0781fac0a5f) - * If we invoke intZygoteCallbacks in - * {@link Main#forkAndSpecializePre}, where in zygote process, - * we would get a chance to invoke findclass, leaving fd of /dev/binder open in zygote process, - * which is not allowed because /dev/binder is not in predefined whitelist here: - * http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/jni/fd_utils.cpp#35 - * So we just hook BaseDexClassLoader#inCompatConfigList to return false to prevent - * open of /dev/binder and we haven't found side effects yet. - * Other roms might share the same problems but not reported too. - */ -public class OneplusWorkaround extends XC_MethodHook { - - @Override - protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - if (XposedBridge.disableHooks || Main.getEdxpImpl().getRouter().isForkCompleted()) { - return; - } - Hookers.logD("BaseDexClassLoader#inCompatConfigList() starts"); - param.setResult(false); - } - -} diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/OnePlusWorkAroundHooker.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/OnePlusWorkAroundHooker.java deleted file mode 100644 index 8fea63fe3..000000000 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/OnePlusWorkAroundHooker.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.elderdrivers.riru.edxp._hooker.yahfa; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp._hooker.impl.OneplusWorkaround; -import com.elderdrivers.riru.edxp.core.yahfa.HookMain; - -import de.robv.android.xposed.XC_MethodHook; -import de.robv.android.xposed.annotation.ApiSensitive; -import de.robv.android.xposed.annotation.Level; - -@ApiSensitive(Level.MIDDLE) -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"; - - 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) { - return false; - } -} \ No newline at end of file diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/BaseEdxpConfig.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/BaseEdxpConfig.java index 12474f647..a4ffce539 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/BaseEdxpConfig.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/BaseEdxpConfig.java @@ -51,4 +51,7 @@ public boolean isNoModuleLogEnabled() { public boolean isBlackWhiteListMode() { return ConfigManager.isBlackWhiteListEnabled(); } + + @Override + public String getModulesList() { return ConfigManager.getModulesList(); } } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/ConfigManager.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/ConfigManager.java index e237c276a..9e0dc4f8c 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/ConfigManager.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/ConfigManager.java @@ -50,4 +50,6 @@ private static boolean isFileExists(String path) { public static native String getDataPathPrefix(); public static native boolean isAppNeedHook(String appDataDir); + + public static native String getModulesList(); } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/BaseEdxpImpl.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/BaseEdxpImpl.java index 8b7593c2a..8d2101d04 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/BaseEdxpImpl.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/BaseEdxpImpl.java @@ -1,14 +1,12 @@ package com.elderdrivers.riru.edxp.core; -import androidx.annotation.NonNull; +import android.support.annotation.NonNull; -import com.elderdrivers.riru.edxp.proxy.BlackWhiteListProxy; import com.elderdrivers.riru.edxp.proxy.NormalProxy; import com.elderdrivers.riru.edxp.proxy.Router; public abstract class BaseEdxpImpl implements EdxpImpl { - protected Proxy mBlackWhiteListProxy; protected Proxy mNormalProxy; protected Router mRouter; @@ -23,15 +21,6 @@ public boolean isInitialized() { return mInitialized; } - @NonNull - @Override - public Proxy getBlackWhiteListProxy() { - if (mBlackWhiteListProxy == null) { - mBlackWhiteListProxy = createBlackWhiteListProxy(); - } - return mBlackWhiteListProxy; - } - @NonNull @Override public Proxy getNormalProxy() { @@ -50,10 +39,6 @@ public Router getRouter() { return mRouter; } - protected Proxy createBlackWhiteListProxy() { - return new BlackWhiteListProxy(getRouter()); - } - protected Proxy createNormalProxy() { return new NormalProxy(getRouter()); } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/EdxpImpl.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/EdxpImpl.java index 332605942..4309936ff 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/EdxpImpl.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/EdxpImpl.java @@ -1,7 +1,7 @@ package com.elderdrivers.riru.edxp.core; -import androidx.annotation.IntDef; -import androidx.annotation.NonNull; +import android.support.annotation.IntDef; +import android.support.annotation.NonNull; import com.elderdrivers.riru.common.KeepAll; import com.elderdrivers.riru.edxp.proxy.Router; @@ -20,9 +20,6 @@ public interface EdxpImpl extends KeepAll { @NonNull Proxy getNormalProxy(); - @NonNull - Proxy getBlackWhiteListProxy(); - @NonNull Router getRouter(); diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/Main.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/Main.java index 07ff8c04d..a4acd4d35 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/Main.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/Main.java @@ -1,27 +1,20 @@ package com.elderdrivers.riru.edxp.core; import android.annotation.SuppressLint; -import android.os.Process; import com.elderdrivers.riru.common.KeepAll; -import com.elderdrivers.riru.edxp.common.BuildConfig; -import com.elderdrivers.riru.edxp.config.ConfigManager; import com.elderdrivers.riru.edxp.util.Utils; import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.Arrays; import java.util.Iterator; import java.util.ServiceLoader; import java.util.concurrent.atomic.AtomicReference; +import static com.elderdrivers.riru.edxp.core.EdxpImpl.NONE; + @SuppressLint("DefaultLocale") public class Main implements KeepAll { - - private static final boolean logEnabled = BuildConfig.DEBUG; - private static String forkAndSpecializePramsStr = ""; - private static String forkSystemServerPramsStr = ""; - private static final AtomicReference edxpImplRef = new AtomicReference<>(null); static { @@ -37,67 +30,23 @@ 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 } 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 +55,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 +73,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-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassLoaderUtils.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassLoaderUtils.java index 4ef454352..2af555e88 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassLoaderUtils.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassLoaderUtils.java @@ -21,7 +21,7 @@ @ApiSensitive(Level.LOW) public class ClassLoaderUtils { - public static final String DEXPATH = "/system/framework/edxp.jar:/system/framework/eddalvikdx.jar:/system/framework/eddexmaker.jar"; + public static final String DEXPATH = "/system/framework/edxp.dex:/system/framework/eddalvikdx.dex:/system/framework/eddexmaker.dex"; public static void replaceParentClassLoader(ClassLoader appClassLoader) { if (appClassLoader == null) { diff --git a/edxp-core/.gitignore b/edxp-core/.gitignore index b077bf8d2..05b2e93c6 100644 --- a/edxp-core/.gitignore +++ b/edxp-core/.gitignore @@ -6,4 +6,5 @@ /template_override/module.prop /template_override/system /template_override/system_x86 -*.iml \ No newline at end of file +*.iml +/.cxx \ No newline at end of file diff --git a/edxp-core/build.gradle b/edxp-core/build.gradle index 8368c27df..e6226d4bf 100644 --- a/edxp-core/build.gradle +++ b/edxp-core/build.gradle @@ -63,8 +63,8 @@ android { release { externalNativeBuild { cmake { - cppFlags "-fvisibility=hidden -fvisibility-inlines-hidden -O2 -s -Wno-unused-value" - cFlags "-fvisibility=hidden -fvisibility-inlines-hidden -O2 -s -Wno-unused-value" + cppFlags "-fvisibility=hidden -fvisibility-inlines-hidden -O2 -s -Wno-unused-value -fomit-frame-pointer" + cFlags "-fvisibility=hidden -fvisibility-inlines-hidden -O2 -s -Wno-unused-value -fomit-frame-pointer" } } minifyEnabled true @@ -76,6 +76,35 @@ android { path "src/main/cpp/CMakeLists.txt" } } + ndkVersion androidCompileNdkVersion +} + +task copyDalvikdxDex { + def dexTask = tasks.getByPath(':dalvikdx:dex') + dependsOn dexTask + doLast { + copy { + from dexTask + into jar_dest_dir + } + } + onlyIf { + !dexTask.state.upToDate + } +} + +task copyDexmakerDex { + def dexTask = tasks.getByPath(':dexmaker:dex') + dependsOn dexTask + doLast { + copy { + from dexTask + into jar_dest_dir + } + } + onlyIf { + !dexTask.state.upToDate + } } task copyDalvikdxJar { @@ -125,8 +154,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 +224,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/base/object.h b/edxp-core/src/main/cpp/main/include/base/object.h index 45806a081..f7ff2fe03 100644 --- a/edxp-core/src/main/cpp/main/include/base/object.h +++ b/edxp-core/src/main/cpp/main/include/base/object.h @@ -5,15 +5,15 @@ #include #include -#define __uintval(p) reinterpret_cast(p) -#define __ptr(p) reinterpret_cast(p) -#define __align_up(x, n) (((x) + ((n) - 1)) & ~((n) - 1)) -#define __align_down(x, n) ((x) & -(n)) -#define __page_size 4096 -#define __page_align(n) __align_up(static_cast(n), __page_size) -#define __ptr_align(x) __ptr(__align_down(reinterpret_cast(x), __page_size)) -#define __make_rwx(p, n) ::mprotect(__ptr_align(p), \ - __page_align(__uintval(p) + n) != __page_align(__uintval(p)) ? __page_align(n) + __page_size : __page_align(n), \ +#define _uintval(p) reinterpret_cast(p) +#define _ptr(p) reinterpret_cast(p) +#define _align_up(x, n) (((x) + ((n) - 1)) & ~((n) - 1)) +#define _align_down(x, n) ((x) & -(n)) +#define _page_size 4096 +#define _page_align(n) _align_up(static_cast(n), _page_size) +#define _ptr_align(x) _ptr(_align_down(reinterpret_cast(x), _page_size)) +#define _make_rwx(p, n) ::mprotect(_ptr_align(p), \ + _page_align(_uintval(p) + n) != _page_align(_uintval(p)) ? _page_align(n) + _page_size : _page_align(n), \ PROT_READ | PROT_WRITE | PROT_EXEC) typedef void (*HookFunType)(void *, void *, void **); @@ -97,7 +97,7 @@ namespace edxp { ALWAYS_INLINE inline static void HookFunction(HookFunType hook_fun, void *original, void *replace, void **backup) { - __make_rwx(original, __page_size); + _make_rwx(original, _page_size); hook_fun(original, replace, backup); } diff --git a/edxp-core/src/main/cpp/main/include/config.h b/edxp-core/src/main/cpp/main/include/config.h index 436d180c0..196da24f6 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,23 +19,22 @@ 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 const auto kInjectDexPath = "/system/framework/edxp.dex:" + "/system/framework/eddalvikdx.dex:" + "/system/framework/eddexmaker.dex"_str; - 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 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 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 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 = std::string( LP_SELECT("/system/lib/", @@ -51,7 +51,7 @@ namespace edxp { static const auto kLibFwPath = kLibBasePath + kLibFwName; static const auto kLibFwkPath = kLibBasePath + kLibFwkName; - inline const char *const BoolToString(bool b) { + inline constexpr const char *const BoolToString(bool b) { return b ? "true" : "false"; } } \ No newline at end of file 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..e9b0e83fa 100644 --- a/edxp-core/src/main/cpp/main/src/config_manager.cpp +++ b/edxp-core/src/main/cpp/main/src/config_manager.cpp @@ -14,55 +14,46 @@ #include #include -#include -#include +#include +#include #include "art/runtime/native/native_util.h" #include "config_manager.h" -using namespace std; -using namespace art; - namespace edxp { + namespace fs = std::filesystem; 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); + std::string data_test_path = data_path_prefix_ / kPrimaryInstallerPkgName; + if (fs::exists(data_test_path)) { + 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); + data_test_path = data_path_prefix_ / kLegacyInstallerPkgName; + if (fs::exists(data_test_path)) { + 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; } void ConfigManager::SnapshotBlackWhiteList() { - DIR *dir; - struct dirent *dent; - dir = opendir(whitelist_path_.c_str()); - if (dir != nullptr) { - while ((dent = readdir(dir)) != nullptr) { - if (dent->d_type == DT_REG) { - const char *fileName = dent->d_name; - LOGI(" whitelist: %s", fileName); - white_list_default_.emplace_back(fileName); - } + white_list_default_.clear(); + for (auto &item: fs::directory_iterator(whitelist_path_)) { + if (item.is_regular_file()) { + const auto &file_name = item.path().filename(); + LOGI(" whitelist: %s", file_name.c_str()); + white_list_default_.emplace(file_name); } - closedir(dir); - } - dir = opendir(blacklist_path_.c_str()); - if (dir != nullptr) { - while ((dent = readdir(dir)) != nullptr) { - if (dent->d_type == DT_REG) { - const char *fileName = dent->d_name; - LOGI(" blacklist: %s", fileName); - black_list_default_.emplace_back(fileName); - } + } + black_list_default_.clear(); + for (auto &item: fs::directory_iterator(blacklist_path_)) { + if (item.is_regular_file()) { + const auto &file_name = item.path().filename(); + LOGI(" blacklist: %s", file_name.c_str()); + black_list_default_.emplace(file_name); } - closedir(dir); } } @@ -72,10 +63,8 @@ namespace edxp { last_user_ = user; } - const char *format = use_prot_storage_ ? "/data/user_de/%u/" : "/data/user/%u/"; - char buff[PATH_MAX]; - snprintf(buff, sizeof(buff), format, last_user_); - data_path_prefix_ = buff; + data_path_prefix_ = use_prot_storage_ ? "/data/user_de" : "/data/user"; + data_path_prefix_ /= std::to_string(last_user_); installer_pkg_name_ = RetrieveInstallerPkgName(); base_config_path_ = GetConfigPath(""); @@ -83,15 +72,16 @@ namespace edxp { whitelist_path_ = GetConfigPath("whitelist/"); use_whitelist_path_ = GetConfigPath("usewhitelist"); - dynamic_modules_enabled_ = access(GetConfigPath("dynamicmodules").c_str(), F_OK) == 0; - black_white_list_enabled_ = access(GetConfigPath("blackwhitelist").c_str(), F_OK) == 0; - deopt_boot_image_enabled_ = access(GetConfigPath("deoptbootimage").c_str(), F_OK) == 0; - resources_hook_enabled_ = access(GetConfigPath("enable_resources").c_str(), F_OK) == 0; - no_module_log_enabled_ = access(GetConfigPath("disable_modules_log").c_str(), F_OK) == 0; - hidden_api_bypass_enabled_ = access(GetConfigPath("disable_hidden_api_bypass").c_str(), F_OK) != 0; + dynamic_modules_enabled_ = fs::exists(GetConfigPath("dynamicmodules")); + black_white_list_enabled_ = fs::exists(GetConfigPath("blackwhitelist")); + deopt_boot_image_enabled_ = fs::exists(GetConfigPath("deoptbootimage")); + resources_hook_enabled_ = fs::exists(GetConfigPath("enable_resources")); + no_module_log_enabled_ = fs::exists(GetConfigPath("disable_modules_log")); + hidden_api_bypass_enabled_ = + !fs::exists(GetConfigPath("disable_hidden_api_bypass")); // use_white_list snapshot - use_white_list_snapshot_ = access(use_whitelist_path_.c_str(), F_OK) == 0; + use_white_list_snapshot_ = fs::exists(use_whitelist_path_); LOGI("data path prefix: %s", data_path_prefix_.c_str()); LOGI(" application list mode: %s", BoolToString(black_white_list_enabled_)); LOGI(" using whitelist: %s", BoolToString(use_white_list_snapshot_)); @@ -105,19 +95,32 @@ namespace edxp { } } + std::tuple + ConfigManager::GetAppInfoFromDir(const std::string &app_data_dir) { + uid_t uid = 0; + fs::path path(app_data_dir); + std::vector splits(path.begin(), path.end()); + if (splits.size() < 5u) { + LOGE("can't parse %s", path.c_str()); + return {false, uid, {}}; + } + const auto &uid_str = splits[3]; + const auto &package_name = splits[4]; + try { + uid = stol(uid_str); + } catch (const std::invalid_argument &ignored) { + LOGE("can't parse %s", app_data_dir.c_str()); + return {false, 0, {}}; + } + return {true, uid, package_name}; + } + // TODO ignore unrelated processes bool ConfigManager::IsAppNeedHook(const std::string &app_data_dir) { // zygote always starts with `uid == 0` and then fork into different user. // so we have to check if we are the correct user or not. - uid_t user = 0; - char package_name[PATH_MAX]; - if (sscanf(app_data_dir.c_str(), "/data/%*[^/]/%u/%s", &user, package_name) != 2) { - if (sscanf(app_data_dir.c_str(), "/data/%*[^/]/%s", package_name) != 1) { - package_name[0] = '\0'; - LOGE("can't parse %s", app_data_dir.c_str()); - return false; // default to no hooking for safety - } - } + const auto[res, user, package_name] = GetAppInfoFromDir(app_data_dir); + if (!res) return true; if (last_user_ != user) { UpdateConfigPath(user); @@ -126,17 +129,17 @@ namespace edxp { if (!black_white_list_enabled_) { return true; } - bool can_access_app_data = access(base_config_path_.c_str(), F_OK) == 0; + bool can_access_app_data = fs::exists(base_config_path_); bool use_white_list; if (can_access_app_data) { - use_white_list = access(use_whitelist_path_.c_str(), F_OK) == 0; + use_white_list = fs::exists(use_whitelist_path_); } else { LOGE("can't access config path, using snapshot use_white_list: %s", 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; } @@ -144,80 +147,55 @@ namespace edxp { if (!can_access_app_data) { LOGE("can't access config path, using snapshot white list: %s", app_data_dir.c_str()); - return !(find(white_list_default_.begin(), white_list_default_.end(), - package_name) == - white_list_default_.end()); + return white_list_default_.count(package_name); } - std::string target_path = whitelist_path_ + package_name; - bool res = access(target_path.c_str(), F_OK) == 0; + std::string target_path = whitelist_path_ / package_name; + bool res = fs::exists(target_path); LOGD("using whitelist, %s -> %d", app_data_dir.c_str(), res); return res; } else { if (!can_access_app_data) { LOGE("can't access config path, using snapshot black list: %s", app_data_dir.c_str()); - return find(black_list_default_.begin(), black_list_default_.end(), package_name) == - black_list_default_.end(); + return black_list_default_.count(package_name); } - std::string target_path = blacklist_path_ + package_name; - bool res = access(target_path.c_str(), F_OK) != 0; + std::string target_path = blacklist_path_ / package_name; + bool res = fs::exists(target_path); LOGD("using blacklist, %s -> %d", app_data_dir.c_str(), res); return res; } } - 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 (!fs::exists(global_modules_list)) { + LOGE("Cannot access path %s", global_modules_list.c_str()); + return false; + } + + if (auto last_write_time = fs::last_write_time(global_modules_list); + LIKELY(last_write_time < last_write_time_)) { + return true; + } else { + last_write_time_ = last_write_time; + } + + std::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..543518af8 100644 --- a/edxp-core/src/main/cpp/main/src/config_manager.h +++ b/edxp-core/src/main/cpp/main/src/config_manager.h @@ -3,62 +3,77 @@ #include #include -#include +#include "JNIHelper.h" +#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_; } + + inline auto IsDynamicModulesEnabled() const { return dynamic_modules_enabled_; } - bool IsDynamicModulesEnabled() const; + inline auto IsResourcesHookEnabled() const { return resources_hook_enabled_; } - bool IsResourcesHookEnabled() const; + inline auto IsDeoptBootImageEnabled() const { return deopt_boot_image_enabled_; } - bool IsDeoptBootImageEnabled() const; + inline auto IsNoModuleLogEnabled() const { return no_module_log_enabled_; } - bool IsNoModuleLogEnabled() const; + inline auto IsHiddenAPIBypassEnabled() const { return hidden_api_bypass_enabled_; } - bool IsHiddenAPIBypassEnabled() const; + inline auto GetInstallerPackageName() const { return installer_pkg_name_; } - std::string GetInstallerPackageName() const; + inline auto GetXposedPropPath() const { return kXposedPropPath; } - std::string GetXposedPropPath() const; + inline auto GetLibSandHookName() const { return kLibSandHookName; } - std::string GetLibSandHookName() const; + inline auto GetLibWhaleName() const { return kLibWhaleName; } - std::string GetLibWhaleName() const; + inline auto GetDataPathPrefix() const { return data_path_prefix_; } - std::string GetDataPathPrefix() const; + inline auto GetConfigPath(const std::string &suffix) const { + return data_path_prefix_ / installer_pkg_name_ / "conf" / suffix; + } - std::string GetConfigPath(const std::string &suffix) const; + inline auto GetModulesList() const { return modules_list_.get(); } bool IsAppNeedHook(const std::string &app_data_dir); - bool hidden_api_bypass_enabled_ = false; + bool UpdateModuleList(); + + static std::tuple + GetAppInfoFromDir(const std::string &app_data_dir); + 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_; - std::string installer_pkg_name_; - std::string base_config_path_; - std::string blacklist_path_; - std::string whitelist_path_; - std::string use_whitelist_path_; + std::filesystem::path data_path_prefix_; + std::filesystem::path installer_pkg_name_; + std::filesystem::path base_config_path_; + std::filesystem::path blacklist_path_; + std::filesystem::path whitelist_path_; + std::filesystem::path use_whitelist_path_; bool black_white_list_enabled_ = false; bool dynamic_modules_enabled_ = false; bool deopt_boot_image_enabled_ = false; @@ -66,8 +81,13 @@ namespace edxp { bool resources_hook_enabled_ = false; // snapshot at boot bool use_white_list_snapshot_ = false; - std::vector white_list_default_; - std::vector black_list_default_; + std::unordered_set white_list_default_; + std::unordered_set black_list_default_; + bool hidden_api_bypass_enabled_ = false; + + std::unique_ptr modules_list_ = nullptr; + + std::filesystem::file_time_type last_write_time_; ConfigManager(); @@ -76,6 +96,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..19b251193 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()); + LOGD("Loaded %s with size %zu", 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,15 @@ 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()); + ConfigManager::GetInstance()->UpdateModuleList(); + PreLoadDex(env, kInjectDexPath); } @@ -251,15 +246,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 +260,16 @@ 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 (!dir || !ConfigManager::GetInstance()->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); + 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..5dcc5b940 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,29 @@ 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 InjectDexAndInit(JNIEnv *env); - void LoadDexAndInit(JNIEnv *env, const char *dex_path); + 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-core/template_override/customize.sh b/edxp-core/template_override/customize.sh index e6838879a..364a98663 100644 --- a/edxp-core/template_override/customize.sh +++ b/edxp-core/template_override/customize.sh @@ -36,18 +36,18 @@ PROP_PRODUCT=$(getprop ro.build.product) PROP_BRAND=$(getprop ro.product.brand) PROP_MANUFACTURER=$(getprop ro.product.manufacturer) -JAR_EDXP="$(getRandomNameExist 8 "" ".jar" " +JAR_EDXP="$(getRandomNameExist 8 "" ".dex" " /system/framework -").jar" -JAR_EDDALVIKDX="$(getRandomNameExist 8 "" ".jar" " +").dex" +JAR_EDDALVIKDX="$(getRandomNameExist 8 "" ".dex" " /system/framework -").jar" -JAR_EDDEXMAKER="$(getRandomNameExist 8 "" ".jar" " +").dex" +JAR_EDDEXMAKER="$(getRandomNameExist 8 "" ".dex" " /system/framework -").jar" -JAR_EDCONFIG="$(getRandomNameExist 8 "" ".jar" " -/system/framework -").jar" +").dex" +#JAR_EDCONFIG="$(getRandomNameExist 8 "" ".jar" " +#/system/framework +#").jar" LIB_RIRU_EDXP="libriru_${RIRU_EDXP}.so" LIB_WHALE_EDXP="lib$(getRandomNameExist 10 "lib" ".so" " /system/lib @@ -290,10 +290,10 @@ fi ui_print "- Copying framework libraries" -mv "${MODPATH}/system/framework/eddalvikdx.jar" "${MODPATH}/system/framework/${JAR_EDDALVIKDX}" -mv "${MODPATH}/system/framework/edxp.jar" "${MODPATH}/system/framework/${JAR_EDXP}" -mv "${MODPATH}/system/framework/eddexmaker.jar" "${MODPATH}/system/framework/${JAR_EDDEXMAKER}" -mv "${MODPATH}/system/framework/edconfig.jar" "${MODPATH}/system/framework/${JAR_EDCONFIG}" +mv "${MODPATH}/system/framework/eddalvikdx.dex" "${MODPATH}/system/framework/${JAR_EDDALVIKDX}" +mv "${MODPATH}/system/framework/edxp.dex" "${MODPATH}/system/framework/${JAR_EDXP}" +mv "${MODPATH}/system/framework/eddexmaker.dex" "${MODPATH}/system/framework/${JAR_EDDEXMAKER}" +#mv "${MODPATH}/system/framework/edconfig.jar" "${MODPATH}/system/framework/${JAR_EDCONFIG}" mv "${MODPATH}/system/lib/libriru_edxp.so" "${MODPATH}/system/lib/${LIB_RIRU_EDXP}" mv "${MODPATH}/system/lib/libwhale.edxp.so" "${MODPATH}/system/lib/${LIB_WHALE_EDXP}" mv "${MODPATH}/system/lib/libsandhook-native.so" "${MODPATH}/system/lib/libsandhook-native.so" @@ -313,15 +313,15 @@ fi ui_print "- Resetting libraries path" -sed -i 's:/system/framework/edxp.jar\:/system/framework/eddalvikdx.jar\:/system/framework/eddexmaker.jar:/system/framework/'"${JAR_EDXP}"'\:/system/framework/'"${JAR_EDDALVIKDX}"'\:/system/framework/'"${JAR_EDDEXMAKER}"':g' "${MODPATH}/system/lib/${LIB_RIRU_EDXP}" -sed -i 's:/system/framework/edconfig.jar:/system/framework/'"${JAR_EDCONFIG}"':g' "${MODPATH}/system/lib/${LIB_RIRU_EDXP}" +sed -i 's:/system/framework/edxp.dex\:/system/framework/eddalvikdx.dex\:/system/framework/eddexmaker.dex:/system/framework/'"${JAR_EDXP}"'\:/system/framework/'"${JAR_EDDALVIKDX}"'\:/system/framework/'"${JAR_EDDEXMAKER}"':g' "${MODPATH}/system/lib/${LIB_RIRU_EDXP}" +#sed -i 's:/system/framework/edconfig.jar:/system/framework/'"${JAR_EDCONFIG}"':g' "${MODPATH}/system/lib/${LIB_RIRU_EDXP}" sed -i 's:libriru_edxp.so:'"${LIB_RIRU_EDXP}"':g' "${MODPATH}/system/lib/${LIB_RIRU_EDXP}" sed -i 's:libwhale.edxp.so:'"${LIB_WHALE_EDXP}"':g' "${MODPATH}/system/lib/${LIB_RIRU_EDXP}" sed -i 's:libsandhook.edxp.so:'"${LIB_SANDHOOK_EDXP}"':g' "${MODPATH}/system/lib/${LIB_RIRU_EDXP}" if [[ "${IS64BIT}" == true ]]; then - sed -i 's:/system/framework/edxp.jar\:/system/framework/eddalvikdx.jar\:/system/framework/eddexmaker.jar:/system/framework/'"${JAR_EDXP}"'\:/system/framework/'"${JAR_EDDALVIKDX}"'\:/system/framework/'"${JAR_EDDEXMAKER}"':g' "${MODPATH}/system/lib64/${LIB_RIRU_EDXP}" - sed -i 's:/system/framework/edconfig.jar:/system/framework/'"${JAR_EDCONFIG}"':g' "${MODPATH}/system/lib64/${LIB_RIRU_EDXP}" + sed -i 's:/system/framework/edxp.dex\:/system/framework/eddalvikdx.dex\:/system/framework/eddexmaker.dex:/system/framework/'"${JAR_EDXP}"'\:/system/framework/'"${JAR_EDDALVIKDX}"'\:/system/framework/'"${JAR_EDDEXMAKER}"':g' "${MODPATH}/system/lib64/${LIB_RIRU_EDXP}" +# sed -i 's:/system/framework/edconfig.jar:/system/framework/'"${JAR_EDCONFIG}"':g' "${MODPATH}/system/lib64/${LIB_RIRU_EDXP}" sed -i 's:libriru_edxp.so:'"${LIB_RIRU_EDXP}"':g' "${MODPATH}/system/lib64/${LIB_RIRU_EDXP}" sed -i 's:libwhale.edxp.so:'"${LIB_WHALE_EDXP}"':g' "${MODPATH}/system/lib64/${LIB_RIRU_EDXP}" sed -i 's:libsandhook.edxp.so:'"${LIB_SANDHOOK_EDXP}"':g' "${MODPATH}/system/lib64/${LIB_RIRU_EDXP}" diff --git a/edxp-core/template_override/sepolicy.rule b/edxp-core/template_override/sepolicy.rule index 3b02a68ce..5e733424d 100644 --- a/edxp-core/template_override/sepolicy.rule +++ b/edxp-core/template_override/sepolicy.rule @@ -2,5 +2,5 @@ allow system_server system_server process {execmem} allow system_server system_server memprotect {mmap_zero} allow coredomain coredomain process {execmem} allow coredomain app_data_file * * -attradd {system_app platform_app} mlstrustedsubject +attradd { system_app platform_app } mlstrustedsubject allow zygote apk_data_file * * diff --git a/edxp-sandhook/.gitignore b/edxp-sandhook/.gitignore index 845f99801..3a66a1982 100644 --- a/edxp-sandhook/.gitignore +++ b/edxp-sandhook/.gitignore @@ -1,2 +1,2 @@ /build -/template_override/system/framework/edxp.jar \ No newline at end of file +/template_override/system/framework \ No newline at end of file diff --git a/edxp-sandhook/build.gradle b/edxp-sandhook/build.gradle index f1e426488..01a8fc9b2 100644 --- a/edxp-sandhook/build.gradle +++ b/edxp-sandhook/build.gradle @@ -22,10 +22,11 @@ android { } } + ndkVersion androidCompileNdkVersion } dependencies { - compileOnly files("${hiddenApiStubJarFilePath}") + compileOnly project(':hiddenapi-stubs') implementation project(':edxp-common') implementation 'com.swift.sandhook:hooklib:4.2.1' compileOnly project(':dexmaker') @@ -59,18 +60,37 @@ afterEvaluate { def myTemplatePath = "${projectDir}/template_override/" + task("copyDex${variantNameCapped}", type: Copy) { + dependsOn "assemble${variantNameCapped}" + dependsOn tasks.getByPath(":edxp-common:copyCommonProperties") + def dexOutPath = "${buildDir}/intermediates/dex/${variantNameLowered}/minify${variantNameCapped}WithR8" + 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") ? - "${buildDir}/intermediates/transforms/dexMerger/${variantNameLowered}/0/" : - "${buildDir}/intermediates/dex/${variantNameLowered}/mergeDex${variantNameCapped}/out/" - from dexOutPath, "${projectDir}/src/main/resources/" + def dexOutPath = "${buildDir}/intermediates/dex/${variantNameLowered}/mergeDex${variantNameCapped}" + from (dexOutPath){ + rename("classes.dex", "edxp.dex") + } + from "${projectDir}/src/main/resources/" destinationDir file(myTemplatePath + "system/framework/") baseName "edxp" doLast { copy { from file(myTemplatePath) into file(templateRootPath) + include "*.dex" } } outputs.upToDateWhen { false } diff --git a/edxp-sandhook/proguard-rules.pro b/edxp-sandhook/proguard-rules.pro index 520e46fdc..326879b61 100644 --- a/edxp-sandhook/proguard-rules.pro +++ b/edxp-sandhook/proguard-rules.pro @@ -32,6 +32,6 @@ -keep class com.swift.sandhook.** {*;} --keepclasseswithmember class * { +-keepclasseswithmembers class * { native ; } \ No newline at end of file diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/SandHookRouter.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/SandHookRouter.java index 9f621f803..b5a9a792f 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/SandHookRouter.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/SandHookRouter.java @@ -7,7 +7,6 @@ import com.elderdrivers.riru.edxp.sandhook.entry.AppBootstrapHookInfo; import com.elderdrivers.riru.edxp.sandhook.entry.SysBootstrapHookInfo; import com.elderdrivers.riru.edxp.sandhook.entry.SysInnerHookInfo; -import com.elderdrivers.riru.edxp.sandhook.entry.WorkAroundHookInfo; import com.elderdrivers.riru.edxp.sandhook.hooker.SystemMainHooker; import com.elderdrivers.riru.edxp.util.Utils; import com.swift.sandhook.xposedcompat.XposedCompat; @@ -45,14 +44,6 @@ public void startSystemServerHook() { } } - public void startWorkAroundHook() { - if (useSandHook) { - XposedCompat.addHookers(XposedBridge.BOOTCLASSLOADER, WorkAroundHookInfo.hookItems); - } else { - super.startWorkAroundHook(); - } - } - public void onEnterChildProcess() { SandHookXposedBridge.onForkPost(); //enable compile in child process diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/AppBootstrapHookInfo.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/AppBootstrapHookInfo.java index 35d215ca6..c976a6c25 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/AppBootstrapHookInfo.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/AppBootstrapHookInfo.java @@ -3,11 +3,9 @@ import com.elderdrivers.riru.common.KeepMembers; import com.elderdrivers.riru.edxp.sandhook.hooker.HandleBindAppHooker; import com.elderdrivers.riru.edxp.sandhook.hooker.LoadedApkConstructorHooker; -import com.elderdrivers.riru.edxp.sandhook.hooker.OnePlusWorkAroundHooker; public class AppBootstrapHookInfo implements KeepMembers { public static String[] hookItemNames = { - OnePlusWorkAroundHooker.class.getName(), HandleBindAppHooker.class.getName(), LoadedApkConstructorHooker.class.getName(), }; @@ -15,6 +13,5 @@ public class AppBootstrapHookInfo implements KeepMembers { public static Class[] hookItems = { HandleBindAppHooker.class, LoadedApkConstructorHooker.class, - OnePlusWorkAroundHooker.class }; } diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/SysBootstrapHookInfo.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/SysBootstrapHookInfo.java index 434a9f344..25e9d9fc0 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/SysBootstrapHookInfo.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/SysBootstrapHookInfo.java @@ -3,12 +3,10 @@ import com.elderdrivers.riru.common.KeepMembers; import com.elderdrivers.riru.edxp.sandhook.hooker.HandleBindAppHooker; import com.elderdrivers.riru.edxp.sandhook.hooker.LoadedApkConstructorHooker; -import com.elderdrivers.riru.edxp.sandhook.hooker.OnePlusWorkAroundHooker; import com.elderdrivers.riru.edxp.sandhook.hooker.SystemMainHooker; public class SysBootstrapHookInfo implements KeepMembers { public static String[] hookItemNames = { - OnePlusWorkAroundHooker.class.getName(), HandleBindAppHooker.class.getName(), SystemMainHooker.class.getName(), LoadedApkConstructorHooker.class.getName() @@ -18,6 +16,5 @@ public class SysBootstrapHookInfo implements KeepMembers { HandleBindAppHooker.class, SystemMainHooker.class, LoadedApkConstructorHooker.class, - OnePlusWorkAroundHooker.class }; } diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/WorkAroundHookInfo.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/WorkAroundHookInfo.java deleted file mode 100644 index cb7031bba..000000000 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/WorkAroundHookInfo.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.elderdrivers.riru.edxp.sandhook.entry; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.sandhook.hooker.OnePlusWorkAroundHooker; - -public class WorkAroundHookInfo implements KeepMembers { - public static String[] hookItemNames = { - OnePlusWorkAroundHooker.class.getName() - }; - - public static Class[] hookItems = { - OnePlusWorkAroundHooker.class - }; -} 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/.gitignore b/edxp-whale/.gitignore index 845f99801..3a66a1982 100644 --- a/edxp-whale/.gitignore +++ b/edxp-whale/.gitignore @@ -1,2 +1,2 @@ /build -/template_override/system/framework/edxp.jar \ No newline at end of file +/template_override/system/framework \ No newline at end of file diff --git a/edxp-whale/build.gradle b/edxp-whale/build.gradle index 76a1d7fb2..ed706ecf7 100644 --- a/edxp-whale/build.gradle +++ b/edxp-whale/build.gradle @@ -22,10 +22,11 @@ android { } } + ndkVersion androidCompileNdkVersion } dependencies { - compileOnly files("${hiddenApiStubJarFilePath}") + compileOnly project(':hiddenapi-stubs') implementation project(':edxp-common') compileOnly project(':dexmaker') } @@ -58,6 +59,24 @@ afterEvaluate { def myTemplatePath = "${projectDir}/template_override/" + task("copyDex${variantNameCapped}", type: Copy) { + dependsOn "assemble${variantNameCapped}" + dependsOn tasks.getByPath(":edxp-common:copyCommonProperties") + def dexOutPath = "${buildDir}/intermediates/dex/${variantNameLowered}/minify${variantNameCapped}WithR8" + 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) + include "*.dex" + } + } + } + task("makeAndCopy${variantNameCapped}", type: Jar, dependsOn: "assemble${variantNameCapped}") { dependsOn tasks.getByPath(":edxp-common:copyCommonProperties") def dexOutPath = variant.name.contains("release") ? diff --git a/edxp-whale/proguard-rules.pro b/edxp-whale/proguard-rules.pro index 503061cbb..778f479ab 100644 --- a/edxp-whale/proguard-rules.pro +++ b/edxp-whale/proguard-rules.pro @@ -32,6 +32,6 @@ -keep class com.lody.** {*;} --keepclasseswithmember class * { +-keepclasseswithmembers class * { native ; } \ No newline at end of file diff --git a/edxp-yahfa/.gitignore b/edxp-yahfa/.gitignore index 845f99801..3a66a1982 100644 --- a/edxp-yahfa/.gitignore +++ b/edxp-yahfa/.gitignore @@ -1,2 +1,2 @@ /build -/template_override/system/framework/edxp.jar \ No newline at end of file +/template_override/system/framework \ No newline at end of file diff --git a/edxp-yahfa/build.gradle b/edxp-yahfa/build.gradle index f142309c1..2c2a1ad3c 100644 --- a/edxp-yahfa/build.gradle +++ b/edxp-yahfa/build.gradle @@ -22,10 +22,11 @@ android { } } + ndkVersion androidCompileNdkVersion } dependencies { - compileOnly files("${hiddenApiStubJarFilePath}") + compileOnly project(':hiddenapi-stubs') implementation project(':edxp-common') compileOnly project(':dexmaker') } @@ -58,6 +59,23 @@ afterEvaluate { def myTemplatePath = "${projectDir}/template_override/" + task("copyDex${variantNameCapped}", type: Copy) { + dependsOn "assemble${variantNameCapped}" + dependsOn tasks.getByPath(":edxp-common:copyCommonProperties") + def dexOutPath = "${buildDir}/intermediates/dex/${variantNameLowered}/minify${variantNameCapped}WithR8" + 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") ? @@ -70,6 +88,7 @@ afterEvaluate { copy { from file(myTemplatePath) into file(templateRootPath) + include "*.dex" } } outputs.upToDateWhen { false } diff --git a/edxp-yahfa/proguard-rules.pro b/edxp-yahfa/proguard-rules.pro index c600fee6c..90c50a020 100644 --- a/edxp-yahfa/proguard-rules.pro +++ b/edxp-yahfa/proguard-rules.pro @@ -30,6 +30,6 @@ -keep class * implements com.elderdrivers.riru.common.KeepAll { *; } -keepclassmembers class * implements com.elderdrivers.riru.common.KeepMembers { *; } --keepclasseswithmember class * { +-keepclasseswithmembers 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.properties b/gradle.properties index a19ed5f95..be668d74a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,2 @@ -android.enableR8=false - -androidCompileSdkVersion=30 \ No newline at end of file +androidCompileSdkVersion=30 +androidCompileNdkVersion=22.0.6917172 rc1 \ No newline at end of file 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/hiddenapi-stubs/build.gradle b/hiddenapi-stubs/build.gradle index beb26cf19..513c00e2c 100644 --- a/hiddenapi-stubs/build.gradle +++ b/hiddenapi-stubs/build.gradle @@ -7,8 +7,9 @@ android { } task makeStubJar(type: Jar){ + dependsOn assemble baseName 'framework-stub' - from("${projectDir}/build/intermediates/javac/release/compileReleaseJavaWithJavac/classes/") + from("${projectDir}/build/intermediates/javac/release/classes/") into('') destinationDir file("${projectDir}/libs") exclude('BuildConfig.class', 'R.class') diff --git a/xposed-bridge/build.gradle b/xposed-bridge/build.gradle index a4ed4a4a4..1e9e58dc6 100644 --- a/xposed-bridge/build.gradle +++ b/xposed-bridge/build.gradle @@ -2,7 +2,6 @@ apply plugin: 'com.android.library' android { compileSdkVersion androidCompileSdkVersion.toInteger() - buildToolsVersion '28.0.3' defaultConfig { minSdkVersion 26 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; }