diff --git a/app/src/main/java/toolkit/coderstory/CorePatchForQ.java b/app/src/main/java/toolkit/coderstory/CorePatchForQ.java index c0e0007..fc2ddb7 100644 --- a/app/src/main/java/toolkit/coderstory/CorePatchForQ.java +++ b/app/src/main/java/toolkit/coderstory/CorePatchForQ.java @@ -28,7 +28,6 @@ public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) Class packageClazz = XposedHelpers.findClass("android.content.pm.PackageParser.Package", loadPackageParam.classLoader); hookAllMethods("com.android.server.pm.PackageManagerService", loadPackageParam.classLoader, "checkDowngrade", new XC_MethodHook() { public void beforeHookedMethod(MethodHookParam methodHookParam) throws Throwable { - super.beforeHookedMethod(methodHookParam); if (prefs.getBoolean("downgrade", true)) { Object packageInfoLite = methodHookParam.args[0]; @@ -65,7 +64,6 @@ public void beforeHookedMethod(MethodHookParam methodHookParam) throws Throwable final Object newInstance = findConstructorExact.newInstance(signingDetailsArgs); hookAllMethods("android.util.apk.ApkSignatureVerifier", loadPackageParam.classLoader, "verifyV1Signature", new XC_MethodHook() { public void afterHookedMethod(MethodHookParam methodHookParam) throws Throwable { - super.afterHookedMethod(methodHookParam); if (prefs.getBoolean("authcreak", false)) { Throwable throwable = methodHookParam.getThrowable(); if (throwable != null) { @@ -90,7 +88,6 @@ public void afterHookedMethod(MethodHookParam methodHookParam) throws Throwable hookAllMethods(signingDetails, "checkCapability", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - super.beforeHookedMethod(param); if (prefs.getBoolean("digestCreak", true)) { if ((Integer) param.args[1] != 4 && prefs.getBoolean("authcreak", false)) { param.setResult(Boolean.TRUE); @@ -102,7 +99,6 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - super.beforeHookedMethod(param); if (prefs.getBoolean("digestCreak", true)) { if ((Integer) param.args[1] != 4 && prefs.getBoolean("authcreak", false)) { param.setResult(Boolean.TRUE); @@ -115,7 +111,6 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { findAndHookMethod("android.content.pm.ApplicationInfo", loadPackageParam.classLoader, "isPackageWhitelistedForHiddenApis", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - super.beforeHookedMethod(param); if (prefs.getBoolean("digestCreak", true)) { ApplicationInfo info = (ApplicationInfo) param.thisObject; if ((info.flags & ApplicationInfo.FLAG_SYSTEM) != 0 @@ -159,7 +154,6 @@ public void initZygote(StartupParam startupParam) { hookAllConstructors("android.util.jar.StrictJarVerifier", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - super.beforeHookedMethod(param); if (prefs.getBoolean("enhancedMode", false)) { param.args[3] = Boolean.FALSE; } diff --git a/app/src/main/java/toolkit/coderstory/CorePatchForR.java b/app/src/main/java/toolkit/coderstory/CorePatchForR.java index b91033b..3801739 100644 --- a/app/src/main/java/toolkit/coderstory/CorePatchForR.java +++ b/app/src/main/java/toolkit/coderstory/CorePatchForR.java @@ -12,6 +12,7 @@ import com.coderstory.toolkit.BuildConfig; +import java.io.PrintWriter; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -69,6 +70,7 @@ public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) XposedBridge.log("D/" + MainHook.TAG + " UsePreSig=" + prefs.getBoolean("UsePreSig", false)); XposedBridge.log("D/" + MainHook.TAG + " enhancedMode=" + prefs.getBoolean("enhancedMode", false)); XposedBridge.log("D/" + MainHook.TAG + " bypassBlock=" + prefs.getBoolean("bypassBlock", true)); + XposedBridge.log("D/" + MainHook.TAG + " sharedUser=" + prefs.getBoolean("sharedUser", false)); } var pmService = XposedHelpers.findClassIfExists("com.android.server.pm.PackageManagerService", @@ -115,23 +117,6 @@ public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) new ReturnConstant(prefs, "authcreak", 0)); } - // Package " + packageName + " signatures do not match previously installed version; ignoring!" - // public boolean checkCapability(String sha256String, @CertCapabilities int flags) { - // public boolean checkCapability(SigningDetails oldDetails, @CertCapabilities int flags) - hookAllMethods("android.content.pm.PackageParser", loadPackageParam.classLoader, "checkCapability", new XC_MethodHook() { - @Override - protected void beforeHookedMethod(MethodHookParam param) { - // Don't handle PERMISSION (grant SIGNATURE permissions to pkgs with this cert) - // Or applications will have all privileged permissions - // https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/content/pm/PackageParser.java;l=5947?q=CertCapabilities - if (prefs.getBoolean("authcreak", false)) { - if ((Integer) param.args[1] != 4) { - param.setResult(true); - } - } - } - }); - // 当verifyV1Signature抛出转换异常时,替换一个签名作为返回值 // 如果用户已安装apk,并且其定义了私有权限,则安装时会因签名与模块内硬编码的不一致而被拒绝。尝试从待安装apk中获取签名。如果其中apk的签名和已安装的一致(只动了内容)就没有问题。此策略可能有潜在的安全隐患。 Class pkc = XposedHelpers.findClass("sun.security.pkcs.PKCS7", loadPackageParam.classLoader); @@ -152,7 +137,6 @@ protected void beforeHookedMethod(MethodHookParam param) { Class parseResult = XposedHelpers.findClassIfExists("android.content.pm.parsing.result.ParseResult", loadPackageParam.classLoader); hookAllMethods("android.util.jar.StrictJarVerifier", loadPackageParam.classLoader, "verifyBytes", new XC_MethodHook() { public void afterHookedMethod(MethodHookParam param) throws Throwable { - super.afterHookedMethod(param); if (prefs.getBoolean("digestCreak", true)) { if (!prefs.getBoolean("UsePreSig", false)) { final Object block = constructor.newInstance(param.args[0]); @@ -262,7 +246,6 @@ protected void beforeHookedMethod(MethodHookParam param) { findAndHookMethod("android.content.pm.ApplicationInfo", loadPackageParam.classLoader, "isPackageWhitelistedForHiddenApis", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - super.beforeHookedMethod(param); if (prefs.getBoolean("digestCreak", true)) { ApplicationInfo info = (ApplicationInfo) param.thisObject; if ((info.flags & ApplicationInfo.FLAG_SYSTEM) != 0 @@ -273,15 +256,6 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { } }); - var utilClass = findClass("com.android.server.pm.PackageManagerServiceUtils", loadPackageParam.classLoader); - if (utilClass != null) { - try { - deoptimizeMethod(utilClass, "verifySignatures"); - } catch (Throwable e) { - XposedBridge.log("E/" + MainHook.TAG + " deoptimizing failed" + Log.getStackTraceString(e)); - } - } - var keySetManagerClass = findClass("com.android.server.pm.KeySetManagerService", loadPackageParam.classLoader); if (keySetManagerClass != null) { var shouldBypass = new ThreadLocal(); @@ -305,6 +279,135 @@ protected void afterHookedMethod(MethodHookParam param) { } }); } + + // for SharedUser + // "Package " + packageName + " has a signing lineage " + "that diverges from the lineage of the sharedUserId" + // https://cs.android.com/android/platform/superproject/+/android-11.0.0_r21:frameworks/base/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java;l=728;drc=02a58171a9d41ad0048d6a1a48d79dee585c22a5 + hookAllMethods(signingDetails, "hasCommonAncestor", new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + if (prefs.getBoolean("digestCreak", true) + && prefs.getBoolean("sharedUser", false) + // because of LSPosed's bug, we can't hook verifySignatures while deoptimize it + && Arrays.stream(Thread.currentThread().getStackTrace()).anyMatch((o) -> "verifySignatures".equals(o.getMethodName())) + ) + param.setResult(true); + } + }); + + var utilClass = findClass("com.android.server.pm.PackageManagerServiceUtils", loadPackageParam.classLoader); + if (utilClass != null) { + try { + deoptimizeMethod(utilClass, "verifySignatures"); + } catch (Throwable e) { + XposedBridge.log("E/" + MainHook.TAG + " deoptimizing failed" + Log.getStackTraceString(e)); + } + } + + // choose a signature after all old signed packages are removed + var sharedUserSettingClass = XposedHelpers.findClass("com.android.server.pm.SharedUserSetting", loadPackageParam.classLoader); + XposedBridge.hookAllMethods( + sharedUserSettingClass, + "removePackage", + new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + if (!prefs.getBoolean("digestCreak", true) || !prefs.getBoolean("sharedUser", false)) + return; + var flags = (int) XposedHelpers.getObjectField(param.thisObject, "uidFlags"); + if ((flags & ApplicationInfo.FLAG_SYSTEM) != 0) + return; // do not modify system's signature + var toRemove = param.args[0]; // PackageSetting + if (toRemove == null) return; + var removed = false; // Is toRemove really needed to be removed + var sharedUserSig = Setting_getSigningDetails(param.thisObject); + Object newSig = null; + var packages = /*Watchable?ArraySet*/ SharedUserSetting_packages(param.thisObject); + var size = (int) XposedHelpers.callMethod(packages, "size"); + for (var i = 0; i < size; i++) { + var p = XposedHelpers.callMethod(packages, "valueAt", i); + // skip the removed package + if (toRemove.equals(p)) { + removed = true; + continue; + } + var packageSig = Setting_getSigningDetails(p); + // if old signing exists, return + if ((boolean) callOriginMethod(packageSig, "checkCapability", sharedUserSig, 0) || (boolean) callOriginMethod(sharedUserSig, "checkCapability", packageSig, 0)) { + return; + } + // otherwise, choose the first signature we meet, and merge with others if possible + // https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/services/core/java/com/android/server/pm/ReconcilePackageUtils.java;l=193;drc=c9a8baf585e8eb0f3272443930301a61331b65c1 + // respect to system + if (newSig == null) newSig = packageSig; + else newSig = SigningDetails_mergeLineageWith(newSig, packageSig); + } + if (!removed || newSig == null) return; + XposedBridge.log("updating signature in sharedUser during remove: " + param.thisObject); + Setting_setSigningDetails(param.thisObject, newSig); + } + } + ); + + XposedBridge.hookAllMethods( + sharedUserSettingClass, + "addPackage", + new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + if (!prefs.getBoolean("digestCreak", true) || !prefs.getBoolean("sharedUser", false)) + return; + var flags = (int) XposedHelpers.getObjectField(param.thisObject, "uidFlags"); + if ((flags & ApplicationInfo.FLAG_SYSTEM) != 0) + return; // do not modify system's signature + var toAdd = param.args[0]; // PackageSetting + if (toAdd == null) return; + var added = false; + var sharedUserSig = Setting_getSigningDetails(param.thisObject); + Object newSig = null; + var packages = /*Watchable?ArraySet*/ SharedUserSetting_packages(param.thisObject); + var size = (int) XposedHelpers.callMethod(packages, "size"); + for (var i = 0; i < size; i++) { + var p = XposedHelpers.callMethod(packages, "valueAt", i); + if (toAdd.equals(p)) { + // must be an existing package + added = true; + p = toAdd; + } + var packageSig = Setting_getSigningDetails(p); + // if old signing exists, return + if ((boolean) callOriginMethod(packageSig, "checkCapability", sharedUserSig, 0) || (boolean) callOriginMethod(sharedUserSig, "checkCapability", packageSig, 0)) { + return; + } + // otherwise, choose the first signature we meet, and merge with others if possible + // https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/services/core/java/com/android/server/pm/ReconcilePackageUtils.java;l=193;drc=c9a8baf585e8eb0f3272443930301a61331b65c1 + // respect to system + if (newSig == null) newSig = packageSig; + else newSig = SigningDetails_mergeLineageWith(newSig, packageSig); + } + if (!added || newSig == null) return; + XposedBridge.log("CorePatch: updating signature in sharedUser during add " + toAdd + ": " + param.thisObject); + Setting_setSigningDetails(param.thisObject, newSig); + } + } + ); + + if (BuildConfig.DEBUG) initializeDebugHook(loadPackageParam); + } + + static Object callOriginMethod(Object obj, String methodName, Object... args) { + try { + var method = XposedHelpers.findMethodBestMatch(obj.getClass(), methodName, args); + return XposedBridge.invokeOriginalMethod(method, obj, args); + } catch (IllegalAccessException e) { + // should not happen + XposedBridge.log(e); + throw new IllegalAccessError(e.getMessage()); + } catch (IllegalArgumentException e) { + throw e; + } catch (InvocationTargetException e) { + throw new RuntimeException(e.getCause()); + } } Class getSigningDetails(ClassLoader classLoader) { @@ -319,10 +422,132 @@ public void initZygote(StartupParam startupParam) { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { if (prefs.getBoolean("enhancedMode", false)) { - super.beforeHookedMethod(param); param.args[3] = Boolean.FALSE; } } }); } + + Object mPMS = null; + + void initializeDebugHook(XC_LoadPackage.LoadPackageParam lpparam) throws IllegalAccessException, InvocationTargetException { + XposedBridge.hookAllMethods( + XposedHelpers.findClass("com.android.server.pm.PackageManagerShellCommand", lpparam.classLoader), + "onCommand", + new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + try { + var pms = mPMS; + if (pms == null) return; + var cmd = (String) param.args[0]; + if (!"corepatch".equals(cmd)) return; + var self = param.thisObject; + var pw = (PrintWriter) XposedHelpers.callMethod(self, "getOutPrintWriter"); + var type = (String) XposedHelpers.callMethod(self, "getNextArgRequired"); + var settings = XposedHelpers.getObjectField(pms, "mSettings"); + if ("p".equals(type) || "package".equals(type)) { + var packageName = (String) XposedHelpers.callMethod(self, "getNextArgRequired"); + var packageSetting = XposedHelpers.callMethod(settings, "getPackageLPr", packageName); + if (packageSetting != null) { + dumpPackageSetting(packageSetting, pw, settings); + } else { + pw.println("no package " + packageName + " found"); + } + } else if ("su".equals(type) || "shareduser".equals(type)) { + var name = (String) XposedHelpers.callMethod(self, "getNextArgRequired"); + var su = getSharedUser(name, settings); + if (su != null) { + dumpSharedUserSetting(su, pw); + } else { + pw.println("no shared user " + name + " found"); + } + } else { + pw.println("usage: "); + } + param.setResult(0); + } catch (Throwable t) { + XposedBridge.log(t); + param.setThrowable(t); + } + } + } + ); + + var pmsClass = XposedHelpers.findClassIfExists("com.android.server.pm.PackageManagerService", + lpparam.classLoader); + + XposedBridge.hookAllConstructors(pmsClass, new XC_MethodHook() { + @Override + protected void afterHookedMethod(MethodHookParam param) throws Throwable { + mPMS = param.thisObject; + } + } + ); + + deoptimizeMethod(pmsClass, "onShellCommand"); + } + + void dumpPackageSetting(Object packageSetting, PrintWriter pw, Object /*Settings*/ settings) { + var signingDetails = Setting_getSigningDetails(packageSetting); + pw.println("signing for package " + packageSetting); + dumpSigningDetails(signingDetails, pw); + var pkg = XposedHelpers.getObjectField(packageSetting, "pkg"); // AndroidPackage + if (pkg == null) { + pw.println("android package is null!"); + return; + } + var id = (String) XposedHelpers.callMethod(pkg, "getSharedUserId"); + pw.println("shared user id:" + id); + if (settings != null) { + var su = getSharedUser(id, settings); + if (su != null) { + dumpSharedUserSetting(su, pw); + } + } + } + + Object getSharedUser(String id, Object /*Settings*/ settings) { + // TODO: use Setting.getSharedUserSettingLPr(appId)? + var sharedUserSettings = XposedHelpers.getObjectField(settings, "mSharedUsers"); + if (sharedUserSettings == null) return null; + return XposedHelpers.callMethod(sharedUserSettings, "get", id); + } + + void dumpSharedUserSetting(Object sharedUser, PrintWriter pw) { + var signingDetails = Setting_getSigningDetails(sharedUser); + pw.println("signing for shared user " + sharedUser); + dumpSigningDetails(signingDetails, pw); + } + + protected void dumpSigningDetails(Object signingDetails, PrintWriter pw) { + var i = 0; + for (var sign : (Signature[]) XposedHelpers.getObjectField(signingDetails, "signatures")) { + i++; + pw.println(i + ": " + sign.toCharsString()); + } + } + + /** + * Get signing details for PackageSetting or SharedUserSetting + */ + Object Setting_getSigningDetails(Object pkgOrSharedUser) { + // PackageSettingBase(A11)|PackageSetting(A13)|SharedUserSetting.signatures.mSigningDetails + return XposedHelpers.getObjectField(XposedHelpers.getObjectField(pkgOrSharedUser, "signatures"), "mSigningDetails"); + } + + /** + * Set signing details for PackageSetting or SharedUserSetting + */ + void Setting_setSigningDetails(Object pkgOrSharedUser, Object signingDetails) { + XposedHelpers.setObjectField(XposedHelpers.getObjectField(pkgOrSharedUser, "signatures"), "mSigningDetails", signingDetails); + } + + protected Object SharedUserSetting_packages(Object /*SharedUserSetting*/ sharedUser) { + return XposedHelpers.getObjectField(sharedUser, "packages"); + } + + protected Object SigningDetails_mergeLineageWith(Object self, Object other) { + return XposedHelpers.callMethod(self, "mergeLineageWith", other); + } } diff --git a/app/src/main/java/toolkit/coderstory/CorePatchForT.java b/app/src/main/java/toolkit/coderstory/CorePatchForT.java index 2c9d8f8..70023ad 100644 --- a/app/src/main/java/toolkit/coderstory/CorePatchForT.java +++ b/app/src/main/java/toolkit/coderstory/CorePatchForT.java @@ -1,7 +1,8 @@ package toolkit.coderstory; -import android.util.Log; +import android.content.pm.Signature; +import java.io.PrintWriter; import java.lang.reflect.InvocationTargetException; import de.robv.android.xposed.XC_MethodHook; @@ -38,23 +39,6 @@ protected void beforeHookedMethod(MethodHookParam param) { } }); - // Package " + packageName + " signatures do not match previously installed version; ignoring!" - // public boolean checkCapability(String sha256String, @CertCapabilities int flags) { - // public boolean checkCapability(SigningDetails oldDetails, @CertCapabilities int flags) - hookAllMethods("android.content.pm.PackageParser", loadPackageParam.classLoader, "checkCapability", new XC_MethodHook() { - @Override - protected void beforeHookedMethod(MethodHookParam param) { - // Don't handle PERMISSION (grant SIGNATURE permissions to pkgs with this cert) - // Or applications will have all privileged permissions - // https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/content/pm/PackageParser.java;l=5947?q=CertCapabilities - if (prefs.getBoolean("authcreak", false)) { - if ((Integer) param.args[1] != 4) { - param.setResult(true); - } - } - } - }); - findAndHookMethod("com.android.server.pm.InstallPackageHelper", loadPackageParam.classLoader, "doesSignatureMatchForPermissions", String.class, "com.android.server.pm.parsing.pkg.ParsedPackage", int.class, new XC_MethodHook() { @@ -97,10 +81,35 @@ protected void afterHookedMethod(MethodHookParam param) { } }); } + + // ensure verifySignatures success + // https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java;l=621;drc=2e50991320cbef77d3e8504a4b284adae8c2f4d2 + var utils = XposedHelpers.findClassIfExists("com.android.server.pm.PackageManagerServiceUtils", loadPackageParam.classLoader); + if (utils != null) { + deoptimizeMethod(utils, "canJoinSharedUserId"); + } } - @Override Class getSigningDetails(ClassLoader classLoader) { return XposedHelpers.findClassIfExists("android.content.pm.SigningDetails", classLoader); } + + @Override + protected void dumpSigningDetails(Object signingDetails, PrintWriter pw) { + var i = 0; + for (var sign : (Signature[]) XposedHelpers.callMethod(signingDetails, "getSignatures")) { + i++; + pw.println(i + ": " + sign.toCharsString()); + } + } + + @Override + protected Object SharedUserSetting_packages(Object sharedUser) { + return XposedHelpers.getObjectField(sharedUser, "mPackages"); + } + + @Override + protected Object SigningDetails_mergeLineageWith(Object self, Object other) { + return XposedHelpers.callMethod(self, "mergeLineageWith", other, 2 /*MERGE_RESTRICTED_CAPABILITY*/); + } } diff --git a/app/src/main/java/toolkit/coderstory/ReturnConstant.java b/app/src/main/java/toolkit/coderstory/ReturnConstant.java index 118ab98..ace1d78 100644 --- a/app/src/main/java/toolkit/coderstory/ReturnConstant.java +++ b/app/src/main/java/toolkit/coderstory/ReturnConstant.java @@ -16,7 +16,6 @@ public ReturnConstant(XSharedPreferences prefs, String prefsKey, Object value) { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - super.beforeHookedMethod(param); prefs.reload(); if (prefs.getBoolean(prefsKey, true)) { param.setResult(value); diff --git a/app/src/main/java/toolkit/coderstory/SettingsActivity.java b/app/src/main/java/toolkit/coderstory/SettingsActivity.java index c15a7e4..407fcdb 100644 --- a/app/src/main/java/toolkit/coderstory/SettingsActivity.java +++ b/app/src/main/java/toolkit/coderstory/SettingsActivity.java @@ -5,17 +5,13 @@ import android.app.AlertDialog; import android.content.Context; import android.content.SharedPreferences; -import android.graphics.Color; import android.graphics.Insets; -import android.graphics.drawable.ColorDrawable; import android.os.Build; import android.os.Bundle; import android.preference.PreferenceFragment; import android.view.View; import android.view.ViewGroup; -import android.view.Window; import android.view.WindowInsets; -import android.view.WindowInsetsController; import com.coderstory.toolkit.R; diff --git a/app/src/main/java/toolkit/coderstory/XposedHelper.java b/app/src/main/java/toolkit/coderstory/XposedHelper.java index f02613e..dd64893 100644 --- a/app/src/main/java/toolkit/coderstory/XposedHelper.java +++ b/app/src/main/java/toolkit/coderstory/XposedHelper.java @@ -21,6 +21,7 @@ public static void findAndHookMethod(String className, ClassLoader classLoader, XposedBridge.log("E/" + MainHook.TAG + " " + Log.getStackTraceString(e)); } } + public static void findAndHookMethod(Class clazz, String methodName, Object... parameterTypesAndCallback) { try { if (clazz != null) { @@ -31,6 +32,7 @@ public static void findAndHookMethod(Class clazz, String methodName, Object.. XposedBridge.log("E/" + MainHook.TAG + " " + Log.getStackTraceString(e)); } } + public static void hookAllMethods(String className, ClassLoader classLoader, String methodName, XC_MethodHook callback) { try { Class packageParser = findClass(className, classLoader); @@ -39,7 +41,6 @@ public static void hookAllMethods(String className, ClassLoader classLoader, Str if (BuildConfig.DEBUG) XposedBridge.log("E/" + MainHook.TAG + " " + Log.getStackTraceString(e)); } - } public void hookAllMethods(Class hookClass, String methodName, XC_MethodHook callback) { diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 226e7e0..47939d7 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -20,4 +20,6 @@ 绕过黑名单 绕过某些设备如 Nothing Phone 上的黑名单 配置初始化失败 + 绕过共享用户签名验证 + 允许安装与其共享用户签名不同的 app(需要同时打开“禁用APK签名验证” diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 42bae1c..74a4194 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -20,4 +20,6 @@ Bypass blocklist in some devices like Nothing Phone UsePreSig won\'t work on MiUI because its framework changes too much.\nWe don\'t have time to track the case. !! Any apk can override the installed one !!\nBe carefully when installing unknown apk + Bypass shared user verify + Allow install app with signature differ from its shared user (\'Disable compare signatures\' must be enabled too) diff --git a/app/src/main/res/xml/prefs.xml b/app/src/main/res/xml/prefs.xml index 8f3c4d6..ffbb0da 100644 --- a/app/src/main/res/xml/prefs.xml +++ b/app/src/main/res/xml/prefs.xml @@ -34,6 +34,12 @@ android:title="@string/bypassBlock" android:summary="@string/bypassBlock_summary" android:defaultValue="true" /> + +