MachineCase/blutter-macos

GitHub: MachineCase/blutter-macos

Stars: 2 | Forks: 0

# blutter-macos Patches and scripts to run [blutter](https://github.com/worawit/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](https://machinecase.github.io/posts/dart-reverse-macos/) ## How it works `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. ## Usage # 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()) ## Patches Four files in blutter need changes: - `scripts/CMakeLists.txt` — add `macos` as valid `TARGET_OS` with correct defines - `dartvm_fetch_build.py` — macOS standalone uses `no-compressed-pointers` - `blutter/src/ElfHelper.cpp` — detect ELF magic before Mach-O path, fix `MH_MAGIC_64` case, uncomment `mach_o.h` include - `blutter/src/Disassembler_arm64.h` — move `CSREG_DART_HEAP` outside `#ifdef DART_COMPRESSED_POINTERS` ## Tested Dart 3.11.4, macOS ARM64 (Apple Silicon).