
Анализатор AOT-снимков Dart с конфигурацией, экспортирующий совместимые с blutter символы и структуры для IDA, radare2 и Frida, а также декомпилирующий функции в dart-analyze-clean Dart без Dart SDK.
Анализатор Dart AOT snapshot с управлением через конфигурацию и экспортёр отладочной информации. Не требует Dart SDK и никогда не запускает цель: находит встроенный snapshot внутри Mach-O / ELF / PE, экспортирует те же символы и структуры, что и blutter, для IDA / radare2 / Frida (с четырьмя намеренными исправлениями там, где эталон, с которого он был портирован, ошибался — см.
src/export/mod.rs), и декомпилирует функции в Dart, который принимаетdart analyze. Поддерживает как десктопные, так и мобильные сборки для реальных устройств (со сжатыми указателями).
Работает с любым артефактом Dart AOT — релизными сборками Flutter, dart compile exe, dart compile aot-snapshot (кластерные snapshot-ы Dart 2.7+).
Самодостаточный и с автоопределением — все 26 профилей SDK плюс 21 вариант со сжатыми указателями встроены; версия Dart сопоставляется по хешу snapshot, а вариант (compressed-pointers, то есть любая мобильная сборка Flutter) — по строке features самого snapshot, с запасным структурным зондированием для кастомных сборок и сборок Flutter-движка. Проверено на реальных поставляемых приложениях, а не только на наших собственных сборках:
dart analyze (95,9% и 91,1% структурировано).dart analyze 0 ошибок.material_3_demo (5 107 строк) и
animations (2 108 строк): 15 796 и 11 102 функции, обе 92,5% структурировано, обе
dart analyze 0 ошибок. Поскольку исходный код известен, они проверяются против него:
98,8% и 100% публичных классов/миксинов/перечислений, объявленных в lib/, восстановлены, 95,4% и
97,4% его строковых литералов присутствуют в выводе, а 18/18 и 21/23 исходных файлов отображаются на
восстановленную библиотеку. tests/app_truth.rs проверяет эти соотношения (нижняя граница 0,90), чтобы цепочка не могла
незаметно деградировать.Декомпилирует в валидный Dart — lift → CFG → структурированная генерация, а не дамп дизассемблирования: циклы,
if/else, break/continue, литералы пула объектов, встроенные в месте их загрузки, восстановленные имена полей
в виде комментариев-атрибуций. На 26 артефактах (291 файл, 24 253 функции) вывод
анализируется с 0 ошибок dart analyze, и на реальных приложениях он тоже держится — Lark 3.6.1 при 95,9%
структурировано и Weibo 2.19.6 при 91,1% (19 053 функции, 1,53 млн операторов), оба без ошибок.
Неприводимый поток управления сохраняет явный gotoLabel и заголовок NOTE, а не молча
выравнивается. См. Декомпилятор.
Быстрый — всё измерено бинарником этого релиза: 9 МБ macOS-пример Flutter экспортируется за
0,26 с; --decompile занимает 1,5 с на Lark (25,6 МБ Android, 25 183 функции), 1,2 с на
material_3_demo (14 МБ macOS, 15 796 функций) и 1,7 с на Weibo (9 МБ Android,
19 053 декомпилированные функции / 1,63 млн операторов), при пиковом RSS 172–263 МБ. Это ~89× быстрее
чем v0.1.7 на том же артефакте (106,8 с → 1,20 с) — за счёт того, что не перестраиваются инвариантные к запуску данные
для каждой функции, за счёт потоковой записи артефактов на диск вместо их буферизации и за счёт параллельного рендеринга
505 библиотек; а не за счёт более быстрого алгоритма. Параллельный путь побайтово идентичен
последовательному (diff -rq по 1011 файлам), потому что имена файлов и «какая библиотека испускает каждую
точку входа» определяются последовательным предварительным проходом до начала любого рендеринга.
Двуязычный CLI — китайская локаль печатает по-китайски, всё остальное по-английски; переопределяется через DAE_LANG=zh|en.
Параллельный декомпилятор — примерно 505 библиотек рендерятся одновременно (по умолчанию n_threads(),
то есть число ядер с ограничением 8); переопределяется через DAE_DEC_THREADS=N. Вывод побайтово идентичен при любом
значении, потому что имена файлов и «какая библиотека испускает каждую точку входа» определяются последовательным
предварительным проходом. После 8 потоков он становится медленнее и использует больше памяти на Mac с 6P+12E ядрами, так что
ограничение — это оптимальная точка, а не ограничение. DART_AOT_PROF=1 печатает разбивку по фазам — учтите, что её
проценты могут превышать 100%, потому что фазы — это процессорное время, суммированное по потокам.
Прогрессивный режим — 20 подкоманд для запроса к snapshot как к базе данных (libs, classes,
functions, members, strings, findrefs, callers, callees, pp, objs, stubs, ...)
и затем декомпиляция ровно одной вещи (getclass / getmethod / getlib / decompile --app).
Запросы отвечают за 15–30 мс на небольшом корпусе и за 43–311 мс на приложении с 15 796 функциями; полный
экспорт такого приложения занимает 0,55 с, или ~1,4 с с --decompile (~1000 файлов). Вывод каждой команды
можно вставить в следующую.
См. Прогрессивный режим.
Не требует инструментария — один самодостаточный бинарник: без Dart SDK, без установки Flutter, и цель никогда не исполняется, только парсится. Разбор Mach-O/ELF/PE и все 47 профилей встроены.
| Способ | Команда |
|---|---|
| Homebrew (macOS) | brew install ejfkdev/tap/dae |
| cargo | cargo install dae-rs |
| Готовый бинарник | бинарник из Releases — Windows/macOS/Linux × x64/arm64 |
| Из исходников | cargo build --release |
Готовые бинарники для macOS подписаны ad-hoc; если Gatekeeper блокирует первый запуск: xattr -dr com.apple.quarantine dae.
(Пакет на crates.io называется dae-rs, потому что dae уже занято; репозиторий, библиотека и бинарник остаются dae.)