Introduction
Dynamic analysis of Android applications has become an essential discipline for those who develop or audit their own mobile projects. Instrumenting an app in real time allows us to fully understand how it behaves, which code paths are involved in each operation, and how our defensive mechanisms respond to different scenarios. Among the tools that facilitate this process stand out Frida and Objection.
To explore these concepts in a controlled way, we will use the application Android SSL Pinning Demo by httptoolkit, an open-source project designed to experiment with various methods of certificate pinning. We will also make use of the scripts published by the same team to analyze the internal workings of TLS verification. This lab is ideal because it offers a secure environment in which it is possible to test instrumentation techniques without impacting third-party software.
In this type of analysis, there are two main routes to achieve application instrumentation: using a rooted device or modifying the APK to include the Frida Gadget, a process that is usually known as Gadget Patching.
The first approach is to use a rooted device. Installing Frida directly on the system allows hooking any process that is running without modifying the original APK. However, working with a rooted device implies accepting that many applications change their behavior when detecting these privileges, which can distort the results of the analysis. In addition, it is not a representative environment for the real user and requires dedicating an exclusive device to the lab due to the risks that root introduces in the security of the terminal itself.
The second option is Gadget Patching, which consists of modifying the lab application to include the Frida library inside it, so that it is the app itself that loads this component when it starts. Once rebuilt and signed, the application can be installed on a completely normal device, without additional privileges. When it runs, the Gadget waits for the analyst to connect from their computer with Frida tools, behaving exactly as if it were not modified. We will take this second path.
As prerequisites for deploying the project, we will have an Android device connected via the ADB debugging tool to our computer.
Installation of the tools
When using the tools that we are going to use, the programming language Python, we will create a new virtual environment for their installation.
$ python -m venv gadget_venv
$ . gadget_venv/bin/activate
We install the tools: frida, frida-tools and objection.
$ pip install frida frida-tools objection
We clone the repository containing the Frida scripts that we are going to use and download the Android SSL Pinning Demo sample application.
$ git clone https://github.com/httptoolkit/frida-interception-and-unpinning
$ wget https://github.com/httptoolkit/android-ssl-pinning-demo/releases/download/v1.6.1/pinning-demo.apk
Next, we need to install the necessary dependencies to be able to patch the application: the tools aapt, adb, jarsigner, apksigner, zipalign and apktool.
$ sudo apt install aapt adb default-jdk apksigner zipalign apktool
Next we will update the version of apktool being used, since the one available in the repositories is very old for unpacking and repacking new versions of Android applications.
$ wget https://raw.githubusercontent.com/iBotPeaches/Apktool/master/scripts/linux/apktool
$ chmod +x apktool
$ wget https://github.com/iBotPeaches/Apktool/releases/download/v2.12.1/apktool_2.12.1.jar
$ export PATH=$PWD:$PATH
Injection of the Frida Gadget into the application
Before being able to use any Objection command on an Android application, it is necessary to modify its APK and re-sign it so that it loads the frida-gadget.so file when it starts. In practice, the process of patching the APK is usually reduced to simply running the command objection patchapk. We will specify as a parameter -s the source file to patch. We also provide the architecture of the device’s processor where the application is going to be installed, in this case arm64-v8a. We have more configuration options in case the patching fails, which can happen in some cases.
$ objection patchapk -s pinning-demo.apk -a arm64-v8a
Using latest Github gadget version: 17.5.1
Remote FridaGadget version is v17.5.1, local is v0. Downloading...
Downloading arm64-v8a library to /home/r/.objection/android/arm64-v8a/libfrida-gadget.so.xz...
Patcher will be using Gadget version: 17.5.1
App already has android.permission.INTERNET
Target class not specified, searching for launchable activity instead...
Injecting loadLibrary call at line: 66
Copying Frida gadget to libs path...
Rebuilding the APK with the frida-gadget loaded...
Built new APK with injected loadLibrary and frida-gadget
Zipalign completed
Signed the new APK
If the process has been carried out correctly, the file .apk pinning-demo.objection.apk will have been generated. We will install it on the mobile device using adb.
$ adb install pinning-demo.objection.apk
Configuration of the Frida scripts
This script requires modifying its configuration from the file config.js. The scripts are located inside the folder frida-interception-and-unpinning. We will modify the variables CERT_PEM with the certificate in PEM format, PROXY_PORT with the port of the web proxy (port 8889), and PROXY_HOST with the localhost IP address. It is recommended to use a SOCKS proxy and the option PROXY_SUPPORTS_SOCKS5 in order to cover many more cases of TLS Pinning with native code interceptions.
// Local testing certificate for now
const CERT_PEM = `-----BEGIN CERTIFICATE-----
MIIFLjCCBB...
-----END CERTIFICATE-----`;
if (CERT_PEM.includes("Put your CA certificate data here")) {
throw new Error('No certificate was provided' +
'\n\n' +
'You need to set CERT_PEM in the Frida config script ' +
'to the contents of your CA certificate.'
);
}
// Default emulator address for now:
const PROXY_HOST = '192.168.0.2';
const PROXY_PORT = 8889;
...
const PROXY_SUPPORTS_SOCKS5 = true;
Execution of the application and instrumentation
After the configuration, we will run the application on the mobile device. The Frida framework will have been loaded if the application gets blocked on the launcher screen. Next, we will search with the application frida-ps for the process identifier of the application we have executed.
$ frida-ps -U | findstr SSL
27517 SSL Pinning Demo
We observe that the PID is 27517, so we run frida along with the scripts.
$ frida -U -l ./frida-interception-and-unpinning/config.js -l ./frida-interception-and-unpinning/native-connect-hook.js -l ./frida-interception-and-unpinning/native-tls-hook.js -l ./frida-interception-and-unpinning/android/android-certificate-unpinning.js -l ./frida-interception-and-unpinning/android/android-certificate-unpinning-fallback.js -l ./frida-interception-and-unpinning/android/android-disable-root-detection.js -l ./frida-interception-and-unpinning/android/android-proxy-override.js -l ./frida-interception-and-unpinning/android/android-system-certificate-injection.js -p 27517
____
/ _ | Frida 17.5.1 - A world-class dynamic instrumentation toolkit
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about 'object'
. . . . exit/quit -> Exit
. . . .
. . . . More info at https://frida.re/docs/home/
. . . .
Attaching...
== Redirecting all TCP connections ==
== Hooked native TLS lib libssl.so ==
== Certificate unpinning completed ==
== Unpinning fallback auto-patcher installed ==
The application will be deployed and it will be possible to monitor all network connections with a proxy, in case the application fails due to SSL and TLS Pinning techniques.
Conclusion
In short, the combined use of Frida, Objection and techniques such as Gadget Patching offers a powerful and realistic dynamic analysis environment to study our own Android applications.