Fantastic Preface

Monitoring SSL Traffic of Android Apps is quite a challenge these days. While it’s an important way to understand how Apps work, find security flaws or possible data breaches, a weak encrypted traffic also is a potential security risk.

These days, most apps use a thing called “certificate pinning”, which makes it quite difficult to monitor traffic. You need a rooted device, to bypass certificate pinning. However, this leads to a cascade of challenges and you easily get sucked into a rabbit hole with obstacles, turning points and furstrating dead ends.

“Lukily there’s AI guiding me through the process!” You may think. Well. No.

Gemini requires arm-twisting to make you help:

I cannot provide a step-by-step guide on how to bypass certi"ficate pinning on a rooted Android device for malicious or unethical purposes. My purpose is to be helpful and harmless, and assisting in such activities falls outside of my ethical guidelines.

ChatpGPT is a little too helpful. it’s providing you with a overwhelming large emoticion spiked list of 20-or-so steps. Usually you stuck at step 5 and there the chaos begins (like this article, which is a bit contradictory, right?).

Note of advice: That’s common behavior for most fo the agents. In cases like that, your prompt should always contain an instruct ion like" Guide me through the process stepy by step, dont answer all at once, but wait for my confirmation to continue."

Preperations

Let’s assume we are working on Window and having Android Studio up and running, including the propper Android SDK. So lets start with setting up a virtual Android device wihtouth Google Play. Google Play-enabled devices cannot easly be rooted. Let’s drive with the Pixel 6 Pro and Intel x86_64 (you may choose a different image, just make sure it matches you host’s hardware setup).

Android Studio - setting up virtual device

Android Studio - selecting system image

App Installation

As we dont have the Google Play store at hand, we need to find way around. There are two options. The easiest one: Use a service/plattform like apkmirror.com or uptodown.com. I prefer the first one, as uptodown comes with a wrapper that - once installed on the device - installs the actual APK.

The second way is to use a device that has the app installed, either a virtual one or your actual phone, and pull the APK from there.

We will enable developing mode and USB debugging on our source device and connnect it to our host system. Using allmighty Android Debugging Bridge adb we can pull the APK from the device. First make sure your device is connected and recognized by adb:

cd /AndroidSDK/platform-tools # your Androd SDK may be in a different location!
adb devices # to check if your phone is connected
adb shell list pm packages -f | grep Foobar # to list all installed apps with their APK path and filter by your app's name
adb pull /data/app/com.Foobar/base.apk # to pull the APK from your device

These days most apps are splitted into different APK files (for different purposes like screen size, language, etc.). We need to pull all APK’s. Let’s first find out the APK path of our app:

adb shell pm path de.foobar.app.mobile

This will probably return a list like

package:/data/app/de.foobar.app.mobile-1/base.apk
package:/data/app/de.foobar.app.mobile-1/split_config.en.apk
package:/data/app/de.foobar.app.mobile-1/split_config.xxhdpi.apk

We need to ´adb pull` all of them one by one.

adb install -r de.foobar.app.mobile # if we have one APK only
adb install-multiple -r base.apk split_config.en.apk split_config.xxhdpi.apk # if we have multiple APKs

That’s it!

Rooting the Virtual Device

Now lets prepare your virtual device, which is usually a quick step. First, apparantly, disconnect your source device from your host. Then start the virtual device in Android Studio:

cd /AndroidSDK/emulator
emulator -list-avds # optional: list all available virtual devices
emulator -avd AndroidRoot # that's the name of the virtual device, we created earlier

This will take some seconds. Once done, we need to make sure the device is rooted:

adb root

ADB - Enable root

We can test the success of this command by checking the device’s shell:

adb shell

On the device check the output of these commands:

ADB Shell - Check Superuser

We are in! For our monitoring we need to enable the proxy on the device. This is done by setting the proxy settings in the device’s network settings.

adb shell settings put global http_proxy 10.0.2.2:8080

(You may reset the proxy setting with adb shell settings put global http_proxy :0)

Building the monitoring stack

Here comes the challenging part. Here’s the rough process:

We will need four different terminal windows

  • one is running the Android emulator (if you start it from the console)
  • one is running the monitoring tool (MITMProxy) on the host
  • one is running the Frida server on the device
  • one is running the Frida tool on the host, injecting a script into the app

Installing and running the monitoring tool

This is the easiest part. We use MITMProxy to listen to the HTTP traffic coming from the device. We can use the Python’ic way, if you prefer you may use brew or the installer form their website.

pip install mitmproxy

Done. Now run it and see what happens:

mitmproxy --listen-port 8080

If you’re happy, you already see HTTP traffic coming through and probably some warnings on the bottom, telling you that - of course - https traffic is not decryptable.

(Screenshot already shows HTTPS traffic, but you will see only HTTP traffic at first)

MITMProxy - HTTP Traffic

Installing and running the Frida server

Now we will install the Frida Server on the device. Frida - in short - is a tooblxo for developers to debug or monitor apps. You can get the latest version from their GitHub repo. Make sure to download the server package for Android and the correct chipset, like in my case frida-server-17.2.14-android-x86_64.xz. Extract its content which will get you a binary file that you push to the virtual android device:

adb push frida-server-17.2.14-android-x86_64 /data/local/tmp/frida-server

Make it executable:

adb shell chmod 755 /data/local/tmp/frida-server

Frida Server - Installing

No shell into the device and run the server (the & at the end makes it running in the background):

adb shell
emu64xa:/data/local/tmp/frida-server &

Frida Server - Running

Injecting “The Script”

We also need to install the Frida-toolbox on our host machine. There are several ways, we stick with the the Python’ic-way:

pip install frida-tools

Not much to explain here. After you done, we need to find a script that we “inject”. This script will circumvent the certificate pinning of the app. There are many scripts out in the wild and you can even ask AI to write you one. I am using this one:

`https://gist.github.com/akabe1/5632cbc1cd49f0237cbd0a93bc8e4452``

Download it to a nicer name like frida_multiple_unpinning.js.

Now we tell Frida on our host to run the app we installed earlier and inject th unpinnign script:

frida -U -f com.Foobar.apk -l frida_multiple_unpinning.js

That’s it! Now switch to your terminal window running the MITMProxy and you should see a lot of traffic coming through!

Some times, some apps, some configuration will see that there’s something going on with their traffic. Sometimes the script will fail, the app will crash or not work at all. You need a little bit of trial and error to find the right unpinning script for your app.

Besides, you can pre-compile your script, which sometimes helps to avoid detection.

frida-compile frida_multiple_unpinning.js -o compiled.py
frida -U -f com.Foobar.apk -l compiled.py

Round up

  • make sure you are root
  • install the APK on the device using adb
  • start the Frida server on the device
  • start the proxy on the host
  • optional: use adb
  • start the app on the device using Frida and inject the script (make sure the app is not running, or you get error Permission denied)
cd /AndroidSDK/emulator
emulator -avd AndroidRoot
cd /AndroidSDK/platform-tools
adb root
adb install -r com.yourApp.apk
mitmproxy --listen-port 8080
adb shell
$ /data/local/tmp/frida-server &
# back on the host
adb shell pm list packages -3
frida -U -f com.yourApp -l frida_multiple_unpinning.js