Reverse Engineering Flutter Applications

A practical guide to extracting and analyzing Flutter app source code from APK files.

person Camille Louédoc-Eyries
|
calendar_today February 7, 2026
|
schedule 5 min read

When reverse engineering mobile applications, Flutter apps present unique challenges compared to traditional native apps.

In this guide, I’ll walk through the complete process of extracting and analyzing Flutter application code from APK files.

There are two main components you might be interested in:

  1. Native Flutter plugins - These contain platform-specific code implementing features like App Attest for iOS and Play Integrity API for Android. They expose functions via Platform Channels that can be called by Flutter code.
  2. Flutter application code - The Dart code that runs the app logic, which is typically identical between iOS and Android versions.

Here, we’ll focus on the Flutter application code, since the native plugins are trivial to dump and read using jadx.

Flutter reverse-engineering is a moving target. In this post, I’m just showing what worked for me :).

Note on Dynamic analysis

We won’t be covering dynamic analysis today.

Getting the APK of your target app

My favorite way of getting an APK is to install it on a phone, and then pulling it.

First, install the target app on your development phone via Aptoide or Google Play Store.

Then extract the APK:

Terminal window
adb shell pm list packages
adb shell pm path <package.name>
# Save the output paths to a text file and run "adb pull" on each path.
# This will give you a bunch of APKs that you'll need to merge.

You’ll often get multiple APK files, that you can merge like so:

Terminal window
cd pulled # this folder should contain all the .apk that you want to mrege
apkeditor m -i ./ -o ../pulled_merged.apk

This produces a single merged APK in ../pulled_merged.apk.

Extracting the code with blutter

First, install blutter:

Terminal window
git clone [email protected]:worawit/blutter.git
cd blutter
# Install Python dependencies
uv venv
source .venv/bin/activate.fish
uv pip install requests
uv pip install pyelftools

Run Blutter on the APK:

Terminal window
mkdir out
# Prioritize system's ninja over depot_tools' (in case you're doing some Chromium development on the side)
fish_add_path /usr/bin
# This will compile some C++ components, and you might have to install some dependenties
uv run blutter.py ./pulled_merged.apk out/

Troubleshooting blutter C++ compilation errors

Ensure you’re using the vanilla ninja build tool from your system rather than the one from depot_tools (in case you’re working on Chromium on the side :)).

Reading the decompiled code

Reading the code with your bare hands

You will get the following directories in ./out:

  • asm/*: libapp assemblies with symbols
  • blutter_frida.js: the frida script template for the target application
  • objs.txt: complete (nested) dump of Object from Object Pool
  • pp.txt: all Dart objects in Object Pool

The interesting part is ./asm/*, which will tell you your app structure’s and logic.

Reading the code with IDA Pro

Blutter also generates a Python script that can be used with IDA to add symbols to libapp.so.

Sadly, it doesn’t support Ghidra yet.

For now, reading the decompiled output from the asm folder in the Blutter output is possible; it just takes a lot of patience.

Conclusion

In 2026, Flutter reverse-engineering is still a pain.

I am not sure how well IDA Pro works, but I assume it’s good.

If one wanted to significantly improve things for everyone, they could write an integration between Blutter and Ghidra.

mail

Stay in the loop

Get notified when we publish new research. No spam, just posts like this.

rss_feed … or follow our RSS feed

Need help with data extraction?

We apply this level of rigor to every data extraction challenge. Let's discuss your project.

Get in touch