Hello! In this post, we’ll prepare a mobile application for pentesting. These operations will be divided into two parts: bypassing security mechanisms (Frida detection, root detection, etc.) and intercepting the app’s traffic via proxy.
First, we install the application on our device and activate the Shamiko module via Magisk in case the app performs root detection. (see: https://www.technopat.net/sosyal/konu/shamiko-ile-root-gizleme.2159998/)
Magisk Deny List
Then, we connect to the device via adb, start the frida-server, and launch the app. The purpose is to see whether the app detects Frida or debugging.
adb shell
However, the app stays on a black screen and closes shortly after, indicating that it detects Frida or debugging. At this stage, we use Jadx GUI, a tool for reverse engineering apk files, to inspect the source code.
String search with Jadx GUI
We open our apk file in Jadx GUI, search for “frida” in the search bar, and encounter classes t5.b and t5.c that we need to analyze.
t5.b.n method
t5.c.a method
After analyzing the classes, we determine that the methods t5.b.n and t5.c.a perform Frida string and port detection. Now it’s time to write a Frida script to hook these methods (i.e., replace the execution with our own custom code). LLMs (like ChatGPT, DeepSeek, etc.) can be incredibly useful here if you’ve correctly identified the code snippet.
frida script
This script contains 3 separate try/catch blocks. Their functions:
checkTrustedRecursive() method of the TrustManagerImpl class return an empty array.a() method of class t5.c return false.b() method of class t5.c return false.The first block is used to validate TLS certificates. With this hook, the app treats the server certificate as valid, effectively bypassing pinning. Now, let’s start the app while injecting our script. This will neutralize the functions preventing the app from launching initially, and we’ll test whether SSL pinning bypass was successful.
frida -U -f <package_name> -l .\frida_script.js
This time, the app launched without issues. Let’s log in and check whether the request appears in the proxy.
SSL Pinning Bypass failed
No requests appeared in the proxy, so our SSL pinning bypass attempt failed. Based on past experience, I suspect the app might be built using Flutter. To confirm, let’s return to Jadx and inspect the source code.
flutter_assets found in Resources
We see a flutter_assets folder under Resources, confirming the app was developed using Flutter. In traditional Android apps, we can bypass SSL pinning by hooking classes like TrustManager or SSLContext using Frida. But because Flutter apps are written in Dart, these methods don’t work directly.
Since HTTPS connections in Flutter are handled by the Dart-side HttpClient class, a different analysis and hook approach is needed. In our case, even though we hooked TrustManagerImpl on the Java side, we couldn’t capture any traffic — which suggests pinning is happening at the Dart or C++ layer.
To bypass pinning in Flutter apps, we’ll use the script from
TheDauntless/disable-flutter-tls-v1.
Now we have two scripts to run. While it’s possible to combine them into a single script, we’ll go with a simpler approach: first run the app with our script, then get the app’s PID (process ID), and finally attach the Flutter script to that PID.
Flutter apps may ignore system proxy settings. Therefore, to redirect the app’s traffic, we need a system-level proxy solution instead of app-level. This is where the ProxyDroid tool helps by enabling a global proxy configuration.
Routing device traffic to Burp machine via ProxyDroid
Started with our own script
Found PID using frida-ps -U | findstr <app_name>
Attached Flutter script using the obtained PID
After completing the above steps, we see that the Flutter script successfully patched the SSL pinning. Let’s try logging in again and check whether we can see the request in the proxy.
Finally the request appeared in proxy!
At last, we achieved the desired result — we can now see the app’s traffic in Burp. Let the testing begin!