⚠️ Warning: This project is outdated. The format of Dart snapshots changes CONSTANTLY, and any Dart RE tools like this one NEED constant maintenance or they stop working with newer versions of Dart / Flutter. Contributions are welcome, but I currently do not have the time to invest in monitoring changes to the VM and keeping this updated.
So, if your snapshot was produced by a reasonably modern version, it probably won't parse [correctly]. Still, if you want to try, you'll probably need at least the fix in #3.
darter
is a Python module that can fully parse the data inside a Dart snapshot
(i.e. the libapp.so
file in a release Flutter app).
Features:
app.so
or .snapshot
files automatically.Examples of what you can do with the parsed info:
Note:
Keep in mind that this is for parsing binary (i.e. architecture-dependent) snapshots.
.dill
files and some .snapshot
files contain Kernel AST, which
is a completely different format and currently not supported by darter
.
[Learn more]
Most of the code is zero-dependency, except for:
parse_elf_snapshot(...)
requires pyelftools
the darter.asm
module (for analyzing the assembled code) requires
Capstone
(and its python binding)
darter
in itself is just a module, it has no stand-alone program or CLI.
The recommended way to use it is by including it in a notebook and
playing with the parsed data.
Install Jupyter and open the 1-introduction
notebook for a basic walkthrough of the parsed data; then head to 2-playground
which contains more interesting examples of use.
It's highly recommended that you first play with a known snapshot (i.e. that you have built yourself or have the code), before analyzing the snapshot you are after.
The parser is still at an early stage and will not work in every case.
This parser was written based on dart-sdk at 1ef83b86ae
.
The snapshot format is internal to the VM. It dumps some of the objects as they appear
in memory; you need to know how the VM (arch, compile flags) was compiled in order
to parse it. It can change frequently between versions, as
there's not a standard spec (AFAIK) for the format.
Any help or donations are welcome.
Given an data section and an instructions section (and optionally a base):
OneByteString
, CodeSourceMap
, Instructions
, etc.).The information is returned as parsed as much as possible, so that it is easy to manipulate. Back-references are tracked too, so that it's easy to know where a certain object is referenced from.
darter
can parse both 'VM' snapshots and 'isolate' ones (the ones we care about).
The darter.asm
module disassembles the compiled code and analyzes it.
This is crucial for AOT snapshots, because we get no high-level bytecode.
If you are new to Dart / Flutter reverse-engineering, it's a good idea to read this introduction first: https://mrale.ph/dartvm/
The relevant code on snapshot serialization is at runtime/vm/clustered_snapshot.cc
and runtime/vm/raw_object.h
.
There's also additional info in the info
directory.