Breaking Flutter: A Pentester’s Guide to Dart, Snapshots, and TLS Bypasses
5 min read
May 4, 2025

Table of contents
Hey everyone!
Hope you're doing great.
Last week, I shared some key Kerberos attack techniques for pentesters.
This time, we’re switching gears to something more mobile: Flutter, and specifically, how to break it.
Lately, I’ve been auditing several Flutter apps and wanted to share some tips I’ve discovered during the process.
Whether you’re analyzing a Flutter app during a mobile engagement or just curious about how Flutter works under the hood, this post will give you practical techniques to reverse and poke at them like a pro.
Let’s jump in.
Quick Theory: How Flutter Apps Actually Work
Before diving into recon techniques, it’s important to understand what makes Flutter apps different under the hood and why reversing them isn't as straightforward as with regular Android apps.
Flutter uses Dart and AOT Compilation
Flutter apps are written in Dart. When building for release (production), Dart code is compiled ahead of time (AOT) into native code. On Android, this results in a native shared object called libapp.so
, which contains the app’s business logic. This means:
- There’s no
.dex
or.smali
representation of the Dart code. - Tools like
jadx
won’t show the actual business logic. - You'll need to analyze native libraries directly or inspect Dart snapshots in non-release builds.
The Flutter Engine is Embedded
Every Flutter app bundles the Flutter engine, which lives in a shared object called libflutter.so
. This handles rendering, input, animation, and communication between Dart and native code.
libflutter.so
is shared across all Flutter apps.- It doesn't include project-specific logic, but it's useful when hooking native functionality with Frida.
Communication Happens via Platform Channels
Flutter uses platform channels (e.g., MethodChannel
, EventChannel
) to communicate between Dart and the native Android or iOS layer. These channels are critical when you want to hook authentication, storage, or cryptographic operations, as Dart often delegates those to native code.
Snapshots in Debug and Profile Builds
In debug
or profile
builds, libapp.so
might not be present. Instead, the app runs using Dart snapshot files that are interpreted at runtime:
kernel_blob.bin
isolate_snapshot_data
vm_snapshot_data
These files can still expose class names, symbols, and logic structure. However, you’ll need specific tools or scripts to extract anything meaningful from them.
Recon Techniques for Flutter Apps
Before jumping into traffic interception, it’s often a good idea to understand the app’s structure, logic, and surface area. Flutter apps complicate this due to their native compilation, but there are still effective techniques you can use to break them open.
Full APK Decompilation with apkx
apkx
automates the extraction of all APK internals, including DEX, resources, native libs, and converts the DEX to JAR for easy navigation. Great starting point to explore native libraries and any embedded Java/Kotlin logic.
apkx target.apk
Static Analysis with MobSF
MobSF gives you a fast overview of the app: permissions, activities, trackers, exposed components, and network endpoints. Even with Flutter, this helps uncover basic misconfigurations or embedded secrets.
Native Reversing with Ghidra
Flutter’s Dart code is usually compiled into libapp.so
, which holds the AOT-compiled logic of the app. Tools like jadx
won’t help much here. Instead, load the native library into Ghidra to reverse engineer low-level logic, look for method names, strings, and identify Flutter plugins or obfuscated behavior.
Dart Snapshot Inspection
Sometimes you’ll find files like kernel_blob.bin
, isolate_snapshot_data
, or vm_snapshot_data
inside the APK. These contain compiled Dart bytecode. With custom tools or scripts, you can try to extract readable Dart symbols or identify class/function names.
Manual Recon with jadx
While most business logic is in Dart, many Flutter apps still include Java-based plugins (e.g. for network or crypto). jadx
is useful for inspecting those native interfaces, especially when combined with Frida hooks later on.
How to Intercept Traffic from Non-Proxy Aware Flutter Apps
So, you install the Flutter app you want to test, set up your proxy, route your device’s traffic through your Kali box... and nothing. No requests in Burp, no useful logs. What’s going on?
The issue?
Flutter apps are often non-proxy aware, meaning they completely ignore your system proxy settings.
I plan to write a dedicated article on this soon, but here’s a quick overview of how to handle it:
Set up an OpenVPN server
This allows you to tunnel all traffic from the target device through a VPN that redirects requests to your Burp proxy.
Create a controlled Wi-Fi access point
Use a device like a Kali box or Raspberry Pi to host a rogue access point. Then configure iptables
or redir
to transparently forward traffic to your proxy.
Once you have traffic properly routed, you’ll most likely encounter TLS pinning. That’s where Frida becomes essential.
Use this Frida script to disable Flutter’s TLS verification
NVISO’s Flutter TLS Bypass
GitHub: https://github.com/NVISOsecurity/disable-flutter-tls-verification
This script often works out of the box and patches the Flutter engine to disable certificate validation. However, in my experience, it tends to work more reliably on iOS than on Android. Your mileage may vary depending on the Flutter version and the target device.
Custom plugins may require extra work
Sometimes the app uses a plugin that handles its own TLS logic. In those cases, the generic Frida patch won’t be enough. Use tools like jadx
to explore the code and locate certificate pinning implementations.
One plugin I’ve run into frequently is:
https://github.com/diefferson/http_certificate_pinning
To bypass it, you can try a Frida script like this one:
https://codeshare.frida.re/@incogbyte/android-mix-sslunpin-bypass/
Important: the class name used in the original repo is now diefferson.http_certificate_pinning.HttpCertificatePinningPlugin
.
Most public Frida bypasses still reference the old class name HttpCertificatePinning
, so if the script fails, check for that.
Optional: Try ReFlutter for Dart snapshot extraction
You can also try ReFlutter to extract and reconstruct Dart snapshot files like isolate_snapshot_data
or kernel_blob.bin
.
It attempts to rebuild the original Dart code into a readable form.
That said, I haven’t had much luck getting useful output from it in practice, especially with recent versions of Flutter. Still, it’s worth trying in case you get lucky.
Final Thoughts
That’s it for this post. Flutter may look different on the surface, but with the right tools and mindset, it becomes just another platform you can analyze and break effectively.
As I mentioned last week, the blog post for this week is focused on Slither’s API. It covers how to use it to create custom detectors and analyze smart contracts in depth.
You can check it out here: Slither API Deep Dive.
Let me know what you'd like to see next, especially if you're into mobile or smart contract hacking.
References
For setting up traffic interception with Burp and OpenVPN, check out this detailed guide:
Intercepting HTTP Traffic with OpenVPN on Android – InfoSec Writeups
The OWASP Mobile Security Testing Guide also covers this technique here:
OWASP MASTG – MASTG-TECH-0109
Chapters

Previous Issue
Next Issue
