diff --git a/build.gradle b/build.gradle index 5db8a85be..ddd888e98 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 @@ -24,7 +23,7 @@ allprojects { templateLibPath = templateRootPath + "/system/lib/" templateLib64Path = templateRootPath + "/system/lib64/" templateEtcPath = templateRootPath + "/system/etc/" - hiddenApiStubJarFilePath = project(":hiddenapi-stubs").projectDir.absolutePath + "/libs/framework-stub.jar" + hiddenApiStubJarFilePath = project(":hiddenapi-stubs").buildDir.absolutePath + "/libs/framework-stub.jar" } repositories { google() 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..a1d358bc5 100644 --- a/dalvikdx/build.gradle +++ b/dalvikdx/build.gradle @@ -1,47 +1,33 @@ -import org.gradle.internal.os.OperatingSystem -apply plugin: 'java-library' +apply plugin: 'com.android.application' -dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) +repositories { + jcenter() } -sourceCompatibility = "7" -targetCompatibility = "7" - -task findDx { - if (OperatingSystem.current().isWindows()){ - return true - } - doLast { - new ByteArrayOutputStream().withStream { os -> - exec { - commandLine "which", "dx" - standardOutput os - } - rootProject.ext.dxPath = os.toString() - } - } +android { + compileSdkVersion androidCompileSdkVersion.toInteger() + ndkVersion androidCompileNdkVersion } -task dexInJar(type: Jar) { - 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}" +afterEvaluate { + android.applicationVariants.all { variant -> + def variantNameCapped = variant.name.capitalize() + def variantNameLowered = variant.name.toLowerCase() + + task("copyDex${variantNameCapped}", type: Copy) { + dependsOn "assemble${variantNameCapped}" + def dexOutPath = "${buildDir}/intermediates/dex/${variantNameLowered}/mergeDex${variantNameCapped}" + from (dexOutPath){ + rename("classes.dex", "eddalvikdx.dex") } + destinationDir file(templateRootPath + "system/framework/") + outputs.upToDateWhen { false } + } + task("makeJar${variantNameCapped}", type: Jar, dependsOn: "assemble${variantNameCapped}") { + dependsOn "assemble${variantNameCapped}" + from "${buildDir}/intermediates/javac/${variantNameLowered}/classes" + baseName "dalvikdx" + outputs.file(archivePath) } } - from "${jar.destinationDir}/classes.dex" - destinationDir jar.destinationDir - baseName "eddalvikdx" - onlyIf { - !jar.state.upToDate || !file(archiveName).exists() - } -} \ No newline at end of file +} diff --git a/dalvikdx/src/main/AndroidManifest.xml b/dalvikdx/src/main/AndroidManifest.xml new file mode 100644 index 000000000..7474421e8 --- /dev/null +++ b/dalvikdx/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + 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..a3a6cc1b5 100644 --- a/dexmaker/build.gradle +++ b/dexmaker/build.gradle @@ -1,37 +1,39 @@ -import org.gradle.internal.os.OperatingSystem -apply plugin: 'java' +apply plugin: 'com.android.application' description = "A utility for doing compile or runtime code generation targeting Android's Dalvik VM" -targetCompatibility = '1.7' -sourceCompatibility = '1.7' - repositories { jcenter() } +android { + compileSdkVersion androidCompileSdkVersion.toInteger() + ndkVersion androidCompileNdkVersion +} + dependencies { - compileOnly project(':dalvikdx') + compileOnly files(project(":dalvikdx").tasks.getByName("makeJarRelease").outputs) } -task dexInJar(type: Jar) { - 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}" +afterEvaluate { + android.applicationVariants.all { variant -> + def variantNameCapped = variant.name.capitalize() + def variantNameLowered = variant.name.toLowerCase() + + task("copyDex${variantNameCapped}", type: Copy) { + dependsOn "assemble${variantNameCapped}" + def dexOutPath = "${buildDir}/intermediates/dex/${variantNameLowered}/mergeDex${variantNameCapped}" + from (dexOutPath){ + rename("classes.dex", "eddexmaker.dex") } + destinationDir file(templateRootPath + "system/framework/") + outputs.upToDateWhen { false } + } + task("makeJar${variantNameCapped}", type: Jar, dependsOn: "assemble${variantNameCapped}") { + dependsOn "assemble${variantNameCapped}" + from "${buildDir}/intermediates/javac/${variantNameLowered}/classes" + baseName "dexmaker" + outputs.file(archivePath) } } - from "${jar.destinationDir}/classes.dex" - destinationDir jar.destinationDir - baseName "eddexmaker" - onlyIf { - !jar.state.upToDate || !file(archiveName).exists() - } -} +} \ No newline at end of file diff --git a/dexmaker/src/main/AndroidManifest.xml b/dexmaker/src/main/AndroidManifest.xml new file mode 100644 index 000000000..419831dd1 --- /dev/null +++ b/dexmaker/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + 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/proguard-rules.pro b/edxp-common/proguard-rules.pro index 721fdf5cf..427bf7d0a 100644 --- a/edxp-common/proguard-rules.pro +++ b/edxp-common/proguard-rules.pro @@ -21,6 +21,7 @@ #-renamesourcefileattribute SourceFile -dontobfuscate +-dontoptimize -keep class de.robv.android.xposed.** {*;} -keep class android.** { *; } 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..c8a14d96d 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 @@ -49,5 +49,5 @@ 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 42db5a690..e80bd37d0 100644 --- a/edxp-core/build.gradle +++ b/edxp-core/build.gradle @@ -4,7 +4,7 @@ import org.gradle.internal.os.OperatingSystem apply plugin: 'com.android.library' // Values set here will be overriden by AppVeyor, feel free to modify during development. -def buildVersionName = 'v0.5.0.6' +def buildVersionName = 'v0.5.0.8' def buildVersionCode = 233 if (System.env.APPVEYOR_BUILD_VERSION != null) { @@ -49,8 +49,8 @@ android { externalNativeBuild { cmake { abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64' - cppFlags "-std=c++17 -ffixed-x18 -Qunused-arguments -frtti" - cFlags "-std=gnu99 -ffixed-x18 -Qunused-arguments -frtti" + cppFlags "-std=c++17 -ffixed-x18 -Qunused-arguments -frtti -fomit-frame-pointer" + cFlags "-std=gnu99 -ffixed-x18 -Qunused-arguments -frtti -fomit-frame-pointer" arguments "-DRIRU_MODULE_API_VERSION=$moduleMaxRiruApiVersion", "-DRIRU_MODULE_VERSION=$buildVersionCode", "-DRIRU_MODULE_VERSION_NAME:STRING=\"$buildVersionName\"" @@ -70,8 +70,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 @@ -83,34 +83,7 @@ android { path "src/main/cpp/CMakeLists.txt" } } -} - -task copyDalvikdxJar { - def jarTask = tasks.getByPath(':dalvikdx:dexInJar') - dependsOn jarTask - doLast { - copy { - from jarTask - into jar_dest_dir - } - } - onlyIf { - !jarTask.state.upToDate || !file(jar_dest_dir + jarTask.archiveName).exists() - } -} - -task copyDexmakerJar { - def jarTask = tasks.getByPath(':dexmaker:dexInJar') - dependsOn jarTask - doLast { - copy { - from jarTask - into jar_dest_dir - } - } - onlyIf { - !jarTask.state.upToDate || !file(jar_dest_dir + jarTask.archiveName).exists() - } + ndkVersion androidCompileNdkVersion } task cleanTemplate(type: Delete) { @@ -132,8 +105,10 @@ 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 + dependsOn tasks.getByPath(":dexmaker:copyDex${variantCapped}") + dependsOn tasks.getByPath(":dalvikdx:copyDex${variantCapped}") + dependsOn tasks.getByPath(":edxp-${backendLowered}:copyDex${variantCapped}") } def prepareMagiskFilesTask = task("prepareMagiskFiles${backendCapped}${variantCapped}", type: Delete) { @@ -220,7 +195,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 cd0a9acd7..def24080b 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,39 +19,31 @@ 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 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/", "/system/lib64/")); - static const auto kLinkerPath = std::string( - LP_SELECT("/apex/com.android.runtime/bin/linker", - "/apex/com.android.runtime/bin/linker64")); - - static const auto kLibDlPath = kLibBasePath + kLibDlName; static const auto kLibArtLegacyPath = kLibBasePath + kLibArtName; static const auto kLibSandHookPath = kLibBasePath + kLibSandHookName; static const auto kLibSandHookNativePath = kLibBasePath + kLibSandHookNativeName; 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/framework/fd_utils.h b/edxp-core/src/main/cpp/main/include/framework/fd_utils.h deleted file mode 100644 index 8fe4190c4..000000000 --- a/edxp-core/src/main/cpp/main/include/framework/fd_utils.h +++ /dev/null @@ -1,38 +0,0 @@ - -#pragma once - -#include -#include "base/object.h" - -namespace android { - - // Static whitelist of open paths that the zygote is allowed to keep open. - static const char *kPathWhitelist[] = { - "/data/app/", - "/data/app-private/" - }; - - class FileDescriptorWhitelist : public edxp::HookedObject { - - public: - FileDescriptorWhitelist(void *thiz) : HookedObject(thiz) {} - - static void Setup(void *handle, HookFunType hook_func) { - HOOK_FUNC(IsAllowed, - "_ZNK23FileDescriptorWhitelist9IsAllowedERKNSt3__112" - "basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE"); - } - - private: - - CREATE_HOOK_STUB_ENTRIES(bool, IsAllowed, void *thiz, const std::string &path) { - for (const auto &whitelist_path : kPathWhitelist) { - if (android::base::StartsWith(path, whitelist_path)) - return true; - } - return IsAllowedBackup(thiz, path); - } - - }; - -} \ 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 01e381848..9298749b9 100644 --- a/edxp-core/src/main/cpp/main/include/logging.h +++ b/edxp-core/src/main/cpp/main/include/logging.h @@ -1,15 +1,12 @@ #ifndef _LOGGING_H #define _LOGGING_H -#include -#include "android/log.h" +#include #ifndef LOG_TAG #define LOG_TAG "EdXposed" #endif -#include "config.h" - #ifdef LOG_DISABLED #define LOGD(...) #define LOGV(...) @@ -17,7 +14,7 @@ #define LOGW(...) #define LOGE(...) #else -#ifndef NDEBUG +#if 1 #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..33a9d02c1 --- /dev/null +++ b/edxp-core/src/main/cpp/main/include/utils.h @@ -0,0 +1,23 @@ +// +// Created by loves on 11/13/2020. +// +#pragma once + +#include +#include +#include "logging.h" + +namespace edxp { + inline const std::string operator ""_str(const char *str, std::size_t size) { + return {str, size}; + } + + inline bool path_exists(const std::filesystem::path &path) { + try { + return std::filesystem::exists(path); + } catch (const std::filesystem::filesystem_error &e) { + LOGE("%s", e.what()); + return false; + } + } +} 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..3167cc6ce 100644 --- a/edxp-core/src/main/cpp/main/src/config_manager.cpp +++ b/edxp-core/src/main/cpp/main/src/config_manager.cpp @@ -14,68 +14,62 @@ #include #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 (path_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 (path_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(); + black_list_default_.clear(); + try { + 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); + 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); + } catch (const fs::filesystem_error &e) { + LOGE("%s", e.what()); } } void ConfigManager::UpdateConfigPath(const uid_t user) { - if (last_user_ != user) { - LOGI("updating config data paths from %u to %u...", last_user_, user); - last_user_ = user; - } + if (LIKELY(last_user_ == user && instance_)) return; - 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; + LOGI("updating config data paths from %u to %u...", last_user_, user); + last_user_ = user; + + 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 +77,20 @@ 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_ = path_exists(GetConfigPath("dynamicmodules")); + black_white_list_enabled_ = path_exists(GetConfigPath("blackwhitelist")); + deopt_boot_image_enabled_ = path_exists(GetConfigPath("deoptbootimage")); + resources_hook_enabled_ = path_exists(GetConfigPath("enable_resources")); + no_module_log_enabled_ = path_exists(GetConfigPath("disable_modules_log")); + hidden_api_bypass_enabled_ = + !path_exists(GetConfigPath("disable_hidden_api_bypass")); + modules_list_.clear(); + app_modules_list_.clear(); + + UpdateModuleList(); // use_white_list snapshot - use_white_list_snapshot_ = access(use_whitelist_path_.c_str(), F_OK) == 0; + use_white_list_snapshot_ = path_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,119 +104,130 @@ namespace edxp { } } + std::string ConfigManager::GetPackageNameFromBaseApkPath(const fs::path &path) { + std::vector paths(path.begin(), path.end()); + auto base_apk = paths.back(); // base.apk + if (base_apk != "base.apk") return {}; + paths.pop_back(); + auto pkg_name_with_obfuscation = paths.back(); + if (auto pos = pkg_name_with_obfuscation.find('-'); pos != std::string::npos) { + return pkg_name_with_obfuscation.substr(0, pos); + } + return {}; + } + // TODO ignore unrelated processes - bool ConfigManager::IsAppNeedHook(const std::string &app_data_dir) { + bool ConfigManager::IsAppNeedHook(const uid_t user, const std::string &package_name) { // 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 - } - } - - if (last_user_ != user) { - UpdateConfigPath(user); - } + UpdateConfigPath(user); 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 = path_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 = path_exists(use_whitelist_path_); } else { LOGE("can't access config path, using snapshot use_white_list: %s", - app_data_dir.c_str()); + package_name.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; } if (use_white_list) { 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()); + package_name.c_str()); + 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; - LOGD("using whitelist, %s -> %d", app_data_dir.c_str(), res); + std::string target_path = whitelist_path_ / package_name; + bool res = path_exists(target_path); + LOGD("using whitelist, %s -> %d", package_name.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(); + package_name.c_str()); + 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; - LOGD("using blacklist, %s -> %d", app_data_dir.c_str(), res); + std::string target_path = blacklist_path_ / package_name; + bool res = !path_exists(target_path); + LOGD("using blacklist, %s -> %d", package_name.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; + ConfigManager::ConfigManager() { + use_prot_storage_ = GetAndroidApiLevel() >= __ANDROID_API_N__; + last_user_ = 0; + UpdateConfigPath(last_user_); } - ALWAYS_INLINE std::string ConfigManager::GetLibSandHookName() const { - return kLibSandHookName; - } + bool ConfigManager::UpdateModuleList() { + if (LIKELY(!modules_list_.empty()) && !IsDynamicModulesEnabled()) + return true; + modules_list_.clear(); + auto global_modules_list = GetConfigPath("modules.list"); + if (!path_exists(global_modules_list)) { + LOGE("Cannot access path %s", global_modules_list.c_str()); + return false; + } - ALWAYS_INLINE std::string ConfigManager::GetLibWhaleName() const { - return kLibWhaleName; - } + 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; + } - ALWAYS_INLINE std::string ConfigManager::GetDataPathPrefix() const { - return data_path_prefix_; + std::ifstream ifs(global_modules_list); + if (!ifs.good()) { + LOGE("Cannot access path %s", global_modules_list.c_str()); + return false; + } + std::string module; + while (std::getline(ifs, module)) { + const auto &module_pkg_name = GetPackageNameFromBaseApkPath(module); + modules_list_.emplace_back(std::move(module), std::unordered_set{}); + const auto &module_scope_conf = GetConfigPath(module_pkg_name + ".conf"); + if (!path_exists(module_scope_conf)) { + LOGD("module scope is not set for %s", module_pkg_name.c_str()); + continue; + } + std::ifstream ifs_c(module_scope_conf); + if (!ifs_c.good()) { + LOGE("Cannot access path %s", module_scope_conf.c_str()); + continue; + } + auto &scope = modules_list_.back().second; + std::string app_pkg_name; + while (std::getline(ifs_c, app_pkg_name)) { + if (!app_pkg_name.empty()) + scope.emplace(std::move(app_pkg_name)); + } + scope.insert(module_pkg_name); // Always add module itself + LOGD("scope of %s is:\n%s", module_pkg_name.c_str(), ([&scope]() { + std::ostringstream join; + std::copy(scope.begin(), scope.end(), + std::ostream_iterator(join, "\n")); + return join.str(); + })().c_str()); + } + return true; } - 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::UpdateAppModuleList(const uid_t user, const std::string &pkg_name) { + UpdateConfigPath(user); + app_modules_list_.clear(); + for (const auto&[module, scope]: modules_list_) { + if (scope.empty() || scope.count(pkg_name)) app_modules_list_.push_back(module); + } + return !app_modules_list_.empty() || pkg_name == installer_pkg_name_; } } \ 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..9047417ce 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 +#include +#include "config.h" 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_); + } - bool IsDynamicModulesEnabled() const; + inline auto IsBlackWhiteListEnabled() const { return black_white_list_enabled_; } - bool IsResourcesHookEnabled() const; + inline auto IsDynamicModulesEnabled() const { return dynamic_modules_enabled_; } - bool IsDeoptBootImageEnabled() const; + inline auto IsResourcesHookEnabled() const { return resources_hook_enabled_; } - bool IsNoModuleLogEnabled() const; + inline auto IsDeoptBootImageEnabled() const { return deopt_boot_image_enabled_; } - bool IsHiddenAPIBypassEnabled() const; + inline auto IsNoModuleLogEnabled() const { return no_module_log_enabled_; } - std::string GetInstallerPackageName() const; + inline auto IsHiddenAPIBypassEnabled() const { return hidden_api_bypass_enabled_; } - std::string GetXposedPropPath() const; + inline auto GetInstallerPackageName() const { return installer_pkg_name_; } - std::string GetLibSandHookName() const; + inline auto GetXposedPropPath() const { return kXposedPropPath; } - std::string GetLibWhaleName() const; + inline auto GetLibSandHookName() const { return kLibSandHookName; } - std::string GetDataPathPrefix() const; + inline auto GetLibWhaleName() const { return kLibWhaleName; } - std::string GetConfigPath(const std::string &suffix) const; + inline auto GetDataPathPrefix() const { return data_path_prefix_; } - bool IsAppNeedHook(const std::string &app_data_dir); + inline auto GetConfigPath(const std::string &suffix) const { + return data_path_prefix_ / installer_pkg_name_ / "conf" / suffix; + } + + inline auto GetAppModulesList() const { return app_modules_list_; }; + + bool UpdateAppModuleList(const uid_t user, const std::string &pkg_name); + + bool IsAppNeedHook(const uid_t user, const std::string &pkg_name); + + bool UpdateModuleList(); - bool hidden_api_bypass_enabled_ = false; private: - inline static ConfigManager *instance_; - uid_t last_user_ = false; + inline static std::unique_ptr instance_ = nullptr; + uid_t last_user_ = 0; 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,15 @@ 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::vector>> modules_list_; + + std::vector app_modules_list_; + + std::filesystem::file_time_type last_write_time_; ConfigManager(); @@ -76,6 +98,11 @@ namespace edxp { void SnapshotBlackWhiteList(); std::string RetrieveInstallerPkgName() const; + + static std::string GetPackageNameFromBaseApkPath(const std::filesystem::path &path); + + 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 890733009..f9d2d604a 100644 --- a/edxp-core/src/main/cpp/main/src/edxp_context.cpp +++ b/edxp-core/src/main/cpp/main/src/edxp_context.cpp @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include "edxp_context.h" #include "config_manager.h" @@ -21,6 +23,8 @@ #pragma clang diagnostic ignored "-Wunused-value" namespace edxp { + namespace fs = std::filesystem; + constexpr int FIRST_ISOLATED_UID = 99000; constexpr int LAST_ISOLATED_UID = 99999; constexpr int FIRST_APP_ZYGOTE_ISOLATED_UID = 90000; @@ -52,7 +56,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; } @@ -62,21 +87,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; } @@ -140,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;"); @@ -155,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 " << class_name << " not found"; + 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_)) { @@ -224,24 +222,37 @@ 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); + ConfigManager::GetInstance()->UpdateModuleList(); // I don't think we need this, but anyway + skip_ = false; + if (!ConfigManager::GetInstance()->IsAppNeedHook(0, "android")) { + skip_ = true; + LOGW("skip injecting xposed into android because it's whitelisted/blacklisted"); + } + if (!skip_ && !ConfigManager::GetInstance()->UpdateAppModuleList(0, "android")) { + skip_ = true; + LOGW("skip injecting into android because no module hooks it"); + } + PreLoadDex(env, kInjectDexPath); } int Context::OnNativeForkSystemServerPost(JNIEnv *env, jclass clazz, jint res) { if (res == 0) { - PrepareJavaEnv(env); - // only do work in child since FindAndCall would print log - FindAndCall(env, "forkSystemServerPost", "(I)V", res); + if (!skip_) { + PrepareJavaEnv(env); + // only do work in child since FindAndCall would print log + FindAndCall(env, "forkSystemServerPost", "(I)V", res); + } else { + auto config_manager = ConfigManager::ReleaseInstance(); + auto context = Context::ReleaseInstance(); + LOGD("skipped android"); + } } 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 @@ -249,33 +260,62 @@ namespace edxp { return 0; } - std::tuple Context::ShouldSkipInject(JNIEnv *env, jstring nice_name, jstring data_dir, jint uid, + std::tuple + Context::GetAppInfoFromDir(JNIEnv *env, jstring dir) { + uid_t uid = 0; + JUTFString app_data_dir(env, dir); + if (!app_data_dir) return {false, 0, {}}; + fs::path path(app_data_dir.get()); + 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.get()); + return {false, uid, {}}; + } + return {true, uid, package_name}; + } + + 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"); + const auto&[res, user, package_name] = GetAppInfoFromDir(env, data_dir); bool skip = false; - bool release = true; - if (is_child_zygote) { + if (!res) { + LOGW("skip injecting into %s because it has no data dir", package_name.c_str()); + skip = true; + } + if (!skip && 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()); + LOGW("skip injecting into %s because it's a child zygote", package_name.c_str()); } - if ((app_id >= FIRST_ISOLATED_UID && app_id <= LAST_ISOLATED_UID) || - (app_id >= FIRST_APP_ZYGOTE_ISOLATED_UID && app_id <= LAST_APP_ZYGOTE_ISOLATED_UID) || - app_id == SHARED_RELRO_UID) { + if (!skip && ((app_id >= FIRST_ISOLATED_UID && app_id <= LAST_ISOLATED_UID) || + (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()); + LOGW("skip injecting into %s because it's isolated", package_name.c_str()); } - const JUTFString dir(env, data_dir); - if(!dir || !ConfigManager::GetInstance()->IsAppNeedHook(dir)) { + if (!skip && !ConfigManager::GetInstance()->IsAppNeedHook(user, package_name)) { skip = true; LOGW("skip injecting xposed into %s because it's whitelisted/blacklisted", - package_name.get()); + package_name.c_str()); } - return {skip, release}; + + if (!skip && !ConfigManager::GetInstance()->UpdateAppModuleList(user, package_name)) { + skip = true; + LOGW("skip injecting xposed into %s because no module hooks it", + package_name.c_str()); + } + return skip; } void Context::OnNativeForkAndSpecializePre(JNIEnv *env, jclass clazz, @@ -291,32 +331,30 @@ 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); + ConfigManager::GetInstance()->UpdateModuleList(); + skip_ = ShouldSkipInject(env, nice_name, app_data_dir, uid, + is_child_zygote); + const JUTFString dir(env, app_data_dir, ""); 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..a25a7bb9c 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,16 @@ #pragma once +#include #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 +21,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 +52,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 +81,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 +93,30 @@ 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); + static std::tuple GetAppInfoFromDir(JNIEnv *env, jstring dir); + + 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..47a938328 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 @@ -2,6 +2,7 @@ #include #include #include +#include #include "edxp_config_manager.h" namespace edxp { @@ -54,11 +55,13 @@ namespace edxp { } - static jboolean ConfigManager_isAppNeedHook(JNI_START, jstring appDataDir) { - const char *app_data_dir = env->GetStringUTFChars(appDataDir, JNI_FALSE); - auto result = (jboolean) ConfigManager::GetInstance()->IsAppNeedHook(app_data_dir); - env->ReleaseStringUTFChars(appDataDir, app_data_dir); - return result; + static jstring ConfigManager_getModulesList(JNI_START) { + auto module_list = ConfigManager::GetInstance()->GetAppModulesList(); + std::ostringstream join; + std::copy(module_list.begin(), module_list.end(), std::ostream_iterator(join, "\n")); + const auto &list = join.str(); + LOGD("module list: %s", list.c_str()); + return env->NewStringUTF(list.c_str()); } static JNINativeMethod gMethods[] = { @@ -72,8 +75,9 @@ 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, isAppNeedHook, "(Ljava/lang/String;)Z"), + NATIVE_METHOD(ConfigManager, getInstallerConfigPath, + "(Ljava/lang/String;)Ljava/lang/String;"), + NATIVE_METHOD(ConfigManager, getModulesList, "()Ljava/lang/String;"), }; void RegisterConfigManagerMethods(JNIEnv *env) { diff --git a/edxp-core/src/main/cpp/main/src/native_hook.cpp b/edxp-core/src/main/cpp/main/src/native_hook.cpp index 77866b917..bb67be172 100644 --- a/edxp-core/src/main/cpp/main/src/native_hook.cpp +++ b/edxp-core/src/main/cpp/main/src/native_hook.cpp @@ -18,7 +18,6 @@ #include "art/runtime/gc/heap.h" #include "art/runtime/hidden_api.h" #include "art/runtime/oat_file_manager.h" -#include "framework/fd_utils.h" std::vector linker_get_solist(); // Dobby but not in .h @@ -26,13 +25,10 @@ namespace edxp { static volatile bool installed = false; static volatile bool art_hooks_installed = false; - static volatile bool fwk_hooks_installed = false; static HookFunType hook_func = nullptr; void InstallArtHooks(void *art_handle); - void InstallFwkHooks(void *fwk_handle); - void InstallInlineHooks() { if (installed) { LOGI("Inline hooks have been installed, skip"); @@ -72,9 +68,6 @@ namespace edxp { ScopedDlHandle art_handle(kLibArtLegacyPath.c_str()); InstallArtHooks(art_handle.Get()); } - - ScopedDlHandle fwk_handle(kLibFwkPath.c_str()); - InstallFwkHooks(fwk_handle.Get()); } void InstallArtHooks(void *art_handle) { @@ -94,13 +87,5 @@ namespace edxp { art_hooks_installed = true; LOGI("ART hooks installed"); } - - void InstallFwkHooks(void *fwk_handle) { - if (fwk_hooks_installed) { - return; - } - android::FileDescriptorWhitelist::Setup(fwk_handle, hook_func); - } - } diff --git a/edxp-core/src/main/cpp/main/src/resource_hook.cpp b/edxp-core/src/main/cpp/main/src/resource_hook.cpp index 41d2fb8f6..ad960f541 100644 --- a/edxp-core/src/main/cpp/main/src/resource_hook.cpp +++ b/edxp-core/src/main/cpp/main/src/resource_hook.cpp @@ -14,6 +14,7 @@ #include "framework/androidfw/ResourceTypes.h" #include "resource_hook.h" #include "dl_util.h" +#include "config.h" // @ApiSensitive(Level.HIGH) namespace edxp { diff --git a/edxp-core/template_override/customize.sh b/edxp-core/template_override/customize.sh index 0b6f9995f..85daef1ab 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 @@ -267,10 +267,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" @@ -290,15 +290,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/riru/module.prop.new b/edxp-core/template_override/riru/module.prop.new index 69bd5bd18..0df553039 100644 --- a/edxp-core/template_override/riru/module.prop.new +++ b/edxp-core/template_override/riru/module.prop.new @@ -1,5 +1,5 @@ name=Riru - EdXposed -version=v0.5.0.6 (YAHFA) +version=v0.5.0.8 (YAHFA) versionCode=233 author=solohsu, MlgmXyysd & rk700 description=Another enhanced implementation of Xposed Framework. Supports Android 8.0, 8.1, 9, 10 or above. Requires Riru - Core v19 or above installed. Telegram: @EdXposed diff --git a/edxp-core/template_override/sepolicy.rule b/edxp-core/template_override/sepolicy.rule index b5a8c6abb..fc54e92c3 100644 --- a/edxp-core/template_override/sepolicy.rule +++ b/edxp-core/template_override/sepolicy.rule @@ -1,6 +1,4 @@ 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 -allow zygote apk_data_file * * +allow zygote app_data_file dir { search read } +allow zygote app_data_file file { getattr read open } \ No newline at end of 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..09a22a55b 100644 --- a/edxp-sandhook/build.gradle +++ b/edxp-sandhook/build.gradle @@ -22,13 +22,14 @@ 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') + compileOnly files(project(":dexmaker").tasks.getByName("makeJarRelease").outputs) } @@ -57,23 +58,17 @@ afterEvaluate { def variantNameCapped = variant.name.capitalize() def variantNameLowered = variant.name.toLowerCase() - def myTemplatePath = "${projectDir}/template_override/" - - task("makeAndCopy${variantNameCapped}", type: Jar, dependsOn: "assemble${variantNameCapped}") { + task("copyDex${variantNameCapped}", type: Copy) { + dependsOn "assemble${variantNameCapped}" dependsOn tasks.getByPath(":edxp-common:copyCommonProperties") - def dexOutPath = variant.name.contains("release") ? - "${buildDir}/intermediates/transforms/dexMerger/${variantNameLowered}/0/" : - "${buildDir}/intermediates/dex/${variantNameLowered}/mergeDex${variantNameCapped}/out/" - from dexOutPath, "${projectDir}/src/main/resources/" - destinationDir file(myTemplatePath + "system/framework/") - baseName "edxp" - doLast { - copy { - from file(myTemplatePath) - into file(templateRootPath) - } + def dexOutPath = "${buildDir}/intermediates/dex/${variantNameLowered}/minify${variantNameCapped}WithR8" + from (dexOutPath){ + rename("classes.dex", "edxp.dex") } + from "${projectDir}/src/main/resources/" + destinationDir file(templateRootPath + "system/framework/") outputs.upToDateWhen { false } } + } } \ No newline at end of file diff --git a/edxp-sandhook/proguard-rules.pro b/edxp-sandhook/proguard-rules.pro index 520e46fdc..45557eded 100644 --- a/edxp-sandhook/proguard-rules.pro +++ b/edxp-sandhook/proguard-rules.pro @@ -20,6 +20,7 @@ # hide the original source file name. #-renamesourcefileattribute SourceFile +-dontoptimize -dontobfuscate -keep class de.robv.android.xposed.** {*;} -keep class android.** { *; } @@ -32,6 +33,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..649fec74d 100644 --- a/edxp-whale/build.gradle +++ b/edxp-whale/build.gradle @@ -22,12 +22,13 @@ android { } } + ndkVersion androidCompileNdkVersion } dependencies { - compileOnly files("${hiddenApiStubJarFilePath}") + compileOnly project(':hiddenapi-stubs') implementation project(':edxp-common') - compileOnly project(':dexmaker') + compileOnly files(project(":dexmaker").tasks.getByName("makeJarRelease").outputs) } @@ -56,22 +57,15 @@ afterEvaluate { def variantNameCapped = variant.name.capitalize() def variantNameLowered = variant.name.toLowerCase() - def myTemplatePath = "${projectDir}/template_override/" - - task("makeAndCopy${variantNameCapped}", type: Jar, dependsOn: "assemble${variantNameCapped}") { + task("copyDex${variantNameCapped}", type: Copy) { + dependsOn "assemble${variantNameCapped}" dependsOn tasks.getByPath(":edxp-common:copyCommonProperties") - def dexOutPath = variant.name.contains("release") ? - "${buildDir}/intermediates/transforms/dexMerger/${variantNameLowered}/0/" : - "${buildDir}/intermediates/dex/${variantNameLowered}/mergeDex${variantNameCapped}/out/" - from dexOutPath, "${projectDir}/src/main/resources/" - destinationDir file(myTemplatePath + "system/framework/") - baseName "edxp" - doLast { - copy { - from file(myTemplatePath) - into file(templateRootPath) - } + def dexOutPath = "${buildDir}/intermediates/dex/${variantNameLowered}/minify${variantNameCapped}WithR8" + from (dexOutPath){ + rename("classes.dex", "edxp.dex") } + from "${projectDir}/src/main/resources/" + destinationDir file(templateRootPath + "system/framework/") outputs.upToDateWhen { false } } } diff --git a/edxp-whale/proguard-rules.pro b/edxp-whale/proguard-rules.pro index 503061cbb..a998d8b22 100644 --- a/edxp-whale/proguard-rules.pro +++ b/edxp-whale/proguard-rules.pro @@ -20,6 +20,7 @@ # hide the original source file name. #-renamesourcefileattribute SourceFile +-dontoptimize -dontobfuscate -keep class de.robv.android.xposed.** {*;} -keep class android.** { *; } @@ -32,6 +33,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..b84ac58f8 100644 --- a/edxp-yahfa/build.gradle +++ b/edxp-yahfa/build.gradle @@ -22,12 +22,13 @@ android { } } + ndkVersion androidCompileNdkVersion } dependencies { - compileOnly files("${hiddenApiStubJarFilePath}") + compileOnly project(':hiddenapi-stubs') implementation project(':edxp-common') - compileOnly project(':dexmaker') + compileOnly files(project(":dexmaker").tasks.getByName("makeJarRelease").outputs) } @@ -56,23 +57,17 @@ afterEvaluate { def variantNameCapped = variant.name.capitalize() def variantNameLowered = variant.name.toLowerCase() - def myTemplatePath = "${projectDir}/template_override/" - - task("makeAndCopy${variantNameCapped}", type: Jar, dependsOn: "assemble${variantNameCapped}") { + task("copyDex${variantNameCapped}", type: Copy) { + dependsOn "assemble${variantNameCapped}" dependsOn tasks.getByPath(":edxp-common:copyCommonProperties") - def dexOutPath = variant.name.contains("release") ? - "${buildDir}/intermediates/transforms/dexMerger/${variantNameLowered}/0/" : - "${buildDir}/intermediates/dex/${variantNameLowered}/mergeDex${variantNameCapped}/out/" - from dexOutPath, "${projectDir}/src/main/resources/" - destinationDir file(myTemplatePath + "system/framework/") - baseName "edxp" - doLast { - copy { - from file(myTemplatePath) - into file(templateRootPath) - } + def dexOutPath = "${buildDir}/intermediates/dex/${variantNameLowered}/minify${variantNameCapped}WithR8" + from (dexOutPath){ + rename("classes.dex", "edxp.dex") } + from "${projectDir}/src/main/resources/" + destinationDir file(templateRootPath + "system/framework/") outputs.upToDateWhen { false } } + } } \ No newline at end of file diff --git a/edxp-yahfa/proguard-rules.pro b/edxp-yahfa/proguard-rules.pro index c600fee6c..50e9b7978 100644 --- a/edxp-yahfa/proguard-rules.pro +++ b/edxp-yahfa/proguard-rules.pro @@ -20,6 +20,7 @@ # hide the original source file name. #-renamesourcefileattribute SourceFile +-dontoptimize -dontobfuscate -keep class de.robv.android.xposed.** {*;} -keep class android.** { *; } @@ -30,6 +31,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..6eeb58e9e 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 \ 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/.gitignore b/hiddenapi-stubs/.gitignore index 796b96d1c..97873191d 100644 --- a/hiddenapi-stubs/.gitignore +++ b/hiddenapi-stubs/.gitignore @@ -1 +1,2 @@ /build +/libs diff --git a/hiddenapi-stubs/build.gradle b/hiddenapi-stubs/build.gradle index beb26cf19..31adb017e 100644 --- a/hiddenapi-stubs/build.gradle +++ b/hiddenapi-stubs/build.gradle @@ -1,22 +1,15 @@ -import com.android.builder.core.BuilderConstants - apply plugin: 'com.android.library' android { compileSdkVersion androidCompileSdkVersion.toInteger() + ndkVersion androidCompileNdkVersion } task makeStubJar(type: Jar){ + dependsOn assemble baseName 'framework-stub' - from("${projectDir}/build/intermediates/javac/release/compileReleaseJavaWithJavac/classes/") - into('') - destinationDir file("${projectDir}/libs") + from("${buildDir}/intermediates/javac/release/classes/") exclude('BuildConfig.class', 'R.class') exclude{ it.name.startsWith('R$')} -} - -afterEvaluate { - tasks.withType(JavaCompile) { - it.finalizedBy(makeStubJar) - } + outputs.file(archivePath) } diff --git a/hiddenapi-stubs/libs/framework-stub.jar b/hiddenapi-stubs/libs/framework-stub.jar deleted file mode 100644 index 2c94a740a..000000000 Binary files a/hiddenapi-stubs/libs/framework-stub.jar and /dev/null differ diff --git a/xposed-bridge/build.gradle b/xposed-bridge/build.gradle index a4ed4a4a4..831afc029 100644 --- a/xposed-bridge/build.gradle +++ b/xposed-bridge/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.library' android { compileSdkVersion androidCompileSdkVersion.toInteger() - buildToolsVersion '28.0.3' + ndkVersion androidCompileNdkVersion defaultConfig { minSdkVersion 26 @@ -39,8 +39,8 @@ preBuild.doLast { } dependencies { - compileOnly project(':hiddenapi-stubs') - compileOnly project(':dexmaker') + compileOnly files(project(":dexmaker").tasks.getByName("makeJarRelease").outputs) + compileOnly files(project(":hiddenapi-stubs").tasks.getByName("makeStubJar").outputs) } afterEvaluate { diff --git a/xposed-bridge/proguard-rules.pro b/xposed-bridge/proguard-rules.pro index e72d685a6..867f79750 100644 --- a/xposed-bridge/proguard-rules.pro +++ b/xposed-bridge/proguard-rules.pro @@ -21,5 +21,6 @@ #-renamesourcefileattribute SourceFile -dontobfuscate +-dontoptimize -keep class de.robv.android.xposed.** {*;} -keep class android.** { *; } \ No newline at end of file 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/XposedBridge.java b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java index 79dc3f7b5..103bea8cd 100644 --- a/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java +++ b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java @@ -146,7 +146,7 @@ public static void initXResources() { */ public static int getXposedVersion() { // ed: fixed value for now - return 91; + return 92; } /** 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; }