Patches and scripts to run blutter on macOS standalone Dart AOT binaries (dart compile exe).
Blutter supports Android libapp.so and iOS App.framework. This extends it to macOS standalones, where the snapshot is embedded as an LC_NOTE inside the outer binary rather than in a separate file.
See the write-up: machinecase.github.io/posts/dart-reverse-macos
dart compile exe produces a single Mach-O that contains the Dart VM runtime (what you see in Binary Ninja) and the compiled app snapshot (what you want to analyze) embedded as opaque data in an LC_NOTE named __dart_app_snap.
The scripts extract the inner Mach-O and wrap it in a synthetic ELF so blutter can parse it using its existing ELF code path.
# 1. Extract inner Mach-O and create ELF wrapper
python3 scripts/extract_snapshot.py ./binary /tmp/analysis/
# 2. Apply patches to blutter
cd /path/to/blutter
git apply /path/to/blutter-macos/patches/macos_standalone_aot.patch
# 3. Run blutter
python3 blutter.py \
/tmp/analysis/dart_snapshot.so \
/tmp/analysis/blutter_out \
--dart-version 3.11.4_macos_arm64
# 4. Triage
grep "String:" /tmp/analysis/blutter_out/pp.txt | grep -v "dart:"
# 5. Import symbols into Binary Ninja
# Open inner.macho, then in Python Console:
exec(open('scripts/import_symbols_bn.py').read())Four files in blutter need changes:
scripts/CMakeLists.txt— addmacosas validTARGET_OSwith correct definesdartvm_fetch_build.py— macOS standalone usesno-compressed-pointersblutter/src/ElfHelper.cpp— detect ELF magic before Mach-O path, fixMH_MAGIC_64case, uncommentmach_o.hincludeblutter/src/Disassembler_arm64.h— moveCSREG_DART_HEAPoutside#ifdef DART_COMPRESSED_POINTERS
Dart 3.11.4, macOS ARM64 (Apple Silicon).
- worawit/blutter original tool
- @m4xfr0m