Last year I published a blog post about bypassing certificate pinning using a tool called Objection.

https://blog.jamie.holdings/2018/09/05/bypass-certificate-pinning-on-android/

Since then I have encountered Android research opportunities with more complex certificate pinning methods not covered by Objection. So I had to learn more about how this worked to figure it all out.

Meet Frida

Under-the-hood Objection is actually using a tool called Frida.

https://www.frida.re/

This is a framework for various platforms allowing code injection. This allows you to do all sorts of fun activities, but the main focus we're interested in is it's ability to override the return value of any function within an Android application.

What does this mean for us? Well, if we can override the return result of any Android function we can hopefully find some method called "bool IsSSLValid()" (or something), and force it to always return true. I have my own Frida script with a selection of common SSL pinning technique overrides you can use for yourself. But first, we need to get Frida setup.

Setup Frida on your machine following the official documentation:

https://www.frida.re/docs/installation/

Now you'll want to install frida-server onto your Android device. Follow these instructions to get things setup:

https://www.frida.re/docs/android/

Once you're setup and frida-server is running on your Android device, you can write JavaScript files to build your injections.

I have a file called 'pinning.js' that is loosely based on some of the work in Objection, but with a few adjustments and some additional SSL pinning bypasses.

https://gist.github.com/cubehouse/56797147b5cb22768b500f25d3888a22

Download my pinning.js script to your machine and run it using the following command:

frida -U -l pinning.js -f [APP_ID] --no-pause

Note, replace [APP_ID] with the app you wish to inject into.

This script will boot the app, start the injections, then let the app complete it's bootup. This ensures that our injections are setup as soon as possible before the app starts, so we don't need to start it and make a mad dash in Objection to get the pinning bypass working before any requests are made.

You should see something like this:

My pinning script supports SSL pinning bypassing for Appcelerator, TrustManagerImpl, trustkit, okhttp3, and Sensepost Trustmanager.

Adding Additional SSL Pinning Bypasses

To add further SSL pinning bypasses you'll want to analyse the internals of the Android app in question. Use a decompiler tool such as Jadx to load your target Android app's APK and browse the code.

https://github.com/skylot/jadx

Here I have an Android app where I have found the SSL pinning in okhttp3. This function is called CertificatePinner::check.

Looking at the code, we can see that the function has no return value, but instead throws an Exception if the certificate is invalid. So all we need to do here is replace the function logic so that it doesn't do anything and and invalid certificates will stop throwing exceptions.

To do this, we find the class name and override the method:

var CertificatePinner = Java.use('okhttp3.CertificatePinner');
CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function (str) {
    console.log('! Intercepted okhttp3: ' + str);
    return;
};

First we get the class itself (var CertificatePinner), then we overide the 'check' function. We need to tell Frida the arguments of the function we're overriding so it can find the correct signature. In this case, the function takes a Java String and List.

Once we're in, we can call return, skipping out the real application logic!