Skip to content

Commit

Permalink
v2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
chiteroman committed Dec 11, 2023
1 parent e0caa9c commit ec68625
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 41 deletions.
10 changes: 6 additions & 4 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand All @@ -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'
}
101 changes: 73 additions & 28 deletions app/src/main/java/es/chiteroman/bootloaderspoofer/Xposed.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -16,13 +22,13 @@
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;
}
}
Expand All @@ -31,34 +37,73 @@ private static int indexOf(byte[] array) {
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) {

for (Method method : cert.getClass().getMethods()) {
if (method.getName().toLowerCase(Locale.ROOT).contains("verify")) {
XposedBridge.hookMethod(method, XC_MethodReplacement.DO_NOTHING);
}
}
protected void afterHookedMethod(MethodHookParam param) {
Certificate[] certificates = (Certificate[]) param.getResult();

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);
for (Method declaredMethod : certificates[0].getClass().getDeclaredMethods()) {
if (declaredMethod.getName().toLowerCase(Locale.ROOT).contains("verify")) {
XposedBridge.hookMethod(declaredMethod, XC_MethodReplacement.DO_NOTHING);
}
}

certificates[0] = doLogic(certificates[0]);

param.setResult(certificates);
}
});
} catch (Throwable t) {
Expand Down
9 changes: 2 additions & 7 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -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
}
4 changes: 2 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit ec68625

Please sign in to comment.