Skip to content

Commit

Permalink
Refine and fix for Android 14
Browse files Browse the repository at this point in the history
Fix disable digest verify for Android 14
Better logging
  • Loading branch information
Howard20181 committed Oct 24, 2023
1 parent 0863417 commit 52ef68c
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 118 deletions.
3 changes: 1 addition & 2 deletions app/src/main/java/toolkit/coderstory/CorePatchForQ.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import android.content.pm.ApplicationInfo;
import android.content.pm.Signature;
import android.util.Log;

import com.coderstory.toolkit.BuildConfig;

Expand All @@ -21,7 +20,7 @@
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class CorePatchForQ extends XposedHelper implements IXposedHookLoadPackage, IXposedHookZygoteInit {
XSharedPreferences prefs = new XSharedPreferences(BuildConfig.APPLICATION_ID, "conf");
final XSharedPreferences prefs = new XSharedPreferences(BuildConfig.APPLICATION_ID, "conf");

@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws IllegalAccessException, InvocationTargetException, InstantiationException {
Expand Down
94 changes: 61 additions & 33 deletions app/src/main/java/toolkit/coderstory/CorePatchForR.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,30 +32,58 @@
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class CorePatchForR extends XposedHelper implements IXposedHookLoadPackage, IXposedHookZygoteInit {
XSharedPreferences prefs = new XSharedPreferences(BuildConfig.APPLICATION_ID, "conf");
private final static Method deoptimizeMethod;

@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws IllegalAccessException, InvocationTargetException, InstantiationException {
static {
Method m = null;
try {
m = XposedBridge.class.getDeclaredMethod("deoptimizeMethod", Member.class);
} catch (Throwable t) {
XposedBridge.log("E/" + MainHook.TAG + " " + Log.getStackTraceString(t));
}
deoptimizeMethod = m;
}

Log.d(MainHook.TAG, "downgrade=" + prefs.getBoolean("downgrade", true));
Log.d(MainHook.TAG, "authcreak=" + prefs.getBoolean("authcreak", true));
Log.d(MainHook.TAG, "digestCreak=" + prefs.getBoolean("digestCreak", true));
Log.d(MainHook.TAG, "UsePreSig=" + prefs.getBoolean("UsePreSig", false));
static void deoptimizeMethod(Class<?> c, String n) throws InvocationTargetException, IllegalAccessException {
for (Method m : c.getDeclaredMethods()) {
if (deoptimizeMethod != null && m.getName().equals(n)) {
deoptimizeMethod.invoke(null, m);
if (BuildConfig.DEBUG)
XposedBridge.log("D/" + MainHook.TAG + " Deoptimized " + m.getName());
}
}
}

// 允许降级
findAndHookMethod("com.android.server.pm.PackageManagerService", loadPackageParam.classLoader,
"checkDowngrade",
"com.android.server.pm.parsing.pkg.AndroidPackage",
"android.content.pm.PackageInfoLite",
new ReturnConstant(prefs, "downgrade", null));
final XSharedPreferences prefs = new XSharedPreferences(BuildConfig.APPLICATION_ID, "conf");

// exists on flyme 9(Android 11) only
findAndHookMethod("com.android.server.pm.PackageManagerService", loadPackageParam.classLoader,
"checkDowngrade",
"android.content.pm.PackageInfoLite",
"android.content.pm.PackageInfoLite",
new ReturnConstant(prefs, "downgrade", true));
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws IllegalAccessException, InvocationTargetException, InstantiationException {
if (BuildConfig.DEBUG) {
XposedBridge.log("D/" + MainHook.TAG + " downgrade=" + prefs.getBoolean("downgrade", true));
XposedBridge.log("D/" + MainHook.TAG + " authcreak=" + prefs.getBoolean("authcreak", true));
XposedBridge.log("D/" + MainHook.TAG + " digestCreak=" + prefs.getBoolean("digestCreak", true));
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));
}

var pmService = XposedHelpers.findClassIfExists("com.android.server.pm.PackageManagerService",
loadPackageParam.classLoader);
if (pmService != null) {
var checkDowngrade = XposedHelpers.findMethodExactIfExists(pmService, "checkDowngrade",
"com.android.server.pm.parsing.pkg.AndroidPackage",
"android.content.pm.PackageInfoLite");
if (checkDowngrade != null) {
// 允许降级
XposedBridge.hookMethod(checkDowngrade, new ReturnConstant(prefs, "downgrade", null));
}
// exists on flyme 9(Android 11) only
var flymeCheckDowngrade = XposedHelpers.findMethodExactIfExists(pmService, "checkDowngrade",
"android.content.pm.PackageInfoLite",
"android.content.pm.PackageInfoLite");
if (flymeCheckDowngrade != null)
XposedBridge.hookMethod(flymeCheckDowngrade, new ReturnConstant(prefs, "downgrade", true));
}

// apk内文件修改后 digest校验会失败
hookAllMethods("android.util.jar.StrictJarVerifier", loadPackageParam.classLoader, "verifyMessageDigest",
Expand All @@ -76,8 +104,12 @@ public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam)
// + " or newer for package " + apkPath
findAndHookMethod("android.util.apk.ApkSignatureVerifier", loadPackageParam.classLoader, "getMinimumSignatureSchemeVersionForTargetSdk", int.class,
new ReturnConstant(prefs, "authcreak", 0));
findAndHookMethod("com.android.apksig.ApkVerifier", loadPackageParam.classLoader, "getMinimumSignatureSchemeVersionForTargetSdk", int.class,
new ReturnConstant(prefs, "authcreak", 0));
var apkVerifierClass = XposedHelpers.findClassIfExists("com.android.apksig.ApkVerifier",
loadPackageParam.classLoader);
if (apkVerifierClass != null) {
findAndHookMethod(apkVerifierClass, "getMinimumSignatureSchemeVersionForTargetSdk", int.class,
new ReturnConstant(prefs, "authcreak", 0));
}

// Package " + packageName + " signatures do not match previously installed version; ignoring!"
// public boolean checkCapability(String sha256String, @CertCapabilities int flags) {
Expand Down Expand Up @@ -146,7 +178,7 @@ public void afterHookedMethod(MethodHookParam methodHookParam) throws Throwable
if (prefs.getBoolean("UsePreSig", false)) {
PackageManager PM = AndroidAppHelper.currentApplication().getPackageManager();
if (PM == null) {
XposedBridge.log("E: " + BuildConfig.APPLICATION_ID + " Cannot get the Package Manager... Are you using MiUI?");
XposedBridge.log("E/" + MainHook.TAG + " " + BuildConfig.APPLICATION_ID + " Cannot get the Package Manager... Are you using MiUI?");
} else {
PackageInfo pI;
if (parseErr != null) {
Expand Down Expand Up @@ -187,7 +219,7 @@ public void afterHookedMethod(MethodHookParam methodHookParam) throws Throwable
if (signingDetailsWithDigests != null) {
Constructor<?> signingDetailsWithDigestsConstructorExact = XposedHelpers.findConstructorExact(signingDetailsWithDigests, signingDetails, Map.class);
signingDetailsWithDigestsConstructorExact.setAccessible(true);
newInstance = signingDetailsWithDigestsConstructorExact.newInstance(new Object[]{newInstance, null});
newInstance = signingDetailsWithDigestsConstructorExact.newInstance(newInstance, null);
}
if (throwable != null) {
Throwable cause = throwable.getCause();
Expand Down Expand Up @@ -243,14 +275,10 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable {

var utilClass = findClass("com.android.server.pm.PackageManagerServiceUtils", loadPackageParam.classLoader);
if (utilClass != null) {
for (var m : utilClass.getDeclaredMethods()) {
if ("verifySignatures".equals(m.getName())) {
try {
XposedBridge.class.getDeclaredMethod("deoptimizeMethod", Member.class).invoke(null, m);
} catch (Throwable e) {
Log.e("CorePatch", "deoptimizing failed", e);
}
}
try {
deoptimizeMethod(utilClass, "verifySignatures");
} catch (Throwable e) {
XposedBridge.log("E/" + MainHook.TAG + " deoptimizing failed" + Log.getStackTraceString(e));
}
}

Expand All @@ -259,7 +287,7 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
var shouldBypass = new ThreadLocal<Boolean>();
hookAllMethods(keySetManagerClass, "shouldCheckUpgradeKeySetLocked", new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
protected void afterHookedMethod(MethodHookParam param) {
if (prefs.getBoolean("digestCreak", true) && Arrays.stream(Thread.currentThread().getStackTrace()).anyMatch((o) -> "preparePackageLI".equals(o.getMethodName()))) {
shouldBypass.set(true);
param.setResult(true);
Expand All @@ -270,7 +298,7 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable {
});
hookAllMethods(keySetManagerClass, "checkUpgradeKeySetLocked", new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
protected void afterHookedMethod(MethodHookParam param) {
if (prefs.getBoolean("digestCreak", true) && shouldBypass.get()) {
param.setResult(true);
}
Expand Down
31 changes: 20 additions & 11 deletions app/src/main/java/toolkit/coderstory/CorePatchForS.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,35 @@
import java.lang.reflect.InvocationTargetException;

import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class CorePatchForS extends CorePatchForR {
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws IllegalAccessException, InvocationTargetException, InstantiationException {
super.handleLoadPackage(loadPackageParam);
if (prefs.getBoolean("digestCreak", true) && prefs.getBoolean("UsePreSig", false)) {
findAndHookMethod("com.android.server.pm.PackageManagerService", loadPackageParam.classLoader, "doesSignatureMatchForPermissions", String.class, "com.android.server.pm.parsing.pkg.ParsedPackage", int.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
//If we decide to crack this then at least make sure they are same apks, avoid another one that tries to impersonate.
if (param.getResult().equals(false)) {
String pPname = (String) XposedHelpers.callMethod(param.args[1], "getPackageName");
if (pPname.contentEquals((String) param.args[0])) {
param.setResult(true);
var pmService = XposedHelpers.findClassIfExists("com.android.server.pm.PackageManagerService",
loadPackageParam.classLoader);
if (pmService != null) {
var doesSignatureMatchForPermissions = XposedHelpers.findMethodExactIfExists(pmService, "doesSignatureMatchForPermissions",
String.class, "com.android.server.pm.parsing.pkg.ParsedPackage", int.class);
if (doesSignatureMatchForPermissions != null) {
XposedBridge.hookMethod(doesSignatureMatchForPermissions, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) {
if (prefs.getBoolean("digestCreak", true) && prefs.getBoolean("UsePreSig", false)) {
//If we decide to crack this then at least make sure they are same apks, avoid another one that tries to impersonate.
if (param.getResult().equals(false)) {
String pPname = (String) XposedHelpers.callMethod(param.args[1], "getPackageName");
if (pPname.contentEquals((String) param.args[0])) {
param.setResult(true);
}
}
}
}
}
});
});
}
}
}
}
50 changes: 29 additions & 21 deletions app/src/main/java/toolkit/coderstory/CorePatchForT.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ public class CorePatchForT extends CorePatchForS {
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws IllegalAccessException, InvocationTargetException, InstantiationException {
super.handleLoadPackage(loadPackageParam);

findAndHookMethod("com.android.server.pm.PackageManagerServiceUtils", loadPackageParam.classLoader,
var checkDowngrade = XposedHelpers.findMethodExactIfExists("com.android.server.pm.PackageManagerServiceUtils", loadPackageParam.classLoader,
"checkDowngrade",
"com.android.server.pm.parsing.pkg.AndroidPackage",
"android.content.pm.PackageInfoLite",
new ReturnConstant(prefs, "downgrade", null));
"android.content.pm.PackageInfoLite");
if (checkDowngrade != null) {
XposedBridge.hookMethod(checkDowngrade, new ReturnConstant(prefs, "downgrade", null));
}

Class<?> signingDetails = getSigningDetails(loadPackageParam.classLoader);
//New package has a different signature
Expand All @@ -43,7 +44,6 @@ protected void beforeHookedMethod(MethodHookParam param) {
hookAllMethods("android.content.pm.PackageParser", loadPackageParam.classLoader, "checkCapability", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) {
Log.e("CorePatch", "checkCapability");
// 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
Expand All @@ -55,29 +55,37 @@ protected void beforeHookedMethod(MethodHookParam param) {
}
});

findAndHookMethod("com.android.server.pm.InstallPackageHelper", loadPackageParam.classLoader,
"doesSignatureMatchForPermissions", String.class,
"com.android.server.pm.parsing.pkg.ParsedPackage", int.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) {
if (prefs.getBoolean("digestCreak", true) && prefs.getBoolean("UsePreSig", false)) {
//If we decide to crack this then at least make sure they are same apks, avoid another one that tries to impersonate.
if (param.getResult().equals(false)) {
String pPname = (String) XposedHelpers.callMethod(param.args[1], "getPackageName");
if (pPname.contentEquals((String) param.args[0])) {
param.setResult(true);
}
}
}
}
});

if (prefs.getBoolean("digestCreak", true) && prefs.getBoolean("UsePreSig", false)) {
findAndHookMethod("com.android.server.pm.InstallPackageHelper", loadPackageParam.classLoader, "doesSignatureMatchForPermissions", String.class, "com.android.server.pm.parsing.pkg.ParsedPackage", int.class, new XC_MethodHook() {
var assertMinSignatureSchemeIsValid = XposedHelpers.findMethodExactIfExists("com.android.server.pm.ScanPackageUtils", loadPackageParam.classLoader,
"assertMinSignatureSchemeIsValid",
"com.android.server.pm.parsing.pkg.AndroidPackage", int.class);
if (assertMinSignatureSchemeIsValid != null) {
XposedBridge.hookMethod(assertMinSignatureSchemeIsValid, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) {
//If we decide to crack this then at least make sure they are same apks, avoid another one that tries to impersonate.
if (param.getResult().equals(false)) {
String pPname = (String) XposedHelpers.callMethod(param.args[1], "getPackageName");
if (pPname.contentEquals((String) param.args[0])) {
param.setResult(true);
}
if (prefs.getBoolean("authcreak", true)) {
param.setResult(null);
}
}
});
}
findAndHookMethod("com.android.server.pm.ScanPackageUtils", loadPackageParam.classLoader, "assertMinSignatureSchemeIsValid", "com.android.server.pm.parsing.pkg.AndroidPackage", int.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
if (prefs.getBoolean("authcreak", true)) {
param.setResult(null);
}
}
});

Class<?> strictJarVerifier = findClass("android.util.jar.StrictJarVerifier", loadPackageParam.classLoader);
if (strictJarVerifier != null) {
XposedBridge.hookAllConstructors(strictJarVerifier, new XC_MethodHook() {
Expand Down
Loading

0 comments on commit 52ef68c

Please sign in to comment.