Introduction
During an Android mobile VAPT assessment, intercepting HTTPS traffic is an important part of dynamic analysis. It allows security analysts to inspect API requests and responses, modify parameters, and understand how an application communicates with its backend.
For native Android applications developed using Java or Kotlin, configuring a proxy such as Burp Suite and installing its CA certificate is often enough to capture HTTPS traffic. Flutter applications can behave differently because they may use Dart/Flutter networking components or additional networking packages, while the Flutter engine is packaged as native libraries.

As a result, a Flutter application may not respect the Android system proxy, and Java/Kotlin-level SSL-pinning techniques may not affect TLS verification performed within the Flutter layer.
This blog covers a practical methodology for intercepting and bypassing TLS verification in Flutter-based Android applications during an authorized security assessment.
What Is SSL Pinning?
SSL pinning, more accurately referred to as TLS certificate pinning, is a mechanism that adds an additional validation check to the normal TLS certificate-verification process.
Normally, a client verifies that the server certificate is trusted and chains to an accepted Certificate Authority (CA). With pinning, the application additionally verifies a specific certificate or public key associated with the expected server. This additional validation can prevent HTTPS interception even when the proxy CA certificate is trusted by the device.
The relevance for testing is direct: when Burp Suite or HTTP Toolkit intercepts HTTPS traffic, it presents a proxy-generated certificate in place of the real one. An app without pinning accepts this because the proxy's CA is trusted by the device. An app with pinning rejects the certificate at the additional validation step, regardless of whether the device trusts the proxy's CA. Installing the proxy's CA certificate is therefore not enough to bypass certificate pinning.
Why Is Flutter Different?
A native Android application written in Java or Kotlin commonly uses Android networking APIs or libraries such as:
- HttpsURLConnection
- OkHttp
- Retrofit
- Native libraries through JNI
In these applications, certificate-pinning logic may be implemented at the Java/Kotlin layer or within a native library, depending on the application's networking implementation.
Flutter applications use Dart and the Flutter engine, and the application can also use additional networking packages. Therefore, the exact location and implementation of TLS verification can vary. The Flutter engine is packaged in the APK as native libraries, commonly including:
The exact library layout and the relevant TLS implementation can vary between Flutter versions, engine builds, and target architectures this is part of why there isn't one universal bypass, a point covered in more depth later in this guide.
Because TLS verification may occur outside the Java/Kotlin networking layer, native Android certificate-pinning bypass techniques may not be sufficient for Flutter applications.
Setting Up Traffic Interception
Before attempting to bypass SSL pinning, first make sure the application's traffic reaches your interception proxy. Burp Suite or HTTP Toolkit can be used as the interception proxy.
1. Android System Proxy
Start with the Android system proxy:
Proxy Host: <TESTING_MACHINE_IP>
Proxy Port: 8080Install the proxy CA certificate on the testing device and launch the application. If the traffic appears in Burp Suite or HTTP Toolkit, proceed directly to SSL-pinning analysis. If the application does not send traffic through the configured system proxy, move to the next approach.
Flutter/Dart networking may not automatically follow the Android system proxy configuration, depending on how the application performs its networking. NVISO has documented this behavior in its Flutter interception research.
2. ProxyDroid
If the system proxy does not work, ProxyDroid can be used to route traffic through a configured HTTP or SOCKS proxy.
Flutter Application → ProxyDroid → Burp SuiteProxyDroid is being used here for traffic routing. It is not the SSL-pinning bypass itself. If traffic reaches the interception proxy but HTTPS connections still fail, move to TLS-verification bypass below.
3. iptables
If ProxyDroid does not provide the required routing in the testing environment, an iptables-based transparent-redirection setup can be used on a rooted device.
Flutter Application → iptables → Transparent Proxy → Burp Suiteiptables is not a proxy application. It provides packet-filtering and NAT functionality that can be used to redirect traffic to a transparent proxy on a rooted device. The exact configuration depends on the device and transparent-proxy implementation, but the underlying commands typically look like this from a rooted ADB shell:
adb shell
su
iptables -t nat -A OUTPUT -p tcp --dport 443 -j DNAT --to-destination <proxy-ip>:8080iptables -t nat -A OUTPUT -p tcp --dport 80 -j DNAT --to-destination <proxy-ip>:8080To scope the redirect to a single app instead of the whole device:
adb shell dumpsys package <package.name> | grep userIdThen:
iptables -t nat -A OUTPUT -p tcp --dport 443 -m owner --uid-owner <app-uid> -j DNAT --to-destination <proxy-ip>:8080Flush the rules once testing is done:
Note that 443 isn't always the right port to redirect — some apps communicate over a custom or non-standard port instead of the default HTTPS port. If traffic still doesn't show up in your proxy after redirecting 443, check what port the application is actually using. Packet capture or the app's own configuration can help identify the port.
For example, if the app is talking on port 7443:
adb shell su -c "iptables -t nat -A OUTPUT -p tcp --dport 7443 -j DNAT --to-destination 10.10.0.13:8080"Once traffic successfully reaches the interception proxy, proceed with the SSL-pinning bypass methods below.
Different Methods to Bypass SSL Pinning in Flutter Android Applications
Method 1: Frida CodeShare Script (Flutter-Specific)
A quick check worth running before diving into the other methods below is Frida CodeShare's flutter-ssl-pinning-bypass script unlike a generic Android pinning-bypass script, this one is designed specifically to target certificate pinning in Flutter-based Android applications.
frida --codeshare licitrasimone/flutter-ssl-pinning-bypass -U -f <package_name>Script: https://codeshare.frida.re/@licitrasimone/flutter-ssl-pinning-bypass/
CodeShare scripts are community-maintained and can change over time, so it's worth checking the current script contents before relying on it for a specific engagement. If traffic doesn't start appearing in your proxy after running this, treat it as ruled out rather than as a dead end move on to the methods below.
Method 2: ReFlutter
ReFlutter is a Flutter reverse-engineering framework that can patch supported Flutter applications. It supports Android ARM32 and ARM64 applications and provides a patched Flutter library intended to facilitate traffic interception.
Unlike a CodeShare script, ReFlutter operates directly on the APK rather than a running process. It patches the Flutter engine library with a supported pattern, then repacks and resigns the APK. This allows supported certificate-pinning implementations to be bypassed without attaching a Frida hook on every launch.
Its effectiveness depends on the Flutter engine version and whether ReFlutter recognizes the corresponding pattern.
Install ReFlutter:
pip3 install reflutterRun it against the target APK:
reflutter target.apkReFlutter generates a modified APK that needs to be signed before installation:
java -jar uber-apk-signer.jar --allowResign -a release.RE.apkInstall the signed APK:
adb install <signed-apk>.apkAfter installation, configure the interception proxy and test the application.
ReFlutter depends on the Flutter engine and supported patching patterns, so it should not be considered a universal solution for every Flutter application. If the patch is unsuccessful, proceed with the next method.
Method 3: HTTP Toolkit with Frida
HTTP Toolkit provides Frida-based scripts for Android HTTPS interception and certificate unpinning. Unlike ReFlutter, it does not modify the APK; instead, the required hooks are applied at runtime to the running application.
Setup
- Install and launch HTTP Toolkit on the testing machine.
- Select Android Device interception and use the QR Code option to connect the testing device.
- Scan the QR code and follow the prompts to install and open the HTTP Toolkit Android application.
- Allow the VPN connection and install the HTTP Toolkit CA certificate.
- For Android App via Frida, use a rooted device connected through ADB and ensure Frida is available on the device.
- Select the target application and start the Frida-based interception.
Installing the CA certificate establishes trust for the interception proxy, but does not bypass certificate pinning by itself. HTTP Toolkit's Frida-based interception applies runtime hooks that can bypass many common certificate-pinning implementations. The effectiveness depends on the application's TLS and pinning implementation.
Method 4: Frida with NVISO disable-flutter-tls-verification
NVISO Security provides a dedicated Frida script for disabling Flutter TLS verification: disable-flutter-tls-verification. The script uses pattern matching to locate the Flutter TLS verification function ssl_verify_peer_cert in handshake.cc.
Unlike ReFlutter, which modifies the APK, the NVISO Frida script works at runtime. It attaches to the running application, searches the loaded libflutter.so library for the Flutter TLS verification function using a known byte pattern, and hooks that function to alter the certificate verification behavior. Because it searches for a pattern instead of relying on a fixed address, it can work across some different Flutter engine builds, although it still depends on the pattern matching the target binary. The main difference from ReFlutter is that the APK is not modified or resigned, but Frida must be attached again whenever the application is restarted
NVISO — disable-flutter-tls-verification
Clone the repository:
git clone https://github.com/NVISOsecurity/disable-flutter-tls-verification.gitcd disable-flutter-tls-verificationThe repository contains disable-flutter-tls.js. Load it against the running app:
frida -U -F -l disable-flutter-tls.js-U targets the USB-connected device.
-F attaches to the app already running in the foreground instead of spawning it fresh.
-l loads the script into that process.
If you have not set up Frida yet, use the guide below to get it running:
Certbar — SSL Pinning Bypass / Frida Setup
Once Frida is configured, load the NVISO script against the target application and verify whether HTTPS traffic can be intercepted. The important point is that this script targets Flutter's TLS verification directly rather than the typical Java/Kotlin networking classes most standard bypass scripts are written for.
Method 5: Manual Native Analysis
If all of the above methods are unsuccessful, manual analysis can be performed on the Flutter native library.
Extract the APK:
apktool d target.apk -o target_decodedLocate libflutter.so:
find target_decoded -name libflutter.soDetermine its architecture:
file target_decoded/lib/arm64-v8a/libflutter.soNote that arm64-v8a won't always be the relevant path an APK can ship libflutter.so under multiple architecture directories (lib/arm64-v8a/, lib/armeabi-v7a/, lib/x86_64/, and so on), and the device you're testing on determines which one is actually loaded. Confirm the architecture in use on your test device before picking which copy to analyze.
The library can then be analyzed using Ghidra or IDA Pro to identify the TLS verification logic used by the specific Flutter engine build, and a targeted Frida hook developed for the identified function.
There is no universal offset that can safely be reused across Flutter applications, because the relevant function and binary layout can vary between Flutter engine builds.
Conclusion
Flutter applications require a different approach to SSL-pinning analysis compared with native Android applications written in Java or Kotlin. A practical workflow is to first establish traffic routing and then test the available bypass techniques based on the application's Flutter version, networking implementation, and testing environment. Start with a lightweight Flutter-specific technique such as the CodeShare script, followed by ReFlutter, HTTP Toolkit, or the NVISO Frida script. If these approaches are unsuccessful, move to manual analysis of the relevant native libraries using Ghidra or IDA Pro.
References
Share
