Giter VIP home page Giter VIP logo

Comments (24)

gamelaster avatar gamelaster commented on May 29, 2024 3

I can confirm that @thegnomewizard's method is still working for com.google.android.projection.gearhead_9.4.631627-release-94631627 🥳

from aacs.

tomasz-grobelny avatar tomasz-grobelny commented on May 29, 2024

Basic idea is to connect mobile device to openauto/car, dump process memory (pmdump) and search for certificates there.

from aacs.

gamelaster avatar gamelaster commented on May 29, 2024

Hi, relating to my question at #4 and emails with Tomasz,

In the end, I was able to dump both latest Headunit Public & Private key and Mobile Device Public & Private key.

In case of Headunit keys, I dumped them from DHU, it's "hidden" inside the app, so I dumped them directly from memory when it was supposed to be loaded by BoringSSL.

In case of Mobile Device keys, it was more difficult. The public key is easy to get from smali files (or via jadx GUI, searching for BEGIN CERTIFICATE keyword). But private key is somehow composed from public key, root certificate and some unknown byte arrays. I wasn't able to figure out how this all works and what are that unknown byte arrays (I don't have much skills about SSL/TLS encryption). Anyway, by decompiling the code and trying to simulate the code, I wasn't able to get correct result. Although, by dumping some of the variables directly from working device, I was able to dump the key. My bet is that Google designed some functions the way, that jadx will generate the pseudo-code wrongly, thus the result will not match. Although, I might be wrong, maybe there are some other factors (I have one suspicion what is different from my reproduction code).

from aacs.

tomasz-grobelny avatar tomasz-grobelny commented on May 29, 2024

Hi @gamelaster,

I tried to get newer certs by doing pmdump+search as I did previously, but this time wasn't able to get the private key :-( Could you possibly describe your approach in more detail? How did you dump "some of the variables directly from working device" - which tools did you use and how did you find the variables to dump?

from aacs.

tomasz-grobelny avatar tomasz-grobelny commented on May 29, 2024

Do I understand correctly that this function is of primary interest here

    public static SSLContext m23915f(iwa iwa) throws Exception {
        SSLContext instance = SSLContext.getInstance("TLSv1.2");
        Cipher instance2 = Cipher.getInstance("AES/CBC/PKCS5Padding");
        f27646b.mo22711j().mo22663aa(6991).mo22646J("Using %s from %s", "AES/CBC/PKCS5Padding", instance2.getProvider());
        byte[] bArr = new byte[48];
        String a = iwa.mo16269a();
        Charset charset = f27645a;
        m23918i(a.getBytes(charset), bArr, iwa.mo16271c());
        m23918i("-----BEGIN CERTIFICATE-----\nMIIDiTCCAnGgAwIBAgIJAMFO56WkVE1CMA0GCSqGSIb3DQEBBQUAMFsxCzAJBgNV\nBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW\naWV3MR8wHQYDVQQKDBZHb29nbGUgQXV0b21vdGl2ZSBMaW5rMB4XDTE0MD
        for (int i = 0; i < 7; i++) {
            m23918i(bArr, bArr, iwa.mo16271c());
        }
        byte[] bArr2 = new byte[32];
        System.arraycopy(bArr, 0, bArr2, 0, 32);
        instance2.init(2, new SecretKeySpec(bArr2, "AES"), new IvParameterSpec(bArr, 32, 16));
        byte[] doFinal = instance2.doFinal(iwa.mo16270b());
        int length = doFinal.length - 54;
        byte[] bArr3 = new byte[length];
        System.arraycopy(doFinal, 28, bArr3, 0, length);
        ivx ivx = new ivx(KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(Base64.decode(bArr3, 2))), iwa.mo16269a());
        instance.init(new KeyManager[]{ivx}, new TrustManager[]{ivx.f27638a}, (SecureRandom) null);
        f27646b.mo22619d().mo22663aa(6992).mo22646J("Successfully initialized SSL context for protocol: %s using provider: %s", instance.getProtocol(), instance.getProvider().getName());
        return instance;
    }

and what we eventually need is this: Base64.decode(bArr3, 2)?

from aacs.

gamelaster avatar gamelaster commented on May 29, 2024

Hi @tomasz-grobelny , as far as I remember, this looks like that function. I will try to take look on it, but probably after 20th October, since I have deadline for a another project :/

from aacs.

kevinlieb avatar kevinlieb commented on May 29, 2024

I am following along here also. Very interested in getting this working on a vehicle where I can not change the date and time.

from aacs.

thegnomewizard avatar thegnomewizard commented on May 29, 2024

I was able to take the above function (though it looked slightly different on my computer, I may have got a newer APK or be using an older JADX), tweak it very slightly and run it to produce some private key (and if you don't do it right, the creation step fails, so perhaps it's valid?)

However, the private key is not compatible (e.g. different modulus) to any of the visible certificates in the code - I assume this is what @gamelaster refers to with "correct results" anyway? There's a class that implements X509KeyManager which the private key and a string possibly containing a base64 certificate is passed into, which also appears to load another certificate embedded in the code as well as creating a completely new certificate - this newly created certificate will have the correct modulus, but when I test it it uses the input certificate causing it to expire on the 19th March 2022 (same as the input certificate).

There is some logic to either use the default string (containing the March cert) and the byte arrays from the main class, but it also has provisions to load the content from elsewhere. Some of it maps onto Phenotype (which allows Google to override values via GMS) but it's quite complex logic, so I'm not certain yet if it might not also be pulling values from another location.

Edit to add: the only Android phone I have is meant to be rooted but it seems to be messed up so I wasn't able to run pmdump and actually see the cert from there to see what it looks like.

from aacs.

gamelaster avatar gamelaster commented on May 29, 2024

@thegnomewizard you're right. For some reason, using directly JADX code doesn't work at all. It must be combination of dumped variable contents from the phone + using some parts of code to produce working private certificate. I'm absolutely cryptography noob, so I don't know how those things works, so I just did things which gave me the cert.

from aacs.

thegnomewizard avatar thegnomewizard commented on May 29, 2024

Ah, then in case anyone is interested in trying it, this is the code I copied and tweaked into an empty Android Activity project. Just call 'doTest', from onCreate for example:

    private void doTest() throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, CertificateException {
        SomethingProvider somethingProvider = new SomethingProvider();
        Charset useCharset = StandardCharsets.UTF_8;
        Cipher instance = Cipher.getInstance("AES/CBC/PKCS5Padding");
        String test = somethingProvider.getString();

        byte[] bArr = new byte[48];
        tweakBytes(somethingProvider.getString().getBytes(useCharset), bArr, somethingProvider.getArray1());
        tweakBytes("-----BEGIN CERTIFICATE-----\nMIIDiTCCAnGgAwIBAgIJAMFO56WkVE1CMA0GCSqGSIb3DQEBBQUAMFsxCzAJBgNV\nBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW\naWV3MR8wHQYDVQQKDBZHb29nbGUgQXV0b21vdGl2ZSBMaW5rMB4XDTE0MDYwNjE4\nMjgxOVoXDTQ0MDYwNTE4MjgxOVowWzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNh\nbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxHzAdBgNVBAoMFkdvb2ds\nZSBBdXRvbW90aXZlIExpbmswggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\nAQDUH+iIbwwVb74NdI5eBv/ACFmh4ml/NOW7gUVWdYX50n8uQQsHHLCNIhk5VV2H\nhanvAZ/XXHPuVAPadE2HpnNqePKF/RDo4eJo/+rOief8gBYq/Z+OQTZeLdNm+GoI\nHBrEjU4Ms8IdLuFW0jF8LlIRgekjLHpc7duUl3QpwBlmAWQK40T/SZjprlmhyqfJ\ng1rxFdnGbrSibmCsTmb3m6WZyZUyrcwmd7t6q3pHbMABO+o02asPG/YPj/SJo4+i\nfb5/Nk56f3hH9pBiPKQXJnVUdVLKMXSRgydDBsGSBol4C0JL77MNDrMR5jdafJ4j\nmWmsa2+mnzoAv9AxEL9T0LiNAgMBAAGjUDBOMB0GA1UdDgQWBBS5dqvv8DPQiwrM\nfgn8xKR91k7wgjAfBgNVHSMEGDAWgBS5dqvv8DPQiwrMfgn8xKR91k7wgjAMBgNV\nHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQDKcnBsrbB0Jbz2VGJKP2lwYB6P\ndCTCCpQu7dVp61UQOX+zWfd2hnNMnLs/r1xPO+eyN0vmw7sD05phaIhbXVauKWZi\n9WqWHTaR+9s6CTyBOc1Mye0DMj+4vHt+WLmf0lYjkYUVYvR1EImX8ktXzkVmOqn+\ne30siqlZ8pQpsOgegIKfJ+pNQM8c3eXVv3KFMUgjZW33SziZL8IMsLvSO+1LtH37\nKqbTEMP6XUwVuZopgGvaHU74eT/WSRGlL7vX4OL5/UXXP4qsGH2Zp7uQlErv4H9j\nkMs37UL1vGb4M8RM7Eyu9/RulepSmqZUF+3i+3eby8iGq/3OWk9wgJf7AXnx\n-----END CERTIFICATE-----\n".getBytes(useCharset), bArr, somethingProvider.getArray1());
        for (int i = 0; i < 7; i++) {
            tweakBytes(bArr, bArr, somethingProvider.getArray1());
        }
        byte[] bArr2 = new byte[32];
        System.arraycopy(bArr, 0, bArr2, 0, 32);
        instance.init(2, new SecretKeySpec(bArr2, "AES"), new IvParameterSpec(bArr, 32, 16));
        byte[] doFinal = instance.doFinal(somethingProvider.getArray2());
        int length = doFinal.length - 54;
        byte[] bArr3 = new byte[length];
        System.arraycopy(doFinal, 28, bArr3, 0, length);
        java.security.PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(Base64.decode(bArr3, 2)));
        String bobo = Base64.encodeToString(privateKey.getEncoded(), Base64.DEFAULT);
        Log.e("TEST", "privateKey.getEncoded()=" + bobo);

        CertificateFactory factory = CertificateFactory.getInstance("X.509");
        ByteArrayInputStream inputStream = new ByteArrayInputStream(test.getBytes(useCharset));
        X509Certificate certificate = (X509Certificate)factory.generateCertificate(inputStream);
        String baba = Base64.encodeToString(certificate.getEncoded(), Base64.DEFAULT);
        Log.e("TEST", "New cert: " + baba);
    }

    private static void tweakBytes(byte[] bArr, byte[] bArr2, byte[] bArr3) {
        for (int i = 0; i < bArr.length; i++) {
            for (int i2 = 0; i2 < 48; i2++) {
                int b = bArr2[i2] & 255;
                bArr2[i2] = (byte) (((((b >> 7) | (b + b)) + 33) ^ bArr3[i2 % bArr3.length]) ^ bArr[i]);
            }
        }
    }
    final class SomethingProvider {
        /* renamed from: a */
        public final String getString() {
            return "-----BEGIN CERTIFICATE-----\nMIIDLDCCAhQCAgLCMA0GCSqGSIb3DQEBCwUAMFsxCzAJBgNVBAYTAlVTMRMwEQYD\nVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MR8wHQYDVQQK\nDBZHb29nbGUgQXV0b21vdGl2ZSBMaW5rMB4XDTE0MDcwNDAwMDAwMFoXDTIyMDMx\nOTIzMzgzMFowXDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAU\nBgNVBAcMDU1vdW50YWluIFZpZXcxEzARBgNVBAoMCkNhclNlcnZpY2UxCzAJBgNV\nBAsMAjQ3MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnFsN3bAQhIz8\nvH5UFqbiztjgcKaL/oE3n8BnKOBB/zbCFw35zSWCVy4fKQxztkLX/A2t9OnIrq6b\njwf7iHIcGqocd7UCeGo1Dswbuor4vGJc5mdH9SFtj/R5ko8z26Q96r4HGIW4XVda\niegpu1n83FLgkznO4DY/C8bkIP56Kon3ehZsrfERXq1TCXDe/ZlPp53cNPwPBHI9\n5NmRfjRAmaBpo4JVSQAKpyFHUJdzkSToPRchKpJSLuLv5ssbdYV7pzuhh2Qwr3k8\nP/XoT41e4DmMCi0KcIe1+E56JX1wuOQGaLtuCgoWDHkJhQTZRUhl9coOYXi4HaF2\nLN7fGDdipwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBbnNS7ZyCLaUEKGMf1ou1a\nHrzqMynjt0M8s6F+rOe50kqthRNAuLlt5HFAW3TI9yQRb8htEUc/5b8tsvHWN2vZ\nJxtvl/f8TQpKV/CtLDEiebmxfqD2e1u3rwSmJPV2ESxbxBtyn8CMNwqgcgYNDCbl\nf2vF3HAp71AmrFgfmu4X0cQ4szIe0yZC0Am7H6eFgI3sHF5/y4loihbATm4lyeQz\nnFew5+8uElgnIubfoRXwVwE/gxipiCOZyjCV28LszeIn9MoCnZ7AEEX5Us8eWl06\nDGK8f6690yJk18E8pEM/tfIzNslgeocRMG2yfmkCuqcHGt6gh/V/B/c74s487fBf\n-----END CERTIFICATE-----\n";
        }

        /* renamed from: b */
        public final byte[] getArray1() {
            final byte[] f30470n = {-72, -102, 94, -110, -110, 104, 43, -1, 94, 31, -44, -115, 58, 97, 83, -21, -108, 122, -3, 17, 71, -10, -83, 96, -114, 106, -58, -59, 94, -68, 118, -76, -13, -77, 40, -94, 29, 42, 96, 17, 64, 98, -55, -50, 33, -89, 88, -45, -113, -88, -19, -9, -41, 14, 30, -41, 10, 71, -86, -16, -48, -49, -14, 5, -124, 83, -120, -91, -30, -60, 4, -64, 39, 56, -20, 71, 54, -4, -125, -74, 53, 76, -125, 120, -127, 53, -94, -89, -28, 72, -39, -80, 105, 69, 51, 120, 8, -81, -25, -22, -46, 43, 67, 12, -66, 4, -17, -46, -64, -29, 99, -111, 111, -103, 4, 57, 100, -101, -116, 1, -1, -120, -65, 24, 89, Byte.MAX_VALUE, -127, 81, 82, 65, -104, 105, 94, -67, 119, -119, 9, 89, -11, -113, -67, 4, 93, 68, -66, 8, 117, 68, -116, -36, 9, 7, -6, -25, -8, 102, 6, 111, 73, -72, 76, -79, -117, -101, -68, 40, -114, -117, -29, 22, 98, -43, -80, 35, 52, 48, -70, 48, 31, -50, -33, -8, 114, 120, 7, -18, 0, 118, 98, 123, 68, -73, 37, -39, 18, -102, 16, -20, -8, 104, -110, 65, 78, -47, 112, -114, 34, 42, -61, -125, 57, 112, 17, 8, 31, 91, 54, -92, -10, 115, 68, 6, 78, -95, 7, 38, 82, 80, -22, -105, -72, -90, 56, 62, -108, 60, -118, 71, 56, 109, 81, 38, -106, 4, -90, -120, 9, 36, -45, -105, -83, 117, 50, 18, 30, 41};
            return f30470n;
        }

        /* renamed from: c */
        public final byte[] getArray2() {
            final byte[] f30471o = {-125, -7, -2, -91, -74, 121, -5, -10, -52, -96, -84, 77, -26, 85, 110, 120, 1, 109, 47, -18, 51, 119, -75, 109, 114, -68, -112, 6, 55, -121, -25, 11, 32, 40, 61, -45, 108, -20, 90, -27, -50, 100, 25, -98, -27, -101, 11, 23, 91, 47, -8, 69, -69, -18, 36, 122, 25, 51, -58, -56, 33, -124, 41, 108, 98, -55, -39, -42, -43, 54, -102, -52, -81, 37, -72, 87, 68, -29, -101, 14, 96, -99, -22, -99, 50, 48, -77, -17, -81, 64, -126, -12, 88, 18, 27, 93, -9, 45, -70, -18, 62, 123, 95, -82, 69, -22, 24, 81, -11, 112, 99, 40, 99, -41, 29, 104, -35, 109, -9, -88, -10, -58, -35, 34, -107, -18, 91, 58, 95, 92, -59, -87, -76, -92, -13, -119, -38, 15, -100, -80, -22, 120, 61, 110, -111, 29, 107, -2, -116, 124, 58, -114, -1, -75, 88, 80, Byte.MAX_VALUE, -125, 110, -77, 49, -52, -115, 96, -32, -58, -2, -18, -82, 115, 90, -38, -83, -99, -8, 57, -25, 83, 102, -13, -5, -41, -19, -54, -123, -31, 53, Byte.MAX_VALUE, -27, 67, 12, 65, -126, 112, -92, -60, 68, -24, -109, -43, 10, 24, 39, 23, 126, 33, -83, -103, -60, 42, 113, -5, -11, -41, -53, 14, 114, -76, 10, 32, 57, 89, -42, -52, -94, 9, -5, -102, -127, -109, 120, -94, 112, -63, -92, 125, -72, 27, -101, Byte.MAX_VALUE, 96, -32, 113, 58, -9, 74, -3, 28, -61, 93, 53, -13, 2, 30, 68, -60, -37, -59, 51, 108, -8, 112, 11, 68, -28, -15, Byte.MIN_VALUE, 25, 109, 60, 112, 42, 14, 85, -78, -117, 77, -11, 115, 74, 119, 111, -105, -78, 84, 0, -122, -54, 1, 25, 114, 74, 83, -27, 79, -85, -13, 69, 123, 30, 98, 43, 99, -62, -40, -125, 85, -18, -25, -91, -15, 99, -96, -31, -4, -45, -95, -116, 88, -14, -119, 74, -8, -71, -19, 80, 99, 109, -101, -20, -76, -37, 41, 4, 92, -107, 51, -38, -98, -20, 87, 67, 72, 52, -25, -70, -43, -96, -52, 54, 40, 27, -34, 52, -62, -41, -102, 101, -78, 75, -20, 94, 32, -106, 91, -75, -2, -54, -16, -74, -71, 93, 22, 71, 32, 69, -64, 39, -65, 98, -38, 57, 92, -93, -41, 9, -12, 90, 36, -100, -48, 24, -91, -62, 7, 92, -87, 0, -82, -37, -65, -90, -81, -124, 118, -109, 76, -106, 124, -67, -86, 65, -57, -26, -124, 54, -101, 85, -94, -64, -59, -101, -49, -92, -115, -23, 124, -69, 63, -114, -61, -115, -74, 55, -54, -105, 35, 86, -76, 121, 107, 30, 88, 58, 58, 86, 56, -73, 121, -12, -59, -43, -83, -105, -34, -30, 83, -11, 107, -117, 48, -39, -72, 43, 33, -58, 47, -61, -13, 94, 34, 79, 106, 118, 8, -68, -11, 112, -85, 94, 68, -13, -33, -26, -20, 102, 63, -118, -27, 81, -32, -52, -79, -114, 49, -102, -30, 26, 118, 42, 85, -26, 78, -3, 94, 17, -100, -32, -15, 60, 7, 73, -58, 34, -74, 47, -75, 81, -63, 82, -35, 99, 24, -86, 38, 75, -80, -14, -23, -9, -13, -99, -61, 66, -80, 21, 39, -17, -110, 0, 37, -68, 29, -114, -58, 117, 24, -42, -30, -77, -106, 69, -37, 112, -24, -123, 58, 106, -82, 28, -26, -95, -5, -76, -28, -96, 107, -98, -26, 74, -106, -20, -94, -112, -75, 43, -41, 3, -71, -90, 125, -26, -22, -53, 65, 95, -4, 9, 45, 91, -25, 25, -15, -107, Byte.MIN_VALUE, -75, -23, 3, 94, -94, 12, -80, -58, -3, -88, 67, -117, 92, -30, -45, -47, 15, 48, 10, -82, 106, -123, -91, 25, -54, 115, 116, 56, -32, 126, 23, 31, -30, 20, 95, -42, -7, 56, -62, 100, -125, 124, 83, 4, 12, -80, 63, -20, 50, 35, 97, 108, -54, -86, 87, 0, -18, 50, -46, 39, -33, -7, 63, 107, 66, -87, 61, 17, 1, -107, 56, 16, 105, -71, 76, 80, 99, -121, Byte.MIN_VALUE, -30, 12, 24, 90, 121, -66, 108, -104, -9, -109, -118, -118, -76, -77, 28, -104, -112, 96, 121, 85, -55, 81, 47, -44, -120, 24, 62, 61, 61, -100, -63, 26, -25, 99, 85, -114, 45, -77, 80, -42, -61, -73, -9, 38, -19, -50, -22, 55, 56, 40, 3, -121, 50, 29, 19, -47, -47, 3, 110, 36, -18, -61, -119, -20, 84, 111, -116, 102, 68, -10, 104, -39, 3, -73, 6, 26, 44, -70, 104, -41, -46, 5, 82, 47, 47, -76, 121, -56, 28, 126, 43, -97, -119, 42, 59, 94, -62, 42, -28, -61, 98, -125, -18, 109, 121, 40, 7, 103, 33, -44, 126, -117, -18, -34, 2, 27, 39, 120, 4, -56, -100, -112, -10, -100, -59, -64, -122, 41, -62, -71, 40, -107, -17, -36, -20, -60, -94, -8, -12, 126, 38, 27, -60, -21, -62, -38, 114, -6, 0, -113, -56, -19, -84, 116, 116, 71, -42, -56, 37, 83, -10, -1, 60, 96, 97, 67, -117, -116, -25, -39, -96, -6, -42, -114, -5, 101, -88, -59, -107, -59, 36, -39, 126, 39, -53, -109, 105, -124, 9, -71, -31, 23, 60, 86, 69, -35, -116, 24, -87, -36, 96, -43, -101, -9, 19, -67, -13, 29, 51, 47, 22, -64, 88, -24, -66, 86, 4, -86, -5, 21, -50, -29, -110, 38, -127, 126, 2, 62, -45, -71, 68, -45, -77, 75, 61, 28, 67, 5, -104, 119, -12, -61, 8, 74, -49, 1, -35, 50, -34, 95, -39, -23, 70, -123, 83, -115, 5, 85, 19, 100, -34, -110, -73, -73, 88, 96, -65, -84, -119, -18, 59, 102, -39, -40, 95, 19, -102, 5, -70, 108, 80, 86, 16, 43, -110, 4, -33, -127, -87, 77, 52, 90, -115, 42, -14, 28, -61, 56, 51, -66, 57, 32, 80, 50, -75, 106, -89, 59, -79, 104, 17, 75, -14, 72, -108, 75, -81, 78, -1, -3, -25, -81, 76, 5, -47, 98, 84, -81, 55, Byte.MAX_VALUE, 4, 85, 112, 18, -57, -49, 31, 83, -33, -68, -62, -3, 8, 36, -10, -111, 58, -90, 15, 41, -93, 64, -125, -69, -118, 57, -67, 14, -85, 115, -60, 99, 113, 10, -83, 6, 75, -71, 10, -121, 104, -44, 121, -103, -43, -126, 78, 64, 51, 103, 72, -86, 35, -8, 78, -50, -87, 119, -61, -58, -96, -3, -102, -16, 26, 124, 85, -58, -32, 48, -126, 14, -119, 57, 67, -84, -1, 8, 71, -119, -69, -47, 38, 82, 120, -65, 24, 36, 118, -84, -94, -115, 7, 13, -71, 113, -100, 9, 59, 28, 80, Byte.MIN_VALUE, 9, 21, 18, -92, 115, 85, -45, -70, 38, 49, -47, 82, 0, 20, 27, 115, -29, 53, 84, -106, -10, 99, -64, 6, -71, -21, 45, 53, 76, -24, 44, 103, -93, -2, Byte.MAX_VALUE, 9, 22, -70, -88, -46, -28, 111, 89, -92, 8, -54, -97, 18, 11, 106, 116, Byte.MAX_VALUE, -116, 24, 81, -37, -3, 86, 78, 39, 126, -76, 14, 13, -3, -8, 72, -100, -46, 77, 26, -46, -75, 49, 71, 8, 122, 93, -36, -118, -67, -116, -94, 101, 79, -66, 54, -86, -22, 1, 50, -87, 101, -34, 43, -124, 36, -62, 55, -82, -67, -95, 92, -45, -9, 42, 122, -100, 58, -42, -127, -66, -18, -104, -6, -111, -54, -62, 72, -111, -18, -104, -50, 57, 23, 111, -58, -45, -40, 25, 63, 75, 92, -17, 12, 38, 18, -53, 16, -126, -2, -108, 118, 57, -6, -38, -117, -74, 99, -51, 59, 78, -70, 41, 57, -120, -32, 7, -77, -69, -15, -115, 5, -13, 22, -59, 114, -115, -98, 97, 24, -100, 15, 5, 98, 49, -49, -45, 117, -88, 81, -44, 42, 13, 77, -85, -10, 97, -64, 77, 49, -93, -87, 31, 83, -107, 65, 103, 76, -75, -118, -33, 117, -27, 13, -41, -13, 60, -75, -6, -74, -115, 0, 48, 43, -83, -115, -83, 61, 58, 41, -100, -24, -45, -101, 98, -49, -5, -37, -70, 109, 74, 68, -58, 89, 65, -1, 47, 81, 17, 2, 68, 54, 37, -1, -103, -76, -30, 112, 94, 0, 3, -96, -37, 64, 124, -62, -16, 16, 62, -49, -93, -3, 88, 33, -72, -45, -117, 14, 68, -5, 64, 94, 44, 46, -99, -10, 62, 89, 99, 66, 107, 70, -34, 124, 14, 21, -99, -102, 33, -81, -121, -95, -115, -76, 71, -44, -49, -95, 24, -37, -119, 35, 24, -11, -112, 35, 125, -115, 126, -7, 67, 114, -62, -37, -58, 116, -64, -22, 73, 40, -15, 123, -101, -59, -35, 32, 39, 42, 125, 8, -52, 10, -90, 112, 103, -63, 11, 111, 124, -27, 11, 29, -123, 38, -88, 112, -125, -76, -84, 117, -126, 32, -41, -44, 26, -115, -112, 83, 83, 118, 57, 93, 82, -72, -59, -119, 88, 93, -82, -51, 62, -74, 27, -71, 6, 95, -36, 20, 72, 107, -10, -66, 28, 92, -114, -86, 56, -42, 86, 29, -113, -126, 70, 86, -106, -28, -71, 63, 76, -110, 95, -79, 107, -42, -47, -121, -17, -88, 6, 61, 103, Byte.MAX_VALUE, -112, -77, 52, -18, 67, 62, 104, -70, -74, -81, -82, 110, -2, 66, 67, 4, 14, -94, -71, 29, -115, -50, 104, -106, -7, -28, -62, -37, 48, -81, 87, -29, -43, 39, 59, -85, -18, 43, -70, 116, Byte.MAX_VALUE, -32, 121, -62, 119, 27, 37, -78, -84, 66, 65, -103, -87, -23, 39, 52, 25, -102, -59, -117, -77, -110, 9, -22, -107, -82, -111, 116, -111, 64, -113, -70, 113, 126, -58, 28, 3, 66, 88, -64, 116, -54, 85, 117, -34, -21, 14, -32, -86, -45, -21, -32, 92, -91, -121, -115, -33, -75, 71, -11, 27, -82, 5, 39, 79, -58, 60, -108, 52, -83, -39, 17, -45, -100, 38, -11, 101, 112, -74, 93, 102, -102, -84, -29, -77, -17, 102, 122, -52, 122, 24, -79, 38, 113, 126, -118, -43, 95, -11, -103, -112, 31, -69, -103, 18, -15, 83, 24, -114, -31, 49, -102, -6, 0, 84, Byte.MAX_VALUE, -119, -75, -94, 78, Byte.MAX_VALUE, -38, -1, -69, 9, 72, 88, 10, -6, 0, 80, 105, 124, 53, -24, -30, 67, -32, 9, -28, -69, 60, 71, -42, -40, 40, -2, Byte.MAX_VALUE, 35, -121, 34, -112, 28};
            return f30471o;
        }
    }

It should print to the log both the private key it found, and a cert I tried generating using the other values from the source (which has sadly already expired, when inspected via openssl x509 -in <filename> -noout -text). For reference, the modulus of the private key I found (via openssl rsa -in <filename> -noout -modulus|openssl md5) was 778f903e3db3bddb5cac4de94937ad4f.

If there are alternate values coming from somewhere they'd go into the SomethingProvider class - the code in the Android Auto app will only replace the default values if all three values (the string, seemingly containing a certificate, and two byte arrays) are provided. If none, one or two only are present, it just uses the default. I think this means there might be some values coming from somewhere for these. Might still just be easier to grab it from memory ;)

from aacs.

gamelaster avatar gamelaster commented on May 29, 2024

@thegnomewizard as @tomasz-grobelny said, it's no more possible to grab it from memory. It needs the combination.

About the final private key, it should have expiration date at least after 8 months after release of APK.

from aacs.

thegnomewizard avatar thegnomewizard commented on May 29, 2024

Oh, I was thinking in terms of maybe shimming the OpenSSL library on device (as I believe Android just natively calls out to it for SSL support), after all it seems like it must still exist in memory at some point (though as I mentioned I still need to pick up a functional, rooted phone).

Regarding the expiry date, I was curious about that - openssl isn't reporting an expiry date for the private key I found (nor the one already in the repo under android_auto.key. Did you try to capture the public key from memory? If so, what was the modulus?

from aacs.

thegnomewizard avatar thegnomewizard commented on May 29, 2024

Finally got a rooted Android device and confirmed the sensible looking key in RAM is 891b79109323149bf53c718de837e0de, different modulus to the private key recovered by running the code in the JAR. I believe this confirms the content from the interface that returns a string (with a certificate) and two binary arrays is being replaced at runtime with values from some kind of contentprovider. The code to do this (which also involves checks for debug keys, for example ((!str.equals("eng") && !str.equals("userdebug")) || (!str2.contains("dev-keys") && !str2.contains("test-keys")))) is pretty complicated though, I haven't yet deduced where it might be coming from manually.

from aacs.

thegnomewizard avatar thegnomewizard commented on May 29, 2024

Scratch that - I think I was just using a too-old APK before. Copied the APK out of my new Android phone and it had different public cert (expires in April 2023) and byte arrays (in the code above, what I called the SomethingProvider). Pasting these values in and running the above code has given me a valid private key that matches the public certificate (sharing the same modulus). I'll need to try it in the car.

from aacs.

thegnomewizard avatar thegnomewizard commented on May 29, 2024

Confirmed the cert and private key I have seemed to work with AAServer and my car (a Chevrolet).

The car had previously stopped just after authentication with no message at all, but it's at the same point others got SSL errors, so I suspect the car just ignores invalid messages.

from aacs.

gamelaster avatar gamelaster commented on May 29, 2024

Oh cool! How you did that @thegnomewizard?

from aacs.

thegnomewizard avatar thegnomewizard commented on May 29, 2024

So after I got an updated APK, I just ran the code I posted above (just taking out the bit at the end that was incorrect. Without that this code is pretty much what appears in the APK, just extracted, tweaked and renamed to be more readable):

    private void doTest() throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, CertificateException {
        AnotherProvider somethingProvider = new AnotherProvider();
        Charset useCharset = StandardCharsets.UTF_8;
        Cipher instance = Cipher.getInstance("AES/CBC/PKCS5Padding");
        String test = somethingProvider.getString();

        byte[] bArr = new byte[48];
        tweakBytes(somethingProvider.getString().getBytes(useCharset), bArr, somethingProvider.getArray1());
        tweakBytes("-----BEGIN CERTIFICATE-----\nMIIDiTCCAnGgAwIBAgIJAMFO56WkVE1CMA0GCSqGSIb3DQEBBQUAMFsxCzAJBgNV\nBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW\naWV3MR8wHQYDVQQKDBZHb29nbGUgQXV0b21vdGl2ZSBMaW5rMB4XDTE0MDYwNjE4\nMjgxOVoXDTQ0MDYwNTE4MjgxOVowWzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNh\nbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxHzAdBgNVBAoMFkdvb2ds\nZSBBdXRvbW90aXZlIExpbmswggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\nAQDUH+iIbwwVb74NdI5eBv/ACFmh4ml/NOW7gUVWdYX50n8uQQsHHLCNIhk5VV2H\nhanvAZ/XXHPuVAPadE2HpnNqePKF/RDo4eJo/+rOief8gBYq/Z+OQTZeLdNm+GoI\nHBrEjU4Ms8IdLuFW0jF8LlIRgekjLHpc7duUl3QpwBlmAWQK40T/SZjprlmhyqfJ\ng1rxFdnGbrSibmCsTmb3m6WZyZUyrcwmd7t6q3pHbMABO+o02asPG/YPj/SJo4+i\nfb5/Nk56f3hH9pBiPKQXJnVUdVLKMXSRgydDBsGSBol4C0JL77MNDrMR5jdafJ4j\nmWmsa2+mnzoAv9AxEL9T0LiNAgMBAAGjUDBOMB0GA1UdDgQWBBS5dqvv8DPQiwrM\nfgn8xKR91k7wgjAfBgNVHSMEGDAWgBS5dqvv8DPQiwrMfgn8xKR91k7wgjAMBgNV\nHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQDKcnBsrbB0Jbz2VGJKP2lwYB6P\ndCTCCpQu7dVp61UQOX+zWfd2hnNMnLs/r1xPO+eyN0vmw7sD05phaIhbXVauKWZi\n9WqWHTaR+9s6CTyBOc1Mye0DMj+4vHt+WLmf0lYjkYUVYvR1EImX8ktXzkVmOqn+\ne30siqlZ8pQpsOgegIKfJ+pNQM8c3eXVv3KFMUgjZW33SziZL8IMsLvSO+1LtH37\nKqbTEMP6XUwVuZopgGvaHU74eT/WSRGlL7vX4OL5/UXXP4qsGH2Zp7uQlErv4H9j\nkMs37UL1vGb4M8RM7Eyu9/RulepSmqZUF+3i+3eby8iGq/3OWk9wgJf7AXnx\n-----END CERTIFICATE-----\n".getBytes(useCharset), bArr, somethingProvider.getArray1());
        for (int i = 0; i < 7; i++) {
            tweakBytes(bArr, bArr, somethingProvider.getArray1());
        }
        byte[] bArr2 = new byte[32];
        System.arraycopy(bArr, 0, bArr2, 0, 32);
        instance.init(2, new SecretKeySpec(bArr2, "AES"), new IvParameterSpec(bArr, 32, 16));
        byte[] doFinal = instance.doFinal(somethingProvider.getArray2());
        int length = doFinal.length - 54;
        byte[] bArr3 = new byte[length];
        System.arraycopy(doFinal, 28, bArr3, 0, length);
        java.security.PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(Base64.decode(bArr3, 2)));
        String bobo = Base64.encodeToString(privateKey.getEncoded(), Base64.DEFAULT);
        Log.e("TEST", "privateKey.getEncoded()=" + bobo);
    }

    private static void tweakBytes(byte[] bArr, byte[] bArr2, byte[] bArr3) {
        for (int i = 0; i < bArr.length; i++) {
            for (int i2 = 0; i2 < 48; i2++) {
                int b = bArr2[i2] & 255;
                bArr2[i2] = (byte) (((((b >> 7) | (b + b)) + 33) ^ bArr3[i2 % bArr3.length]) ^ bArr[i]);
            }
        }
    }

From the updated APK, I got new values:

    final class AnotherProvider {
        public final String getString() {
            return "-----BEGIN CERTIFICATE-----\nMIIDLDCCAhQCAgN8MA0GCSqGSIb3DQEBCwUAMFsxCzAJBgNVBAYTAlVTMRMwEQYD\nVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MR8wHQYDVQQK\nDBZHb29nbGUgQXV0b21vdGl2ZSBMaW5rMB4XDTE0MDcwNDAwMDAwMFoXDTIzMDQy\nNTIxMDUyMlowXDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAU\nBgNVBAcMDU1vdW50YWluIFZpZXcxEzARBgNVBAoMCkNhclNlcnZpY2UxCzAJBgNV\nBAsMAjYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8YiJ201G6Nm6\nulscy1/W3VWJI2j0RUV8vKucvt71EnQbooUyJgNw96DbZ6HTlaryt3KDqLQ2MhWe\nxDyi9XjGCIzQuphpV9ywVAtF5aerdFKI+c5xwzaXDKtZ9BqcVDAVumAdQbFpeIGI\n8F6HyGYjf3lTge6X2kR3AGEXVnK7piqH+MHXPcm6NHebz/fqUffGmNhlnEvvg8dH\n4QE2qhQYMf1gSokj8RZiXqK/6COhTZ0x42UzDq2X5S5ysvYnEKIKePYsLPfKnGPo\ncY7NRGhL3cAgcBDclpGg//xLlJkx0vHe0y+oBCtLbY3HqwvyDGcVH/fhTuMDpcOH\n74Fc67CFcwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQDL6iWUMt+5zgqkNQY6ObX5\nCYzNB8FCd9MG7a6HmQT+nNPSz1DKgm0yQN5AFZyozm3IM7pk0pm8ui8rIkt/KTyc\nk0RfBvHbMJQ6ptFYjWIth+uo9TX4b4ZbtkcJdf5w9M6lkW5LT5vzfbAFIk16Kp7K\njUiktVoyI8y1968I1iscxIb/UdKyr4Ht6S/me6u5106/8qsGxpUnsQlsHMjbtepl\nezZcDQkoRgWTbfZMz6c32qybeNSCoAHsQTZ+1yiWLxiEjgt0XW8e/DV+BpS3espU\njZ+MPycNvm8rHBVX1A34ylpnw3C9tKbG2QiK6ggvuDFISPddYWqyixHom7W3C80y\n-----END CERTIFICATE-----\n";
        }


        /* renamed from: b */
        public final byte[] getArray2() {
            final byte[] f28562d = {123, 120, -82, 28, 122, -32, 80, 62, 102, 113, 40, 107, -31, 64, 125, -25, 63, 103, -18, 66, 15, -108, -32, -103, 17, 124, 10, 24, 16, -77, -75, Byte.MIN_VALUE, 124, 24, 108, 36, 37, -33, 19, -47, 73, 62, 0, 81, -114, -114, -101, Byte.MAX_VALUE, -37, 7, -27, 5, 26, 89, 79, -99, 22, -100, 15, -124, -126, -15, 25, -117, 121, 111, 93, -47, 21, 74, 64, -50, 122, -109, 80, 107, -88, -38, 101, -16, -120, -127, -95, 106, 111, 26, -123, -18, -33, -95, -55, -26, -75, 105, -76, -19, 43, -6, -111, 98, -25, 112, -18, 38, 53, 54, 22, -62, -37, -45, -125, -64, -123, 38, 92, 123, 65, 28, -62, -115, 3, -25, -91, 77, -95, -58, -74, 68, -64, 26, 50, 95, 114, -84, 55, -32, 56, -79, -70, -41, 27, -97, -108, -122, -37, 24, -47, -56, 28, -37, -12, -68, 114, -44, -93, 63, -60, -102, -27, -113, Byte.MAX_VALUE, -21, 67, -77, -122, 26, -77, -36, -107, 24, 14, 86, -110, 68, -85, 47, 55, 73, 103, 23, 27, 22, -85, -87, -45, 112, -4, 53, -50, 90, 77, -111, 119, -77, 20, -118, -85, Byte.MAX_VALUE, 90, 91, -91, 96, -77, 27, 45, 66, 9, 123, 49, Byte.MIN_VALUE, -56, -111, -94, -100, 100, -58, 101, -107, -41, -53, 38, -51, 5, -8, -14, 31, 14, 113, -36, -111, -42, -91, -37, 36, 118, 12, 51, -5, 36, -99, 22, -54, -81, -8, 92, -81, 88, -102, 53, -103, -22, 95, 50, 47, -86, 57, -4, -78, 117, 24, -17, -59, -4, 95, -47, -117, -8, 19, -18, 27, 53, -73, -126, -123, -57, 113, 15, 72, 103, 32, -30, 56, Byte.MIN_VALUE, 30, 108, -70, 63, -60, -124, -77, -102, -21, 94, -112, -19, 85, -73, 20, 82, -16, -58, 88, -65, -48, 116, 11, -15, -85, 119, 64, 122, -114, -101, -53, -122, -65, -10, -16, 40, -105, 117, 16, -59, -104, -84, 90, -83, 99, -34, -96, 101, 42, 90, -7, 79, 57, 0, -109, -35, -92, 52, 7, 13, -52, 97, 98, 121, 122, -9, -3, -97, -66, 46, 8, 93, 17, 115, 17, 120, -64, -118, -53, -98, -62, -96, -71, 34, 53, 38, 28, 43, 30, -24, -91, 101, 7, 36, 65, -92, -91, 80, -86, 72, 68, -55, 40, 72, 101, 99, -6, -114, 123, 112, -81, -22, -43, 122, 100, 103, 108, 82, 103, -85, -84, -40, -105, -80, -88, -85, 18, 92, 110, -77, -9, -57, -87, 7, -96, 81, 121, 108, 109, -51, -99, -98, 59, 46, -69, 116, 49, 118, 123, -126, -22, 21, 13, -42, 29, -74, 92, 47, -36, 49, 13, 74, -10, -40, -52, -85, 96, -18, -38, -43, -56, -71, 44, 32, -34, -110, -23, -8, -91, 49, 86, -7, -5, -43, 80, -80, 36, 80, -110, 43, -7, -14, -60, 73, -18, -81, 50, 125, -87, -24, -63, -115, -17, -110, 28, -9, -27, 123, -90, 79, -103, 76, 39, 72, 43, -119, 26, 50, 12, 61, 64, 115, -68, -40, -124, -5, -83, 23, 13, -120, 77, 113, -53, -4, 101, -91, 74, -69, -77, 99, -116, -36, 57, -77, -98, 98, -37, -65, 14, -36, 52, 18, 33, 112, 78, -33, -80, 72, -14, -39, 124, 86, -123, 5, -113, -75, -85, -34, -26, 112, 9, -82, 21, 68, 88, -12, -25, 81, 108, 38, 6, 105, 55, 40, 70, -9, 91, -123, 38, -123, 106, 0, -90, 75, 113, -89, -65, 68, 18, -74, 52, -99, -52, 52, 64, -50, -28, 2, 63, 10, -6, 0, 117, 87, -66, 41, 87, -58, 1, -118, 4, 79, 49, 123, -18, -92, 109, -87, -115, 25, -127, -76, 60, -94, 105, 62, -87, 6, -7, 80, -88, 83, -55, -74, -95, 16, 34, 119, -120, -53, -84, 62, 122, -85, 97, -50, -31, -14, 126, -75, -72, -97, 56, -78, -108, 44, 21, 94, -67, 76, 79, Byte.MAX_VALUE, 95, 69, 24, 97, -2, Byte.MAX_VALUE, -21, -103, -32, 39, -51, 34, 75, -67, 93, 123, 99, -126, -89, -39, -67, -60, 6, 37, 121, 14, -23, Byte.MIN_VALUE, 100, 28, -80, -102, 15, 90, -15, 34, -58, -41, 35, -52, -15, -11, -80, 111, -73, 19, -54, -22, 94, 91, 82, 3, 48, 0, 21, 43, -115, 64, 54, -89, -89, -76, 57, -97, -109, -118, 6, -124, 52, -59, -25, -28, -120, -126, -43, 111, 45, 84, -72, 16, 0, -109, 37, -109, 7, -64, 100, 7, 9, 95, 11, -60, -17, 81, -105, 45, 62, 105, 107, -82, -108, 99, -115, 70, 64, -23, 5, 2, -7, -22, 121, -8, Byte.MIN_VALUE, -41, 22, -58, 81, 48, -7, -17, 63, 122, 108, -50, -75, -43, -112, 76, 108, -111, 1, 80, 39, 95, -116, -92, 35, -86, -17, 60, -36, -3, 116, 78, -1, -40, -9, -70, 71, 85, 100, -65, 44, 30, 85, -122, Byte.MIN_VALUE, -50, -98, 126, -73, -117, 22, 30, 53, 114, -84, 32, 50, -83, -88, -9, 124, -18, -60, 6, -97, 96, 62, -83, 108, -51, -53, 85, -93, 117, -32, 91, 47, 97, 49, -70, 3, -12, 125, 23, -76, -126, -8, 119, 100, 62, 82, 20, 101, 28, -120, 15, -106, 66, -72, 14, 24, 48, -29, -119, 4, -43, -93, 89, 27, 122, -27, 3, -53, -61, -84, 12, -119, -79, -58, 15, 20, 70, -123, -85, 48, 102, 0, -9, -118, -5, 70, 21, -99, -89, -94, -67, -26, -98, 66, -14, -22, -116, -85, -122, 42, 38, -43, 58, 116, 96, 16, 121, 8, 75, -21, 76, 56, 124, -104, -8, 109, 44, -59, -6, 106, 78, 33, -63, -21, -77, 48, 107, 0, -95, 58, -40, -59, 13, -124, 116, 67, -20, -113, 84, -5, -2, -101, 91, 28, 0, -109, -101, 24, -99, 110, 100, 112, 112, -73, 84, 38, 54, 110, 36, -122, -18, 22, Byte.MAX_VALUE, 123, -118, -114, -122, 122, 39, 92, -91, -87, -115, 126, -100, -86, -58, -15, -47, 97, -95, 13, 65, -111, 113, -65, 28, 28, 111, 89, 13, 0, 6, -80, -108, -13, -53, 121, -15, Byte.MIN_VALUE, -38, -63, -45, 115, -32, 48, 77, -43, 45, 40, -4, -72, -46, 37, -92, 68, 90, -72, 8, 3, -49, 37, -49, -114, 110, -25, -25, 41, 13, 109, -67, -22, -126, 9, 126, -58, 27, 21, 77, -101, 77, -43, 39, 100, 98, 24, 94, 88, -108, 86, -80, 84, -65, 92, -124, 44, -7, 119, -36, 99, 113, 96, 75, -91, 59, 52, -4, -77, -62, 90, -106, -91, 89, 67, -59, 114, 8, -90, -72, 8, 69, -29, 74, 115, -35, 81, -63, 98, 67, -89, -57, 74, 2, 32, 25, 54, 89, 36, 17, 75, 57, 57, -26, 4, 65, 41, -58, -125, -1, -9, -76, 112, -41, 54, 69, -2, 56, -26, 17, -35, 46, 93, -76, 61, 110, 42, -5, -104, -63, -49, -60, 15, -70, 30, -107, 6, 14, 2, 80, 31, -70, 29, -70, 18, -19, 100, -40, 123, -45, 122, -20, -112, 94, 90, -117, -60, 97, Byte.MIN_VALUE, 59, -91, 97, -3, 65, -76, -78, 16, 83, -89, 30, -18, 112, -65, -26, -58, 94, -125, 68, -7, 40, -70, 68, -74, 77, -43, 79, 26, 54, -24, -80, -86, 43, 78, -78, 44, 50, -17, -14, -74, 116, -21, -74, -23, 6, 75, -32, -71, 118, 126, -8, -115, 40, 61, -77, 111, 100, 109, -50, 17, 3, -29, 57, -69, 89, -74, 60, 39, -29, 47, 28, -112, -62, -115, 26, -110, -87, -3, -125, 23, 65, 123, -112, -68, -66, -30, -16, -77, 83, -51, 120, -119, -124, -116, -104, -126, 89, -35, -39, -22, 99, -78, Byte.MAX_VALUE, 58, 84, -1, 113, 117, 22, 83, 7, -76, 52, 63, 46, -42, 3, 95, -76, -5, Byte.MIN_VALUE, -127, 35, -24, 24, -77, -14, 37, 27, 14, -45, 123, -3, 67, -101, 79, -112, 67, 7, -18, 99, -36, 30, -42, 56, -73, -65, 33, -90, 12, -34, -109, 38, -82, -16, 43, 64, 105, -64, -51, -18, -110, -117, -93, 33, 37, -126, 43, -122, -36, 17, -28, 3, 124, 87, -2, 68, -29, 37, 101, 46, 25, -70, 52, -61, -57, 19, -3, 45, -46, -100, 84, 50, 34, -32, -124, -90, 92, 96, 63, 97, 29, -47, 72, -44, 110, 104, -59, -6, -52, -58, Byte.MAX_VALUE, 39, 99, -121, -73, -60, 10, -32, 122, 114, -52, 124, 8, 36, -1, 71, -21, 6, 25, 45, 76, -80, -27, 125, -54, -83, -11, -26, -12, -97, 28, -26, -32, 2, 66, -38, 26, -87, -59, -70, 90, -21, 12, -47, 108, -105, -83, -39, 123, 27, 106, -97, -3, -99, 61, 78, -49, -62, -116, 23, 39, -37, -123, 114, 42, -83, -121, 0, -75, -74, 59, 100, -71, -91, -54, -88, -30, -37, 41, 114, 96, 0, 107, 34, -15, -84, 86, -98, -89, -22, 15, 41, -57, -124, 111, 97, -70, -20, -122, 118, 5, -118, 83, 97, -79, 126, -45, 59, -45, -87, -88, -107, -4, 82, -88, -31, 120, -27, -97, -13, 21, -112, 46, -75, 94, -65, -67, -42, -122, 100, 35, 6, -86, Byte.MIN_VALUE, 80, 55, 84, 17, -43, 30, -87, 103, 5, 89, -96, 117, 46, -62, -1, 108, -85, 31, 22, -20, -68, -66, 12, -103, 60, 26, -59, -113, -33, 20, -62, -37, -57, -55, 91, -4, 92, 27, -33, 97, -28, 83, -81, -75, 57, -122, 54, -89, 25, -22, 81, -3, 111, -22, -126, -117, -14, -5, 99, -22, 7, -98, 91, 83, 108, -56, -3, 96, -81, 86, 88, -58, 4, -119, 101, -74, 79, 102, -58, -24, 6, -23, 15, 53, -64, 86, -115, 57, -118, -62, -100, 4, 30, -14, 66, 110, -65, 5, 38, 46, 64, -36, 96, -61, -9, 13, 4, -40, -7, 28, -122, -107, -71, -17, 26, -92, 74, -9, -94, 13, -40, 50, -120, -106, 6, -49, 96, -113, -30, 51, -53, 93, -99, -11, -55, -61, -60, -8, -25, -20, 98, 95, -75, 25, 50, -102, -102, -51, 69, 71, 90, -83, -57, 90, 20, -16, -85, 9, -17, -19, -2, 14, 108, -33, -56, 108, 100, 97, 62, -59, 28, -91, -116, -85, -74, Byte.MAX_VALUE, -117, 34, -43, 104, 27, 8, 74, 75, -1, -93, -123, -15, 99, 48, -16, 106, -104, 10, 39, 88, 124};
            return f28562d;
        }

        /* renamed from: c */
        public final byte[] getArray1() {
            final byte[] f28561c = {90, -74, 78, -28, -115, 37, -102, -41, 120, 116, -123, 36, -42, 107, 69, -42, 113, 48, -124, 125, 116, 12, 65, 20, -56, 111, -25, 95, -85, -14, 21, 123, 54, -12, 89, 53, -27, -124, 31, 24, -13, -104, 96, 48, -78, -53, 12, -85, 18, -35, -31, 110, 20, 74, 108, -58, -70, -79, 69, 44, 6, -22, 85, -99, -1, -88, 107, -11, 57, -20, 23, -92, 114, -27, 26, 10, 7, -84, Byte.MAX_VALUE, -75, -125, 123, -85, 15, -32, -13, 39, -46, 40, -15, -117, 40, -2, -74, 112, -65, -35, -117, -79, -8, -94, -97, -105, 38, -80, 102, -91, 35, 21, 93, 49, 63, 31, 41, 65, 48, -85, 126, 64, 70, 116, 99, 38, 116, -92, 73, 49, -49, 6, 101, -80, 46, 4, 26, -78, 118, 116, -29, -19, -89, -56, 49, -54, 110, -33, -39, -53, -72, 70, 14, 54, -127, 34, -52, -10, 44, -50, -83, -92, -42, -103, 118, 97, 72, 100, 7, -127, -27, -30, -98, -42, -23, Byte.MIN_VALUE, -82, 95, -122, -84, -81, -6, -126, -65, 26, 35, -8, -77, -114, 58, 99, 19, 67, 110, 101, -95, -40, 100, 53, -115, 0, -83, -4, 100, 79, -41, 112, -33, -109, -86, 41, 58, -2, 3, -28, -98, 102, 57, -63, -127, -21, -114, -34, -58, 94, -41, -120, 20, 106, -57, -121, -116, -98, -69, -76, -69, -12, -108, 64, 69, -23, -1, 105, 82, 54, -53, -16, -117, 27, -27, -67, -15, -45, -46, 75, -66, 18, 56, 86};
            return f28561c;
        }
    }

Then simply ran the code in an otherwise blank Android application project and it printed the private key to the console. The public certificate in the above bit of code is the public cert, too.

from aacs.

gamelaster avatar gamelaster commented on May 29, 2024

@thegnomewizard wow great! It's interesting, because I was trying to do exactly the same, but my outputs were not good, always it was some garbage or something, I thought the JADX is decompiling it wrongly. Although, I was running the code on normal Java on PC, not inside Android, so maybe that is the trick. Thanks!

from aacs.

thegnomewizard avatar thegnomewizard commented on May 29, 2024

@gamelaster it'd be interesting to know what went wrong - I think the only really fiddly bit I noticed was in the helper function. It has a little bit of code that JADX decompiles wrong - it comes out as something like byte b = bArr2[i2] & 255; but as is that will cause the output to be nonsense, because it gets the sign wrong (the code is actually a standard Java trick for doing bitwise operations, int b = bArr2[i2] & 255;), after I fixed that I got the correct results.

from aacs.

tomasz-grobelny avatar tomasz-grobelny commented on May 29, 2024

@thegnomewizard, could you share how you got the values for AnotherProvider, in particular getArray1/getArray2? Did you do a memory dump or some further processing of decompiled APK? If memdump, what tools did you use (I am no Android expert so a high level instruction would be most welcome)?

from aacs.

thegnomewizard avatar thegnomewizard commented on May 29, 2024

@tomasz-grobelny it was all via the decompiled APK - I used jadx-gui to decompile (as much as it could) then looked up the function referenced above your comment from 8th October. From that example, "AnotherProvider" is the parameter passed in, iwa iwa, and the functions getString is mo16269a(), getArray1 is mo16270b() and getArray2 is mo16271c() (or the other way around, I forget). As such, you can search the entire APK via jadx-gui for iwa, mo16269a, mo16270b and mo16271b, all of which should return both the root iwa interface and any classes implementing them. One of the classes should contain the correct public certificate + binary arrays (and nothing else). It actually just pulls the byte arrays back from the class containing m23915f() though.

I was initially confused as I was using an older APK (I used a 'download APK' site and I suspect they cached an old one). Getting a real phone also meant it updated itself and the APK on the device had a valid cert and changed byte arrays to match.

from aacs.

kevinlieb avatar kevinlieb commented on May 29, 2024

I don't understand all the lower-level stuff here but appreciate the work! Please let me know when the new cert can be checked in to the codebase here, or share with me privately if you'd like me to test on my hardware (2021 Kia Niro and 2020 Harley)

from aacs.

X-Ryl669 avatar X-Ryl669 commented on May 29, 2024

A bit late to the party... I was wondering why this rabbit and tortoise game ?
If I understand correctly, the head unit isn't updated with new google certificate anyway once its delivered. I'm guessing that there is no certificate pinning in the unit so it's working with any device's certificate that's signed with Google's key.

So the certificate validation is only for the "device". This probably means that you can use any Google's certificate (even the one from 2022) for bootstrapping the communication. What is important is for the device to accept to use that certificate, so said differently, either adjust its date & time to make it believe it's in 2022 or write a X509TrustManager that completely ignore the expiration date of the certificate.

That way, you don't enter the course for finding the latest certificate from Google obfuscated source.

Am I missing something?

Here's and example TrustManager class that's ignoring the certificate validity. It should be used in the server's code (or its equivalent if not using Java).

from aacs.

gamelaster avatar gamelaster commented on May 29, 2024

This might work, but I actually find easier to dump the keys from APK than doing all of this :D

from aacs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.