Android · Hybrid apps
Reverse engineering a Flutter app: what you can actually read
Flutter changes the shape of a teardown. Most of the app's logic compiles to native code and is not coming back as readable Dart — but the packaging still tells you a lot, and the native side is where the monetization SDKs live anyway. Here is what the APK gives you, what it doesn't, and how to tell a Flutter app apart from a React Native or Unity one at a glance.
Step 1 — Identify the framework before you decompile anything
Native libraries are the most honest signal in the whole package: they survive obfuscation because they are machine code, not names. Unzip and look:
unzip -l app.apk | grep -E "lib/|flutter_assets|assets/" | head -30
| You see | Framework |
|---|---|
lib/*/libflutter.so + assets/flutter_assets/ | Flutter |
lib/*/libreactnativejni.so, libhermes.so, index.android.bundle | React Native (Hermes or JSC) |
lib/*/libunity.so, assets/bin/Data/ | Unity |
lib/*/libmonodroid*.so, assemblies/ | Xamarin / .NET MAUI |
lib/*/libcocos2d*.so | Cocos2d-x |
A hybrid app can carry two of these at once — the native shell plus one embedded framework. CamScanner, for example, ships a native Android core with Flutter modules bolted on through FlutterBoost: the Flutter part runs newer features, the native part runs scanning. Miss that split and you will mis-attribute half the app's behaviour.
Step 2 — Know what the Dart snapshot does and doesn't give you
Release Flutter builds compile Dart to a native snapshot (libapp.so on Android). It is not
Dart source, and it is not Smali either: there is no supported decompiler that turns it back into
readable Dart. What you can do:
- Extract strings — endpoint hosts, route names, error messages, feature flags, and the occasional API key someone thought was obfuscated.
- Read
flutter_assets/— fonts, images, andAssetManifest.json, which enumerates bundled assets and often names features the app hasn't shipped yet. - Parse
kernel_blob.binif present — a debug/JIT artifact. Its presence in a shipped APK is itself a finding (someone shipped a non-AOT build). - Disassemble
libapp.sowith normal native tooling if you truly need control flow. This is slow, and rarely worth it for a competitive teardown — but it is the honest answer to "can you get the logic back".
The boundary to state out loud: you can recover Flutter's surface (endpoints, assets, plugin set) and not its logic. Anyone claiming a full Dart decompile of a release build is selling you something.
Step 3 — The plugins are where the interesting data is
A Flutter app is a small native container plus a list of plugins, and each plugin is a normal Android dependency. That means the monetization stack is still readable in the DEX and the manifest, even though the UI logic isn't:
# The plugin list is declared in the manifest, and it maps to real SDKs
aapt2 dump xmltree app.apk --file AndroidManifest.xml | grep -iE "flutter|plugin"
# Ads / attribution / analytics live in DEX classes exactly as in a native app
jadx -d out app.apk
grep -rIl "com.google.android.gms.ads\|com.applovin\|com.facebook.ads" out/
grep -rIl "com.appsflyer\|com.adjust.sdk" out/
grep -rIl "io.flutter.plugins" out/ | head -20
For most competitive questions — how does this app make money, which networks does it use, what does it call server-side — the Flutter split costs you almost nothing, because those answers were never in the Dart code.
Step 4 — Hostnames, and why they matter more in hybrid apps
grep -rhoE "https?://[a-zA-Z0-9._-]+" out/ | sed 's|https\?://||' \
| cut -d/ -f1 | sort | uniq -c | sort -rn | head -40
In a native app this list is mostly the vendor's own gateways. In a Flutter app you also get the Dart side's endpoints out of the snapshot strings — which is useful precisely because the Dart code is otherwise opaque. Expect the two lists to overlap; the interesting entries are the ones that only appear on one side.
Record the version code and the date next to every finding. A teardown without a version is a rumour within a month.
Want this done for a specific app? Send a Google Play link and get the full reverse-engineering report — framework split, SDK list, ad networks, API endpoints, architecture — as PDF + Markdown in about 2 hours. $29 for one app, $19 each for three or more.
Disclosure: this page is published by AppXray, which sells that report. Everything above is the method, free to use without it.