This article expands on the things you can achieve with the frida framework. It focuses on the usage of frida-gadget to bypass SSL Pinning controls on Android applications. Do note that this method requires tampering of the application, which means that it also requires re-signing the app. Also note that this approach should work on both rooted and non-rooted devices.
if code in yourInterests:
click(here)
elif video in yourInterests:
click(here)
else:
keepReading()
def keepReading():
In a previous post, we saw how to use the frida framework to bypass SSL pinning on a an Android mobile application in order to intercept the traffic between the application and the server. This approach, however, requires you to push and run the frida-server into de device.
Here, we will see how to use a different approach: by reverse engineering the application, injecting a library and then re-building it, we can embed the frida-gadget within the application, so that the next time the app is loaded, it will wait to establish a connection with the frida client on our workstation.
What is the frida-gadget?
Unlike the frida-server (which you have to run on the device), the frida-gadget is part of the frida framework and comes as a library (.so) that you can include and call in your code at your will.
This is very helpful if you have limited access/control over the device (for instance on a non-rooted device), you can reverse engineer and tamper the application to execute the frida functionality when the main activity is launched, which is what we are about to do.
Let’s get to it…
Using this approach requires a series of steps that you have you follow in a specific order. Overall, the process goes like this:
- Find device architecture.
- Get proxy’s certificate (& install it on device).
- Reverse application with apktool.
- Inject frida-gadget.
- Inject smali hook.
- Increase app version.
- Re-build application with apktool.
- Zipalign the resulting apk.
- Sign the apk with apksigner.
- Install the tampered app.
- Tweak the frida script.
- Run the frida client.
- Intercept and enjoy.
1. Finding device architecture.
First thing we need to do is to find what is the architecture of the device we are dealing with. In this case, we will be using a Genymotion virtual device running an Android 6.0 instance, we will need the Android Debug Bridge (ADB) to communicate between the device and workstation.
Let’s fire up the virtual emulator and use ADB to find out what architecture the device is, the next command starts ADB and lists the connected devices:
./adb devices
List of devices attached
192.168.56.101:5555 device
Then we use getprop to pull the information about the CPU’s architecture:
./adb shell getprop ro.product.cpu.abi
x86
2. Getting the proxy’s certificate.
Next thing we need to do is to get the certificate of the proxy we will be using for interception. In this case we will be using Burpsuite as proxy:
Now, go to a browser and get the certificate easily by navigating to the proxy’s ip:port (192.168.0.9:8080 in this case). Here you need to go to the top right corner and click the CA Certificate link.
Once downloaded, install the certificate in the device (push it into the sdcard and go to Settings -> Security -> Install from sdcard). Also, keep the certificate at hand for future use:
3. Reverse engineering the application.
Mobile applications for Android devices come in the apk format. Our target, in this case, is a very simple application that implements SSL pinning for the securitygrind.com domain and the pinning code looks like the following:
Once the application is compiled, an apk file will be generated. It is that file (securitygrind.apk)that we will be using from now on. We now proceed to reverse engineer the app with apktool:
apktool d securitygrind.apk -f
You shall see something like the below.
Also, a new folder with the name on the file and containing the reversed code will be created (in this case securitygrind).
4. Injecting frida-gadget.
In the first step, we found that the device’s architecture is x86, we need this information to find the right frida-gadget here. If we search for “frida-gadget” we will see a few on them, look for the one appropriate for your device’s arch.
In this case, we will be using frida-gadget-12.2.26-android-x86.so.xz, after downloading it, we need to decompress with unxz.
unxz frida-gadget-12.2.26-android-x86.so.xz
After this, you will be ready to inject the library. To do this, copy the frida-gadget library into the folder containing the reversed application, put it into the lib folder (if it doesn’t exists, create it and create an arch folder within as well):
mkdir securitygrind/lib/
mkdir securitygrind/lib/x86
Now, copy the frida-gadget library into the newly created folders:
cp frida-gadget-12.2.26-android-x86.so /securitygrind/lib/x86/libfrida-gadget.so
5. Injecting smali hook.
Now, we need to find the application’s starting point, for this, we can inspect the AndroidManifest.xml file created by the reversing process. On this file, first look for the application tag, within it, look for the activity that has an intent-filter with the MAIN action and find it’s name:
As we can see, in our case , the activitie’s name is LoginActivity, which means that, within the smali directory there must be a file with this name and the smali extension (LoginActivity.smali), we can find it with the next command:
find . -name 'LoginActivity.smali'
We now open the smali file and look for the constructor, it is here where we need to add the smali hook that will invoke the frida-gadget library:
To inject the hook, first increase the locals by one and add the next two lines and save the file:
.locals 3
const-string v2, "frida-gadget"
invoke-static {v2}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
6. Increase app version.
We also need to increase the application version, otherwise, you might get an error when installing, saying that that the app version is incorrect. To do this, we edit the apktool.yml file (you can also set the versionCode property on the AndroidManifest.xml file, within the manifest tag).
In this case, we will edit the apktool.yml, the version code (versionCode) is at the end of the file.
We increase the application version by 1:
7. Re-building application.
Now that we have included the frida-gadget, tampered the application to load the library as one of the first thing the app does and increased the app version, we are ready to re-build the application.
To do this, we use apktool again:
apktool b securitygrind
You will notice the dist folder has been created within the target folder and, in this folder, you will find the re-builded app.
8. zipaligning the app.
Aligning the re-builded apk optimizes the application and it’s space usage, to do so, we use zipalign, as shown below:
ziplign -p 4 securitygrind.apk securitygrind-aligned.apk
9. Signing the app.
Once aligned, we proceed to sign the application, otherwise, we won’t be able to re-install the app. To do this, we first need a keystore, if you don’t have one already, you can create one with the following command:
keytool -genkey -alias keystore -keystore keyStore.pfx -storetype PKCS12 -keyalg RSA -validity 365 -keysize 2048
With our keystore at hand, we now use apksigner to digitally sign the application with our newly created keystore.
apksigner sign --ks keyStore.pfx securitygrind/dist/securitygrind-aligned.apk
10. Install the tampered app.
We now install the the tampered application, if the original application is installed, uninstall it and install the tampered one:
./adb install /opt/gadget-injector/securitygrind/dist/securitygrind-aligned-signed.apk
If you run the application at this point, you will see noting but a white screen, which means that the tampering worked fine and that frida is awaiting a connection:
Close the application for now and, within the device, go to Settings -> Wi-Fi -> WiredSSID (long press) -> Modify Network -> Proxy -> Manual: here you will configure the device to use Burpsuite as proxy:
11. Tweak the frida script.
Scripts in frida contains JavaScript code that translates into Java code for overriding a specific behavior in the target process or application. In this case, we will be overriding the init method of the SSL Context.
There is already a script for bypassing SSL pinning, which works by re-pinning the SSL Context with our proxy’s certificate, you can find it here. However, this script reads the certificate to be re-pinned from the internal storage of the device, this can be a problem if we are working with a non-rooted device.
Instead, we will tweak the frida script a little bit to hard code our proxy’s certificate on it (so that we do not have to read it from somewhere else). But, the first thing we need to do is to have the proxy certificate in a format suitable for hardcoding into the frida script. A PEM format will work just fine, let’s use openssl to convert the proxy’s cert to PEM format:
openssl x509 -inform der -in cacert.der -out proxy-cert.pem
Then, going back into the frida script, we need to add the String and ByteArrayInputStream object references:
var String = Java.use("java.lang.String");
var ByteArrayInputStream = Java.use("java.io.ByteArrayInputStream");
Now, we to load our PEM certificate into a String variable:
var cert = String.$new("-----BEGIN CERTIFICATE-----\n"
+ "MIIDyTCCArGgAwIBAgIEVA06ODANBgkqhkiG9w0BAQsFADCBijEUMBIGA1UEBhML\n"
...snipped...
After this, we create a byteArrayInputStream from the bytes of our previously define String (cert). Generated a certificate based on that input stream and finally close it.
var byteArrayInputStream = ByteArrayInputStream.$new(cert.getBytes());
var ca = cf.generateCertificate(byteArrayInputStream);
byteArrayInputStream.close();
Here is an example of the tweaked frida script.
12. Running frida client.
We are ready to bypass SSL pinning for this application, double check that Burpsuite is running and that the device is setup to use it as proxy. Using the modified frida script, run the next command (but run the application first, which will only show a white screen; awaiting for connection):
frida -U gadget -l frida-sslpinning.js
You will notice that frida has ran correctly and that it is “waiting for the app to invoke SSLContext.init()…“, that is to say, that frida is waiting until the applications tries to establish an SSL connection with the server. In our case, that happens when the user hits the “Sign or Register” button.
After we enter the credentials on the application and hit the button, we can see frida injected our TrustManager (with our proxy’s certificate):
13. Intercept and enjoy.
And, if we check our proxy, we sill see that traffic was intercepted and decrypted, go to Burpsuite and check:
Gadget Injector
I have created a small python script that automates part of the process described above. Find more on the GitHub repository here or by clicking the image below.
Also, find the next video showcasing how the tool works:
Conclusion
Securing the communication between the mobile client and the server is of paramount importance. As a pentester you are often required to bypass security controls meant to protect the application. The process describe above does not mean that the application is vulnerable, it only means that the attacker have certain level of control over the device and/or the user was allows installations from unknown sources.
Great work tbh :). I have a single question. Let say within the same environment you created, there is another app that uses SSL pinning (let’s call it app A). is it possible for Frida gadget in your repacked securitygrind.apk to intercept app (A) pinning and bypass it?
Hi Abdulla,
Thanks for your message. I do not think that’s possible, apps are separated from one another via sandboxing, which isolates them and prevents one app to access other app’s resources. Since we have injected the gadget into a specific application, traffic interception will be possible only for that application and that instance of the gadget won’t be able to intercept other application’s traffic.
Regards,
Cristian
Hi, im having trouble when using the automated too, it says android manifest not found aborting.. any help?
Hi Mato,
This tool uses apktool to extract the application’s sources in order to edit a few of them to inject the frida-gadget and them re-compile the application. From what you say, it looks like the AndroidManifest.xml file was not found during the execution of the tool, so, one of the first things you can try is to independently execute apktool on the target apk, this in order to understand if the Android Manifest is correctly extracted and decoded during apktool’s execution (the error seems to point at apktool not able to execute correctly).
Regards,
Cristian
Hi mate,
Our APK will not work in tampered environment (i.e. if APK recompiled with another sign ) so if we inject Frida injector and recompiled, it will bypass our tampered environment..
Hello,
I’m not sure I follow, what do you mean the APK won’t work on a tampered environment? If you tamper the application (by injecting the gadget), you certainly need your own signing key to re-sign the resulting application. Are you receiving any kind of error message?
Regards,
Cristian
Would you mind to share the same APK for the learning purpose?
Hello,
I think it is in the same Github repo as the tool, here you go: https://github.com/securitygrind/gadget-injector/blob/master/securitygrind.apk.zip
Thanks,
Cristian
Have you ever thought about adding a little bit more than just your articles? I mean, what you say is valuable and everything. But imagine if you added some great images or videos to give your posts more, “pop”! Your content is excellent but with pics and video clips, this site could definitely be one of the greatest in its field. Terrific blog!|
Hello Mauro,
Thanks for the comment! Not sure what you mean though, most of the posts in this blog have either images or videos on it, even this post you are commenting on has both images and videos related to the topic at hand. What sort of pics or video clips do you think will make the blog better?
Thanks,
Cristian
My partner and I stumbled over here by a different web page and thought I may as well check things out. I like what I see so i am just following you. Look forward to looking over your web page again.|
Excellent post. I will be experiencing many of these issues as well..
however great topic. I need to spend a while learning
Hello dears! I passed by here by chance, and believe me: I’m not even a programmer, I just started translating from English to my native language, and in just a few minutes I came to understand what I never had the opportunity to study! So let me congratulate the creator of this excellent content! His language is very objective and his multimedia is perfect! My respect and admiration for him for his clarity in making himself understood!
Greetings from Peru.