Skip to content

Commit

Permalink
Spoof software attestation
Browse files Browse the repository at this point in the history
  • Loading branch information
chiteroman committed Dec 11, 2023
1 parent ec68625 commit a987e0e
Showing 1 changed file with 77 additions and 9 deletions.
86 changes: 77 additions & 9 deletions app/src/main/java/es/chiteroman/bootloaderspoofer/Xposed.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,18 @@
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;

import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;

import java.io.StringReader;
import java.lang.reflect.Method;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreSpi;
import java.security.cert.Certificate;
Expand All @@ -23,6 +32,24 @@
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public final class Xposed implements IXposedHookLoadPackage {
private static final String SW_RSA_ATTEST_ROOT_KEY = """
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCia63rbi5EYe/VDoLmt5TRdSMfd5tjkWP/96r/C3JHTsAsQ+wz
fNes7UA+jCigZtX3hwszl94OuE4TQKuvpSe/lWmgMdsGUmX4RFlXYfC78hdLt0GA
ZMAoDo9Sd47b0ke2RekZyOmLw9vCkT/X11DEHTVm+Vfkl5YLCazOkjWFmwIDAQAB
AoGAU8dxXchmqzVNbbvff7zgUa63YErk51Yem/EXzhkMaIXRkMO0edaCtZtnkRvg
9OQ2qEiLWaCTlUoyU7H/HUn2lwTQsOXyZI7dHijVDRMIv1mmrHCrGW/JC8FXfPLS
r3L3KoHXQVYL2mslbR8Rpogxq4WwnwK6XqSTH9mynFwQwEkCQQDMX3EZk3ricWVH
ruXD0BpXOMMpZuLu4rg5+1L51WEJvItIMeSjLuNa+g3AI8AYTYYi/aSLk6XEv82L
iXFGmJ2XAkEAy3M8k8Z0QzHae4olduqoHVWEarBtDE+fqFQBWgdm8fZhdHWrvlAc
qwJIXMUVc+dWm/FAQarCjbqWqhCRdaYgnQJBAJ7z7GdUCVNtlrQ2F4ZAqPwFreTZ
nM7njxmpm1Os3hhQiJPSGl3A7huoOGGkbJd6VEWKuRvF7jwkYZ2RfITH1mkCQAvh
X9E1Toa5+4spRwTJsSV9X+0m/kcwwx7+QNH0CrPockptsKi9Xt8xk+4u6BDLmogi
r2DmStQh6DhoHUZkfBUCQQCOgBkqH/15drpdR+BQH3VaP4/ALFfxR9E3G+lS+M5a
IqJEk9kh8vjuGzTaAZyU5keUmpWNc1gI7OvDMaH4+8vQ
-----END RSA PRIVATE KEY-----
""";
private static volatile boolean hardwareAttesatation = true;

private static int indexOf(byte[] array, byte[] target) {
outer:
Expand All @@ -45,17 +72,33 @@ private static Certificate doLogic(Certificate certificate) {

ASN1Sequence keyDescription = ASN1Sequence.getInstance(extension.getExtnValue().getOctets());

ASN1Sequence swEnforcedAuthList = (ASN1Sequence) keyDescription.getObjectAt(6).toASN1Primitive();

ASN1Sequence teeEnforcedAuthList = (ASN1Sequence) keyDescription.getObjectAt(7).toASN1Primitive();

ASN1Sequence rootOfTrustAuthList = null;

for (ASN1Encodable encodable : swEnforcedAuthList) {
if (!(encodable instanceof ASN1TaggedObject asn1TaggedObject)) continue;

if (asn1TaggedObject.getTagNo() != 704) continue;

rootOfTrustAuthList = (ASN1Sequence) asn1TaggedObject.getBaseObject().toASN1Primitive();

hardwareAttesatation = false;

break;
}

for (ASN1Encodable encodable : teeEnforcedAuthList) {
if (!(encodable instanceof ASN1TaggedObject asn1TaggedObject)) continue;

if (asn1TaggedObject.getTagNo() != 704) continue;

rootOfTrustAuthList = (ASN1Sequence) asn1TaggedObject.getBaseObject().toASN1Primitive();

hardwareAttesatation = true;

break;
}

Expand All @@ -72,12 +115,35 @@ private static Certificate doLogic(Certificate certificate) {

X509CertificateHolder modCert = new X509CertificateHolder(bytes);

JcaX509CertificateConverter converter = new JcaX509CertificateConverter();
if (hardwareAttesatation) {

JcaX509CertificateConverter converter = new JcaX509CertificateConverter();

return converter.getCertificate(modCert);
return converter.getCertificate(modCert);

} else {

PEMParser parser = new PEMParser(new StringReader(SW_RSA_ATTEST_ROOT_KEY));
PEMKeyPair pemKeyPair = (PEMKeyPair) parser.readObject();
parser.close();

JcaPEMKeyConverter jcaPEMKeyConverter = new JcaPEMKeyConverter();

KeyPair keyPair = jcaPEMKeyConverter.getKeyPair(pemKeyPair);

X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(certificateHolder.getSubject(), certificateHolder.getSerialNumber(), certificateHolder.getNotBefore(), certificateHolder.getNotAfter(), certificateHolder.getSubject(), keyPair.getPublic());

certBuilder.copyAndAddExtension(extension.getExtnId(), extension.isCritical(), modCert);

ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256WithRSAEncryption").build(keyPair.getPrivate());

X509CertificateHolder certHolder = certBuilder.build(contentSigner);

return new JcaX509CertificateConverter().getCertificate(certHolder);
}

} catch (Exception e) {
XposedBridge.log("ERROR in creating certificate: " + e);
XposedBridge.log("ERROR creating certificate: " + e);
}

return certificate;
Expand All @@ -95,14 +161,16 @@ public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) {
protected void afterHookedMethod(MethodHookParam param) {
Certificate[] certificates = (Certificate[]) param.getResult();

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]);

if (hardwareAttesatation) {
for (Method method : certificates[0].getClass().getMethods()) {
if (method.getName().toLowerCase(Locale.ROOT).contains("verify")) {
XposedBridge.hookMethod(method, XC_MethodReplacement.DO_NOTHING);
}
}
}

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

param.setResult(certificates);
}
});
Expand Down

0 comments on commit a987e0e

Please sign in to comment.