From ec68625b965482dd72459303a571c0becf5176b8 Mon Sep 17 00:00:00 2001 From: chiteroman <98092901+chiteroman@users.noreply.github.com> Date: Mon, 11 Dec 2023 17:05:45 +0100 Subject: [PATCH] v2.0 --- app/build.gradle | 10 +- .../chiteroman/bootloaderspoofer/Xposed.java | 99 ++++++++++++++----- build.gradle | 9 +- gradle/wrapper/gradle-wrapper.properties | 4 +- 4 files changed, 82 insertions(+), 40 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index eeb7bd4..20fd789 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,13 +5,14 @@ plugins { android { namespace 'es.chiteroman.bootloaderspoofer' compileSdk 34 + buildToolsVersion '34.0.0' defaultConfig { applicationId "es.chiteroman.bootloaderspoofer" - minSdk 24 + minSdk 26 targetSdk 34 - versionCode 3 - versionName '1.2' + versionCode 20 + versionName '2.0' multiDexEnabled false } @@ -24,13 +25,14 @@ android { multiDexEnabled false } } + compileOptions { sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 } - buildToolsVersion '34.0.0' } dependencies { compileOnly 'de.robv.android.xposed:api:82' + implementation 'org.bouncycastle:bcpkix-lts8on:2.73.3' } diff --git a/app/src/main/java/es/chiteroman/bootloaderspoofer/Xposed.java b/app/src/main/java/es/chiteroman/bootloaderspoofer/Xposed.java index 12203f9..7119016 100644 --- a/app/src/main/java/es/chiteroman/bootloaderspoofer/Xposed.java +++ b/app/src/main/java/es/chiteroman/bootloaderspoofer/Xposed.java @@ -1,12 +1,18 @@ package es.chiteroman.bootloaderspoofer; -import java.io.ByteArrayInputStream; +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.x509.Extension; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; + import java.lang.reflect.Method; import java.security.KeyStore; import java.security.KeyStoreSpi; import java.security.cert.Certificate; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; +import java.security.cert.CertificateException; import java.util.Locale; import de.robv.android.xposed.IXposedHookLoadPackage; @@ -16,13 +22,13 @@ import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; -public class Xposed implements IXposedHookLoadPackage { - private static int indexOf(byte[] array) { - final byte[] PATTERN = {48, 74, 4, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 10, 1, 2}; +public final class Xposed implements IXposedHookLoadPackage { + + private static int indexOf(byte[] array, byte[] target) { outer: - for (int i = 0; i < array.length - PATTERN.length + 1; i++) { - for (int j = 0; j < PATTERN.length; j++) { - if (array[i + j] != PATTERN[j]) { + for (int i = 0; i < array.length - target.length + 1; i++) { + for (int j = 0; j < target.length; j++) { + if (array[i + j] != target[j]) { continue outer; } } @@ -31,34 +37,73 @@ public class Xposed implements IXposedHookLoadPackage { return -1; } + private static Certificate doLogic(Certificate certificate) { + try { + X509CertificateHolder certificateHolder = new X509CertificateHolder(certificate.getEncoded()); + + Extension extension = certificateHolder.getExtension(new ASN1ObjectIdentifier("1.3.6.1.4.1.11129.2.1.17")); + + ASN1Sequence keyDescription = ASN1Sequence.getInstance(extension.getExtnValue().getOctets()); + + ASN1Sequence teeEnforcedAuthList = (ASN1Sequence) keyDescription.getObjectAt(7).toASN1Primitive(); + + ASN1Sequence rootOfTrustAuthList = null; + + for (ASN1Encodable encodable : teeEnforcedAuthList) { + if (!(encodable instanceof ASN1TaggedObject asn1TaggedObject)) continue; + + if (asn1TaggedObject.getTagNo() != 704) continue; + + rootOfTrustAuthList = (ASN1Sequence) asn1TaggedObject.getBaseObject().toASN1Primitive(); + + break; + } + + if (rootOfTrustAuthList == null) { + throw new CertificateException("ERROR, Root of Trust is null"); + } + + byte[] bytes = certificate.getEncoded(); + + int index = indexOf(bytes, rootOfTrustAuthList.getEncoded()); + + bytes[index + 38] = 1; + bytes[index + 41] = 0; + + X509CertificateHolder modCert = new X509CertificateHolder(bytes); + + JcaX509CertificateConverter converter = new JcaX509CertificateConverter(); + + return converter.getCertificate(modCert); + + } catch (Exception e) { + XposedBridge.log("ERROR in creating certificate: " + e); + } + + return certificate; + } + @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) { try { KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); + keyStore.load(null); + KeyStoreSpi keyStoreSpi = (KeyStoreSpi) XposedHelpers.getObjectField(keyStore, "keyStoreSpi"); XposedHelpers.findAndHookMethod(keyStoreSpi.getClass(), "engineGetCertificateChain", String.class, new XC_MethodHook() { @Override - protected void afterHookedMethod(MethodHookParam param) throws Throwable { - Certificate[] certificates = (Certificate[]) param.getResultOrThrowable(); - if (certificates[0] instanceof X509Certificate cert) { + protected void afterHookedMethod(MethodHookParam param) { + Certificate[] certificates = (Certificate[]) param.getResult(); - for (Method method : cert.getClass().getMethods()) { - if (method.getName().toLowerCase(Locale.ROOT).contains("verify")) { - XposedBridge.hookMethod(method, XC_MethodReplacement.DO_NOTHING); - } + for (Method declaredMethod : certificates[0].getClass().getDeclaredMethods()) { + if (declaredMethod.getName().toLowerCase(Locale.ROOT).contains("verify")) { + XposedBridge.hookMethod(declaredMethod, XC_MethodReplacement.DO_NOTHING); } - - byte[] bytes = cert.getEncoded(); - if (bytes == null || bytes.length == 0) return; - int index = indexOf(bytes); - if (index == -1) return; - bytes[index + 38] = 1; - bytes[index + 41] = 0; - CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); - X509Certificate modCert = (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(bytes)); - certificates[0] = modCert; - param.setResult(certificates); } + + certificates[0] = doLogic(certificates[0]); + + param.setResult(certificates); } }); } catch (Throwable t) { diff --git a/build.gradle b/build.gradle index 7a80059..08a0047 100644 --- a/build.gradle +++ b/build.gradle @@ -1,9 +1,4 @@ -buildscript { - ext { - agp_version = '8.1.1' - } -}// Top-level build file where you can add configuration options common to all sub-projects/modules. +// Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id 'com.android.application' version '8.1.1' apply false - id 'com.android.library' version '8.0.2' apply false + id 'com.android.application' version '8.2.0' apply false } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 43c3449..b0b91e2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Sep 18 16:40:53 CEST 2023 +#Mon Dec 11 17:01:20 CET 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists