Recently, a client asked if I could document the network behavior of a suite of mobile applications running on both Android and iOS. I thought at first that this would be straightforward.
The bad news? It was anything but. The good news? I discovered Frida, which let me tackle the problem in a whole other light.
The Black Boxes Are Getting More Opaque
In the good ol’ days of the Web, it was pretty easy to proxy a Web browser through a web debugging proxy like Fiddler or Burp Suite and capture its traffic. And that still works for many situations. However, there are many cases where this either falls short or is impossible.
A major issue is tracing mobile application behavior. To decrypt a mobile app’s encrypted web traffic over HTTPS, you have to get the app you want to trace to sign requests using a security certificate generated by your debugging proxy. On modern devices, this usually means (for Android) rooting your device with something like Magisk or (for iPhone) jailbreaking with an app such as unc0ver.
Even then, however, you still may not be able to get a specific app to use your user certificate. Many apps use a technique known as certificate pinning. As explained by Ray Wenderlich, pinning associates a host with its certificate or public key, which is bundled with the app at compile time. If an app is using pinning, it’ll reject any attempts at using a user certificate.
And that’s not the end of your woes. What if the app you want to trace isn’t even using HTTP/2.0 for all of its communications? More and more apps are adapting HTTP/3, which doesn’t even use TCP as its transport layer — all messages are sent via the UDP-based protocol QUIC. And some apps use other protocols for specialized tasks; for example, Instagram leverages MQTT for real-time notifications.
What is Frida?
Enter Frida. Frida is, in the words of its developer, “GreaseMonkey for native applications.” It provides a framework for hooking native application function and object method calls on a large variety of platforms — including Android and iOS.
And that’s not all. You can even alter return results and change a program’s behavior! As a matter of fact, there’s Frida code that can even bypass SSL pinning for most Android apps.
To hook calls on mobile applications on Android and iOS, you run a Frida server on the device — a lightweight server that implements Frida core and accepts injection commands over a TCP port.
Finally, the Frida tools, written in Python, let you send injection commands to the Frida server. You can use either the Python command-line utilities shipped with Frida or use the Frida library for Python to write your own injection script. (I’ll talk about why you’d want to do that in a subsequent article.)
Getting Set Up for Frida
Getting started with Frida on a mobile device can take some time due to the need to have a rooted or jailbroken device. Rooting and jailbreaking are themselves immense topics that I won’t cover here. For Android, I recommend obtaining a Google Pixel 3 and following the GadgetHacks.com guide to rooting your Android device with Magisk.
Once you have your device rooted, you can use the Magisk program to download and run a number of utilities that require superuser access to run. One of those is the program MagiskFrida, which runs Frida server on the device whenever it boots. MagiskFrida is also synced with the Frida artifact repository and automatically keeps your Frida server at the latest version.
On iPhone, it’s just as easy: After jailbreaking with unc0ver, you can use the “jailbroken app store” app Cydia to install Frida server.
Verifying Your Frida Setup
Once Frida is running, download the Frida tools to your desktop or laptop and plug in your device. You’ll know everything is working if the following command succeeds:
frida-ps will list all processes and their processed IDs running on the device:
The -U signals to frida-ps to connect to Frida server over USB. if you don’t specify it, frida-ps will list the processes on your local computer instead. (Yes, you can trace those too!)
Running Your First Trace Script
To give you a taste of what’s possible, let’s run the file Android TCP Trace, which will give us a printout of every TCP socket connection that an app makes. To run this script directly from CodeShare, run:
frida -U --codeshare mame82/android-tcp-trace -f com.android.chrome --no-pause
Note that, compared to what’s on Frida CodeShare, I added a couple of arguments here. The -U argument, again, tells Frida to send commands to Frida server over a USB connection. The –no-pause argument doesn’t stop script processing after Frida’s attached and injected itself into the process.
Once you trust the project, you should start to see a printout of all socket connections, their unique IDs, they type, the port they’re using, and the host to which they’re connected.
The One Issue with Frida for Tracing
From here, you can use other scripts on the Internet to trace a large number of standard Java library and Objective-C calls — including network calls. (Check out dweinstein’s awesome-frida for a significant compilation of such resources.)
However, not everything you want to trace may be using standard API library functions and classes. Many larger app makers, for example, roll their own network stacks for better control and performance. I’ll talk in subsequent articles about how you can use the utility
That aside, Frida is a powerful tool that changes the game when it comes to application activity and network tracing. In my next article, I’ll dive into how to find relevant functions and method calls and generate your first Frida script.