SSL unpining frida + Fiddler/Burp

1. Install Fiddler Everywhere + CERT

After that, check the option "Capture HTTPS traffic", and install the certificate.

Next, click on "Advanced Settings", and export the certificate.

Now, we need to push the certificate into the android emulator and install it. See more details below.

We need to install it inside the SYSTEM trusted certificates.

For that, convert first the .crt to .pem format.

openssl x509 -inform der -in FiddlerRootCertificate.crt -out certificate.pem
openssl x509 -inform PEM -subject_hash_old -in certificate.pem
e5c3944b
-----BEGIN CERTIFICATE-----
MIIDozCCAougAwIBAgIQAKPzRj150AoV9QaH05oFgzANBgkqhkiG9w0BAQsFADBq
MSswKQYDVQQLDCJDcmVhdGVkIGJ5IGh0dHA6Ly93d3cuZmlkZGxlcjIuY29tMRgw
FgYDVQQKDA9ET19OT1RfVFJVU1RfQkMxITAfBgNVBAMMGERPX05PVF9UUlVTVF9G
aWRkbGVyUm9vdDAeFw0yMTA2MTUwMDAwMDBaFw0zMTA2MjIxODA0MTBaMGoxKzAp
(...)

mv certificate.pem e5c3944b.0

-- Import it--
.\adb.exe connect localhost:21503
.\adb.exe remount
.\adb.exe push e5c3944b.0 /system/etc/security/cacerts/

At this step, we have the certificate in the USER and SYSTEM trusted credentials.

2. Configure the Proxy

On the Fiddle settings window, copy the listener port and mark the option "Allows remote computers connect".

On the android emulator, configure the proxy.

3. Frida unpinning

Copy the Fiddler certificate to the same folder where frida server is installed.

.\adb.exe connect localhost:21503
.\adb.exe push 'FiddlerRootCertificate.crt' /data/local/temp

.\adb.exe shell
G011A:/data/local/temp # ls
FiddlerRootCertificate.crt  frida-server-14.2.18-android-x86
mv FiddlerRootCertificate.crt cert-der.crt

After that, download the SSL unpining from Frida code repository.

We need to change the path where we copied it into the Fiddler certificate (line 25 below).

/data/local/temp/cert-der.crt
/* 
   Android SSL Re-pinning frida script v0.2 030417-pier
$ adb push burpca-cert-der.crt /data/local/tmp/cert-der.crt
   $ frida -U -f it.app.mobile -l frida-android-repinning.js --no-pause
https://techblog.mediaservice.net/2017/07/universal-android-ssl-pinning-bypass-with-frida/
   
   UPDATE 20191605: Fixed undeclared var. Thanks to @oleavr and @ehsanpc9999 !
*/
setTimeout(function(){
    Java.perform(function (){
     console.log("");
     console.log("[.] Cert Pinning Bypass/Re-Pinning");
var CertificateFactory = Java.use("java.security.cert.CertificateFactory");
     var FileInputStream = Java.use("java.io.FileInputStream");
     var BufferedInputStream = Java.use("java.io.BufferedInputStream");
     var X509Certificate = Java.use("java.security.cert.X509Certificate");
     var KeyStore = Java.use("java.security.KeyStore");
     var TrustManagerFactory = Java.use("javax.net.ssl.TrustManagerFactory");
     var SSLContext = Java.use("javax.net.ssl.SSLContext");
// Load CAs from an InputStream
     console.log("[+] Loading our CA...")
     var cf = CertificateFactory.getInstance("X.509");
     
     try {
      var fileInputStream = FileInputStream.$new("/data/local/temp/cert-der.crt");
     }
     catch(err) {
      console.log("[o] " + err);
     }
     
     var bufferedInputStream = BufferedInputStream.$new(fileInputStream);
    var ca = cf.generateCertificate(bufferedInputStream);
     bufferedInputStream.close();
var certInfo = Java.cast(ca, X509Certificate);
     console.log("[o] Our CA Info: " + certInfo.getSubjectDN());
// Create a KeyStore containing our trusted CAs
     console.log("[+] Creating a KeyStore for our CA...");
     var keyStoreType = KeyStore.getDefaultType();
     var keyStore = KeyStore.getInstance(keyStoreType);
     keyStore.load(null, null);
     keyStore.setCertificateEntry("ca", ca);
     
     // Create a TrustManager that trusts the CAs in our KeyStore
     console.log("[+] Creating a TrustManager that trusts the CA in our KeyStore...");
     var tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
     var tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
     tmf.init(keyStore);
     console.log("[+] Our TrustManager is ready...");
console.log("[+] Hijacking SSLContext methods now...")
     console.log("[-] Waiting for the app to invoke SSLContext.init()...")
SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").implementation = function(a,b,c) {
      console.log("[o] App invoked javax.net.ssl.SSLContext.init...");
      SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").call(this, a, tmf.getTrustManagers(), c);
      console.log("[+] SSLContext initialized with our custom TrustManager!");
     }
    });
},0);

After that, it's time to run the application.

--run frida server--
.\adb.exe shell '/data/local/temp/frida-server-14.2.18-android-x86 &'

--execute ssl unpinning--
frida.exe -U -f 'com.xx.xxx.xxxx' -l .\frida_ssl.js --no-pause

and ... we got it 😎

The same approach can be used with burpsuite, just by changing the certificate.

Resources

Last updated