v3.3
This commit is contained in:
parent
6cd483afce
commit
4425a3bb58
|
@ -0,0 +1,16 @@
|
|||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
- package-ecosystem: "gradle" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "daily"
|
|
@ -0,0 +1,37 @@
|
|||
name: Android CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: "recursive"
|
||||
fetch-depth: 0
|
||||
|
||||
- name: set up JDK 17
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew assembleRelease
|
||||
|
||||
- name: Upload app-release.apk
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: BootloaderSpoofer
|
||||
path: app/build/outputs/apk/release/app-release.apk
|
|
@ -0,0 +1,25 @@
|
|||
name: Update Gradle Wrapper
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
update-gradle-wrapper:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout the code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: "temurin"
|
||||
java-version: 21
|
||||
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
|
||||
- name: Update Gradle Wrapper
|
||||
uses: gradle-update/update-gradle-wrapper-action@v1
|
|
@ -11,8 +11,8 @@ android {
|
|||
applicationId "es.chiteroman.bootloaderspoofer"
|
||||
minSdk 26
|
||||
targetSdk 34
|
||||
versionCode 32
|
||||
versionName '3.2'
|
||||
versionCode 33
|
||||
versionName '3.3'
|
||||
multiDexEnabled false
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ public final class Data {
|
|||
AwEHoUQDQgAEwCzLu4AL1c86SRwHKjgGlk3L16fbU3U8zWUa1hB+OwCxwqvyD686
|
||||
HLsIKAgZluKMIAQQKRalYapz+tPSdJ4mig==
|
||||
-----END EC PRIVATE KEY-----""";
|
||||
|
||||
public static final String RSA_PRIVATE_KEY = """
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIG4QIBAAKCAYEArnxeKSlkk0ink02gPhc0c9IRXcfYCCxwQZxy0Ih6QB5vEBVy
|
||||
|
@ -62,7 +61,6 @@ public final class Data {
|
|||
uYEkqw8XWqeMAjbuCEG0Rk0aZ6KBAjEAjGBkEFqWweS33qvDGT3UDfPeAqzu5KZg
|
||||
7NYCZ+rhTzONtC+0gwty8SkvqgWOApAu
|
||||
-----END CERTIFICATE-----""";
|
||||
|
||||
public static final String CERT_2 = """
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDlDCCAXygAwIBAgIRALVqd4i3MNOEeYMeYq8wCrcwDQYJKoZIhvcNAQELBQAw
|
||||
|
@ -118,4 +116,98 @@ public final class Data {
|
|||
MDSXYrB4I4WHXPGjxhZuCuPBLTdOLU8YRvMYdEvYebWHMpvwGCF6bAx3JBpIeOQ1
|
||||
wDB5y0USicV3YgYGmi+NZfhA4URSh77Yd6uuJOJENRaNVTzk
|
||||
-----END CERTIFICATE-----""";
|
||||
public static final String RSA_CERT_1 = """
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE4DCCAsigAwIBAgIRAIQxhLQWHo37txEGHTSDrYEwDQYJKoZIhvcNAQELBQAw
|
||||
OTEMMAoGA1UEDAwDVEVFMSkwJwYDVQQFEyBiZGZhOWZhYzAzZGE0NTA2ZmI5Njlm
|
||||
NmM5YmVjM2QxNzAeFw0xOTExMTEyMzU0NDJaFw0yOTExMDgyMzU0NDJaMDkxDDAK
|
||||
BgNVBAwMA1RFRTEpMCcGA1UEBRMgNDRlZDIzNTQ4Y2FiMjUyODc0ZjEzMmY5Y2Rj
|
||||
NzczNGYwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCufF4pKWSTSKeT
|
||||
TaA+FzRz0hFdx9gILHBBnHLQiHpAHm8QFXJwKUVSwHTKTrSMqkDIKAdSST746PIP
|
||||
YDiTVODsBRFXLjdK3hHWYhpqwpRtZhYycTTol96GHom0L8iQYk0CpI7+yxdatK9B
|
||||
sjb7+Ylz49xmJKK02ObP34mWVC3dHBCxmaf/HOQ7tSYrqHWs4pCoyT0UE93bZ1eS
|
||||
5b3CEnQiGuest3K727hYTLne+81uPNByTfkTffY/hO5mDBlRnCQEaPqypnjd6ETx
|
||||
joHBL4mKFIpRKY4p9Q8JJBK9248p5bY8xi/Hl8hDWb0jMRtgRn7h3XBHiLF49lrj
|
||||
Hrx55VPPV2MLPSkztGa7jrUaV2lslSPOC2hx9YJVlsmJ0J2s8BlbmGI4woGz43s5
|
||||
9yIzb+DxK5x0QNFu6jrtdtCHozJ2XVcUOMGaz6SoDYX699Hy+Ps7votYn+BjnGB7
|
||||
RVs4nmWh22jnLWUGEtbqX77pohqry+6zgCAsEu3gbcmryptdjrMCAwEAAaNjMGEw
|
||||
HQYDVR0OBBYEFE60P57rqz3PSH+N1I9Pjafbf2wBMB8GA1UdIwQYMBaAFICGFd7Q
|
||||
lNVDSUrfvWCzz9NoIVX6MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIE
|
||||
MA0GCSqGSIb3DQEBCwUAA4ICAQCg3AyWTANN2v9B/oSxQ2WVQSKHNjIGrHxy747M
|
||||
Yc7w35j43KoM9PJjv9XF9T0/ftR4qHXUGZF4JZgzFOFNrLBCE0ITI7IrBHzUJ/TY
|
||||
3QxoJuz2H3zUEUxkig85OdWXbVR3Y0KzLqz0Z3a8NXlXg9/RGsyuD3fhiUlqo6+Y
|
||||
GyjuQ/zhIplt6XbIrhig4VC4O9dUlIyVfr04Wajk64D2BAejt9yWpUYwCkUGIJL2
|
||||
JKZ6rD7YHDipRD77V0ldbeTXXAKZp4L9kyaJWTLtekBoBMPhH0Gu84lszJXPn8Si
|
||||
T3SdeMFVmz83VL5+1NnuBr6LokM71OYXTECPFxd51I59jUCZVUPOULakYSwa885w
|
||||
x0MyH7faXXUV81+f4omdQ85XOwwn2BSo8V1NXsjUY1W0vCKHe8OxrN7yg1bUz+al
|
||||
XcUYFAXczJ/7sJere8cw9u5IGVQtRBMsv0ztxqgHZVgF3thg0XeU+MbgYNH/J6hi
|
||||
NCpQWRhvhgGXs3yAGFd8U0PPkwViQJ+vHKIqzGOjLbMhFiC0PA56cfeSk8+J7blx
|
||||
ffkgq+g2VFxDdKM+BCrFFKDqo5U7WoWucpHQRUWwU3pThpEyImjbbWddwEHJhC83
|
||||
y41Z4TBUaGOg6105H8hDpQIEu4ik5/J2StMeASlEI9Yor2nigyVXaI3rus3YjBHt
|
||||
lbi40w==
|
||||
-----END CERTIFICATE-----""";
|
||||
public static final String RSA_CERT_2 = """
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
+KdojutP
|
||||
-----END CERTIFICATE-----""";
|
||||
public static final String RSA_CERT_3 = """
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----""";
|
||||
}
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
package es.chiteroman.bootloaderspoofer;
|
||||
|
||||
import android.app.AndroidAppHelper;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.Signature;
|
||||
import android.security.keystore.KeyGenParameterSpec;
|
||||
import android.security.keystore.KeyProperties;
|
||||
import android.util.Log;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1Boolean;
|
||||
import org.bouncycastle.asn1.ASN1Encodable;
|
||||
import org.bouncycastle.asn1.ASN1Enumerated;
|
||||
|
@ -7,9 +15,7 @@ import org.bouncycastle.asn1.ASN1Integer;
|
|||
import org.bouncycastle.asn1.ASN1Null;
|
||||
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
|
||||
import org.bouncycastle.asn1.ASN1OctetString;
|
||||
import org.bouncycastle.asn1.ASN1Primitive;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.ASN1TaggedObject;
|
||||
import org.bouncycastle.asn1.DERNull;
|
||||
import org.bouncycastle.asn1.DEROctetString;
|
||||
import org.bouncycastle.asn1.DLSequence;
|
||||
|
@ -39,8 +45,6 @@ import java.security.cert.Certificate;
|
|||
import java.security.cert.X509Certificate;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import de.robv.android.xposed.IXposedHookLoadPackage;
|
||||
import de.robv.android.xposed.XC_MethodHook;
|
||||
|
@ -50,66 +54,54 @@ import de.robv.android.xposed.XposedHelpers;
|
|||
import de.robv.android.xposed.callbacks.XC_LoadPackage;
|
||||
|
||||
public final class Xposed implements IXposedHookLoadPackage {
|
||||
|
||||
public static final KeyPair EC_KEYPAIR;
|
||||
private static final Map<Integer, ASN1Primitive> map = new HashMap<>();
|
||||
private static final String TAG = "BootloaderSpoofer";
|
||||
private static final KeyPair EC_KEYPAIR, RSA_KEYPAIR;
|
||||
private static final Certificate[] certsChain = new Certificate[3];
|
||||
private static final SecureRandom random = new SecureRandom();
|
||||
private static byte[] attestationChallengeBytes = new byte[0];
|
||||
private static boolean brokenTEE = false;
|
||||
private static Signature[] signatures;
|
||||
private static int versionCode;
|
||||
private static String packageName;
|
||||
|
||||
static {
|
||||
try {
|
||||
PEMParser parser = new PEMParser(new StringReader(Data.EC_PRIVATE_KEY));
|
||||
Object o = parser.readObject();
|
||||
parser.close();
|
||||
Object o;
|
||||
PEMKeyPair pemKeyPair;
|
||||
|
||||
PEMKeyPair pemKeyPair = (PEMKeyPair) o;
|
||||
try (PEMParser parser = new PEMParser(new StringReader(Data.EC_PRIVATE_KEY))) {
|
||||
o = parser.readObject();
|
||||
}
|
||||
|
||||
pemKeyPair = (PEMKeyPair) o;
|
||||
|
||||
EC_KEYPAIR = new JcaPEMKeyConverter().getKeyPair(pemKeyPair);
|
||||
|
||||
try (PEMParser parser = new PEMParser(new StringReader(Data.RSA_PRIVATE_KEY))) {
|
||||
o = parser.readObject();
|
||||
}
|
||||
|
||||
pemKeyPair = (PEMKeyPair) o;
|
||||
|
||||
RSA_KEYPAIR = new JcaPEMKeyConverter().getKeyPair(pemKeyPair);
|
||||
|
||||
certsChain[0] = parseOtherCert(Data.CERT_1);
|
||||
certsChain[1] = parseOtherCert(Data.CERT_2);
|
||||
certsChain[2] = parseOtherCert(Data.CERT_3);
|
||||
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
}
|
||||
|
||||
private static X509CertificateHolder parseOtherCert(int num) {
|
||||
String str = "";
|
||||
private static Certificate parseOtherCert(String cert) throws Exception {
|
||||
|
||||
if (num == 1) str = Data.CERT_1;
|
||||
else if (num == 2) str = Data.CERT_2;
|
||||
else if (num == 3) str = Data.CERT_3;
|
||||
PemReader reader = new PemReader(new StringReader(cert));
|
||||
PemObject pemObject = reader.readPemObject();
|
||||
reader.close();
|
||||
|
||||
try {
|
||||
PemReader reader = new PemReader(new StringReader(str));
|
||||
PemObject pemObject = reader.readPemObject();
|
||||
reader.close();
|
||||
X509CertificateHolder holder = new X509CertificateHolder(pemObject.getContent());
|
||||
|
||||
return new X509CertificateHolder(pemObject.getContent());
|
||||
|
||||
} catch (Exception e) {
|
||||
XposedBridge.log("ERROR, couldn't parse other cert " + num + " : " + e);
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
private static Certificate[] getOtherCerts() throws Throwable {
|
||||
|
||||
var holder_cert_1 = parseOtherCert(1);
|
||||
var holder_cert_2 = parseOtherCert(2);
|
||||
var holder_cert_3 = parseOtherCert(3);
|
||||
|
||||
Certificate c1 = new JcaX509CertificateConverter().getCertificate(holder_cert_1);
|
||||
Certificate c2 = new JcaX509CertificateConverter().getCertificate(holder_cert_2);
|
||||
Certificate c3 = new JcaX509CertificateConverter().getCertificate(holder_cert_3);
|
||||
|
||||
return new Certificate[]{c1, c2, c3};
|
||||
}
|
||||
|
||||
private static ASN1Primitive getPrimitiveFromList(int tagNo) {
|
||||
|
||||
if (map.containsKey(tagNo)) return map.get(tagNo);
|
||||
|
||||
return null;
|
||||
return new JcaX509CertificateConverter().getCertificate(holder);
|
||||
}
|
||||
|
||||
private static Extension addHackedExtension() {
|
||||
|
@ -144,69 +136,36 @@ public final class Xposed implements IXposedHookLoadPackage {
|
|||
ASN1Integer AvendorPatchLevel = new ASN1Integer(20231217);
|
||||
ASN1Integer AbootPatchLevel = new ASN1Integer(20231217);
|
||||
|
||||
ASN1Primitive AcreationDateTime = null;
|
||||
ASN1Primitive Aorigin = null;
|
||||
ASN1Primitive AattestationApplicationId = null;
|
||||
|
||||
if (!brokenTEE) {
|
||||
AcreationDateTime = getPrimitiveFromList(701);
|
||||
Aorigin = getPrimitiveFromList(702);
|
||||
AattestationApplicationId = getPrimitiveFromList(709);
|
||||
}
|
||||
ASN1Integer AcreationDateTime = new ASN1Integer(System.currentTimeMillis());
|
||||
ASN1Integer Aorigin = new ASN1Integer(0);
|
||||
|
||||
var purpose = new DLTaggedObject(true, 1, Apurpose);
|
||||
var algorithm = new DLTaggedObject(true, 2, Aalgorithm);
|
||||
var keySize = new DLTaggedObject(true, 3, AkeySize);
|
||||
var ecCurve = new DLTaggedObject(true, 10, AecCurve);
|
||||
var noAuthRequired = new DLTaggedObject(true, 503, AnoAuthRequired);
|
||||
var creationDateTime = new DLTaggedObject(true, 701, AcreationDateTime);
|
||||
var origin = new DLTaggedObject(true, 702, Aorigin);
|
||||
var rootOfTrust = new DLTaggedObject(true, 704, rootOfTrustSeq);
|
||||
var osVersion = new DLTaggedObject(true, 705, AosVersion);
|
||||
var osPatchLevel = new DLTaggedObject(true, 706, AosPatchLevel);
|
||||
var vendorPatchLevel = new DLTaggedObject(true, 718, AvendorPatchLevel);
|
||||
var bootPatchLevel = new DLTaggedObject(true, 719, AbootPatchLevel);
|
||||
|
||||
ASN1TaggedObject creationDateTime = null;
|
||||
ASN1TaggedObject origin = null;
|
||||
ASN1TaggedObject attestationApplicationId = null;
|
||||
|
||||
if (!brokenTEE) {
|
||||
creationDateTime = new DLTaggedObject(true, 701, AcreationDateTime);
|
||||
origin = new DLTaggedObject(true, 702, Aorigin);
|
||||
attestationApplicationId = new DLTaggedObject(true, 709, AattestationApplicationId);
|
||||
}
|
||||
|
||||
ASN1Encodable[] teeEnforcedEncodables;
|
||||
|
||||
if (brokenTEE) {
|
||||
teeEnforcedEncodables = new ASN1Encodable[]{
|
||||
purpose,
|
||||
algorithm,
|
||||
keySize,
|
||||
ecCurve,
|
||||
noAuthRequired,
|
||||
rootOfTrust,
|
||||
osVersion,
|
||||
osPatchLevel,
|
||||
vendorPatchLevel,
|
||||
bootPatchLevel
|
||||
};
|
||||
} else {
|
||||
teeEnforcedEncodables = new ASN1Encodable[]{
|
||||
purpose,
|
||||
algorithm,
|
||||
keySize,
|
||||
ecCurve,
|
||||
noAuthRequired,
|
||||
creationDateTime,
|
||||
origin,
|
||||
rootOfTrust,
|
||||
osVersion,
|
||||
osPatchLevel,
|
||||
attestationApplicationId,
|
||||
vendorPatchLevel,
|
||||
bootPatchLevel
|
||||
};
|
||||
}
|
||||
ASN1Encodable[] teeEnforcedEncodables = {
|
||||
purpose,
|
||||
algorithm,
|
||||
keySize,
|
||||
ecCurve,
|
||||
noAuthRequired,
|
||||
creationDateTime,
|
||||
origin,
|
||||
rootOfTrust,
|
||||
osVersion,
|
||||
osPatchLevel,
|
||||
vendorPatchLevel,
|
||||
bootPatchLevel
|
||||
};
|
||||
|
||||
ASN1Integer attestationVersion = new ASN1Integer(4);
|
||||
ASN1Enumerated attestationSecurityLevel = new ASN1Enumerated(2);
|
||||
|
@ -235,44 +194,14 @@ public final class Xposed implements IXposedHookLoadPackage {
|
|||
return new Extension(new ASN1ObjectIdentifier("1.3.6.1.4.1.11129.2.1.17"), true, keyDescriptionOctetStr);
|
||||
|
||||
} catch (Exception e) {
|
||||
XposedBridge.log("error create extensions: " + e);
|
||||
Log.e(TAG, "error create extensions: " + e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void parseKeyDescription(ASN1Sequence keyDescription) {
|
||||
ASN1Sequence swEnforcedAuthList = (ASN1Sequence) keyDescription.getObjectAt(6).toASN1Primitive();
|
||||
ASN1Sequence teeEnforcedAuthList = (ASN1Sequence) keyDescription.getObjectAt(7).toASN1Primitive();
|
||||
private static Certificate hackLeafCert() throws Exception {
|
||||
|
||||
for (ASN1Encodable encodable : swEnforcedAuthList) {
|
||||
ASN1TaggedObject taggedObject = (ASN1TaggedObject) encodable;
|
||||
|
||||
int tagNo = taggedObject.getTagNo();
|
||||
ASN1Primitive asn1Primitive = taggedObject.getBaseObject().toASN1Primitive();
|
||||
|
||||
if (asn1Primitive == null) {
|
||||
XposedBridge.log("ERROR, couldn't parse " + tagNo + " object!");
|
||||
} else {
|
||||
map.put(tagNo, asn1Primitive);
|
||||
}
|
||||
}
|
||||
|
||||
for (ASN1Encodable encodable : teeEnforcedAuthList) {
|
||||
ASN1TaggedObject taggedObject = (ASN1TaggedObject) encodable;
|
||||
|
||||
int tagNo = taggedObject.getTagNo();
|
||||
ASN1Primitive asn1Primitive = taggedObject.getBaseObject().toASN1Primitive();
|
||||
|
||||
if (asn1Primitive == null) {
|
||||
XposedBridge.log("ERROR, couldn't parse " + tagNo + " object!");
|
||||
} else {
|
||||
map.put(tagNo, asn1Primitive);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Certificate brokenTeeLeafCert() throws Throwable {
|
||||
var certBuilder = new JcaX509v3CertificateBuilder(
|
||||
new X500Name("CN=chiteroman"),
|
||||
new BigInteger(128, random),
|
||||
|
@ -291,56 +220,38 @@ public final class Xposed implements IXposedHookLoadPackage {
|
|||
return new JcaX509CertificateConverter().getCertificate(certHolder);
|
||||
}
|
||||
|
||||
private static Certificate hackLeafCert(X509Certificate certificate) throws Throwable {
|
||||
var holder = new X509CertificateHolder(certificate.getEncoded());
|
||||
|
||||
var certBuilder = new JcaX509v3CertificateBuilder(
|
||||
holder.getIssuer(),
|
||||
holder.getSerialNumber(),
|
||||
holder.getNotBefore(),
|
||||
holder.getNotAfter(),
|
||||
holder.getSubject(),
|
||||
EC_KEYPAIR.getPublic()
|
||||
);
|
||||
|
||||
for (Object extensionOID : holder.getExtensionOIDs()) {
|
||||
|
||||
ASN1ObjectIdentifier identifier = (ASN1ObjectIdentifier) extensionOID;
|
||||
|
||||
if ("1.3.6.1.4.1.11129.2.1.17".equals(identifier.getId())) continue;
|
||||
|
||||
Extension e = holder.getExtension(identifier);
|
||||
|
||||
certBuilder.addExtension(e);
|
||||
}
|
||||
|
||||
Extension extension = holder.getExtension(new ASN1ObjectIdentifier("1.3.6.1.4.1.11129.2.1.17"));
|
||||
|
||||
ASN1Sequence keyDescription = ASN1Sequence.getInstance(extension.getExtnValue().getOctets());
|
||||
|
||||
parseKeyDescription(keyDescription);
|
||||
|
||||
certBuilder.addExtension(addHackedExtension());
|
||||
|
||||
ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256withECDSA").build(EC_KEYPAIR.getPrivate());
|
||||
|
||||
X509CertificateHolder certHolder = certBuilder.build(contentSigner);
|
||||
|
||||
return new JcaX509CertificateConverter().getCertificate(certHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
|
||||
|
||||
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "AndroidKeyStore");
|
||||
XposedHelpers.findAndHookMethod(keyPairGenerator.getClass(), "generateKeyPair", XC_MethodReplacement.returnConstant(EC_KEYPAIR));
|
||||
PackageManager packageManager = AndroidAppHelper.currentApplication().getPackageManager();
|
||||
|
||||
Class<?> keyGenBuilder = XposedHelpers.findClassIfExists("android.security.keystore.KeyGenParameterSpec.Builder", lpparam.classLoader);
|
||||
XposedHelpers.findAndHookMethod(keyGenBuilder, "setAttestationChallenge", byte[].class, new XC_MethodHook() {
|
||||
PackageInfo packageInfo = packageManager.getPackageInfo(lpparam.packageName, 0);
|
||||
|
||||
packageName = lpparam.packageName;
|
||||
signatures = packageInfo.signatures;
|
||||
versionCode = packageInfo.versionCode;
|
||||
|
||||
Class<?> AndroidKeyStoreKeyPairGeneratorSpi = XposedHelpers.findClassIfExists("android.security.keystore2.AndroidKeyStoreKeyPairGeneratorSpi", lpparam.classLoader);
|
||||
|
||||
if (AndroidKeyStoreKeyPairGeneratorSpi == null) {
|
||||
|
||||
KeyPairGenerator keyPairGenerator1 = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");
|
||||
XposedHelpers.findAndHookMethod(keyPairGenerator1.getClass(), "generateKeyPair", XC_MethodReplacement.returnConstant(EC_KEYPAIR));
|
||||
XposedHelpers.findAndHookMethod(keyPairGenerator1.getClass(), "genKeyPair", XC_MethodReplacement.returnConstant(EC_KEYPAIR));
|
||||
|
||||
KeyPairGenerator keyPairGenerator2 = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
|
||||
XposedHelpers.findAndHookMethod(keyPairGenerator2.getClass(), "generateKeyPair", XC_MethodReplacement.returnConstant(RSA_KEYPAIR));
|
||||
XposedHelpers.findAndHookMethod(keyPairGenerator1.getClass(), "genKeyPair", XC_MethodReplacement.returnConstant(RSA_KEYPAIR));
|
||||
|
||||
} else {
|
||||
XposedHelpers.findAndHookMethod(AndroidKeyStoreKeyPairGeneratorSpi, "generateKeyPair", XC_MethodReplacement.returnConstant(EC_KEYPAIR));
|
||||
}
|
||||
|
||||
XposedHelpers.findAndHookMethod(KeyGenParameterSpec.Builder.class, "setAttestationChallenge", byte[].class, new XC_MethodHook() {
|
||||
@Override
|
||||
protected void beforeHookedMethod(MethodHookParam param) {
|
||||
protected void afterHookedMethod(MethodHookParam param) {
|
||||
attestationChallengeBytes = (byte[]) param.args[0];
|
||||
XposedBridge.log("attestationChallenge: " + Arrays.toString(attestationChallengeBytes));
|
||||
Log.d(TAG, "attestationChallenge: " + Arrays.toString(attestationChallengeBytes));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -349,43 +260,42 @@ public final class Xposed implements IXposedHookLoadPackage {
|
|||
XposedHelpers.findAndHookMethod(keyStoreSpi.getClass(), "engineGetCertificateChain", String.class, new XC_MethodHook() {
|
||||
@Override
|
||||
protected void afterHookedMethod(MethodHookParam param) {
|
||||
Certificate[] certificates = null;
|
||||
|
||||
try {
|
||||
Certificate[] otherCerts = getOtherCerts();
|
||||
certificates = (Certificate[]) param.getResultOrThrowable();
|
||||
} catch (Throwable e) {
|
||||
XposedBridge.log("Couldn't get original certificate chain, broken TEE ?");
|
||||
}
|
||||
|
||||
Certificate[] hackCerts = new Certificate[4];
|
||||
Certificate[] hackCerts = new Certificate[4];
|
||||
|
||||
System.arraycopy(otherCerts, 0, hackCerts, 1, otherCerts.length);
|
||||
System.arraycopy(certsChain, 0, hackCerts, 1, certsChain.length);
|
||||
|
||||
Certificate[] certificates = (Certificate[]) param.getResult();
|
||||
if (certificates != null && certificates.length > 1) {
|
||||
|
||||
if (certificates == null || certificates.length == 0) {
|
||||
brokenTEE = true;
|
||||
Certificate leaf = certificates[0];
|
||||
|
||||
XposedBridge.log("Uhhh, seems like you have a broken TEE.");
|
||||
hackCerts[0] = brokenTeeLeafCert();
|
||||
if (!(leaf instanceof X509Certificate x509Certificate)) return;
|
||||
|
||||
} else {
|
||||
brokenTEE = false;
|
||||
byte[] bytes = x509Certificate.getExtensionValue("1.3.6.1.4.1.11129.2.1.17");
|
||||
|
||||
Certificate leaf = certificates[0];
|
||||
|
||||
if (!(leaf instanceof X509Certificate x509Certificate)) return;
|
||||
|
||||
byte[] bytes = x509Certificate.getExtensionValue("1.3.6.1.4.1.11129.2.1.17");
|
||||
|
||||
if (bytes == null || bytes.length == 0) {
|
||||
XposedBridge.log("Leaf certificate doesn't contain attestation extensions... Ignoring it.");
|
||||
return;
|
||||
}
|
||||
|
||||
hackCerts[0] = hackLeafCert(x509Certificate);
|
||||
if (bytes == null || bytes.length == 0) {
|
||||
XposedBridge.log("Leaf certificate doesn't contain attestation extensions... Ignoring it.");
|
||||
return;
|
||||
}
|
||||
|
||||
param.setResult(hackCerts);
|
||||
|
||||
} catch (Throwable t) {
|
||||
XposedBridge.log("ERROR: " + t);
|
||||
} else {
|
||||
Log.d(TAG, "Original certificate chain is null or empty... Broken TEE ?");
|
||||
}
|
||||
|
||||
try {
|
||||
hackCerts[0] = hackLeafCert();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "ERROR creating hacked leaf certificate: " + e);
|
||||
}
|
||||
|
||||
param.setResult(hackCerts);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue