
Analyseur de snapshots AOT Dart piloté par configuration qui exporte des symboles et des structures compatibles blutter pour IDA, radare2 et Frida, et décompile les fonctions en Dart propre pour dart-analyze sans SDK Dart.
Analyseur de snapshots AOT Dart piloté par configuration et exportateur d'informations de débogage. Sans SDK Dart, n'exécute jamais la cible : localise le snapshot embarqué dans Mach-O / ELF / PE, exporte les mêmes symboles et structures que blutter pour IDA / radare2 / Frida (avec quatre corrections délibérées là où la référence dont il a été porté se trompait — voir
src/export/mod.rs), et décompile les fonctions en Dart quedart analyzeaccepte. Couvre les builds desktop et mobile sur appareil réel (pointeurs compressés).
Fonctionne sur tout artefact AOT Dart — builds release Flutter, dart compile exe, dart compile aot-snapshot (snapshots cluster Dart 2.7+).
Autonome et auto-détectant — les 26 profils SDK ainsi que 21 variantes à pointeurs compressés sont embarqués ; la version de Dart est identifiée par le hash du snapshot et la variante (compressed-pointers, c'est-à-dire tout build Flutter mobile) à partir de la chaîne de caractéristiques du snapshot lui-même, avec un repli par sonde structurelle pour les builds personnalisés/Flutter-engine. Vérifié contre de vraies applications en production, pas seulement nos propres builds :
dart analyze (95,9 % et 91,1 % structuré).dart analyze 0 erreur.material_3_demo (5 107 lignes) et
animations (2 108 lignes) : 15 796 et 11 102 fonctions, toutes deux à 92,5 % structuré, toutes deux
dart analyze 0 erreur. Comme la source est connue, elles sont vérifiées par rapport à elle :
98,8 % et 100 % des classes/mixins/enums publics déclarés dans lib/ sont récupérés, 95,4 % et
97,4 % de ses littéraux de chaîne apparaissent dans la sortie, et 18/18 et 21/23 fichiers source correspondent à une
bibliothèque récupérée. tests/app_truth.rs vérifie ces ratios (plancher 0,90) afin que la chaîne ne puisse pas
pourrir silencieusement.Décompile en Dart valide — lift → CFG → émission structurée, pas un dump de désassemblage : boucles,
if/else, break/continue, littéraux du pool d'objets inlinés à leur site de chargement, noms de champs
récupérés comme commentaires d'attribution. Sur 26 artefacts (291 fichiers, 24 253 fonctions), la sortie
s'analyse avec 0 erreur dart analyze, et sur de vraies applications cela tient aussi — Lark 3.6.1 à 95,9 %
structuré et Weibo 2.19.6 à 91,1 % (19 053 fonctions, 1,53 M instructions), tous deux sans erreur.
Le flux de contrôle irréductible conserve un gotoLabel explicite et un en-tête NOTE plutôt que d'être
silencieusement aplati. Voir Décompilateur.
Rapide — tout mesuré avec le binaire de cette version : un échantillon Flutter macOS de 9 Mo s'exporte en
0,26 s ; --decompile prend 1,5 s sur Lark (25,6 Mo Android, 25 183 fonctions), 1,2 s sur
material_3_demo (14 Mo macOS, 15 796 fonctions) et 1,7 s sur Weibo (9 Mo Android,
19 053 fonctions décompilées / 1,63 M instructions), à 172–263 Mo de RSS maximal. C'est ~89× plus rapide
que la v0.1.7 sur le même artefact (106,8 s → 1,20 s) — grâce au fait de ne pas reconstruire les données invariantes
par fonction, de diffuser les artefacts sur disque au lieu de les mettre en mémoire tampon, et de rendre les
505 bibliothèques en parallèle ; pas grâce à un algorithme plus rapide. Le chemin parallèle est identique au
niveau octet au chemin série (diff -rq sur 1011 fichiers), car les noms de fichiers et « quelle bibliothèque émet chaque
point d'entrée » sont tous deux fixés par une pré-passe séquentielle avant que tout rendu ne commence.
CLI bilingue — la locale chinoise affiche le chinois, tout le reste l'anglais ; à remplacer avec DAE_LANG=zh|en.
Décompilateur parallèle — les 505 bibliothèques environ sont rendues simultanément (par défaut n_threads(),
c'est-à-dire le nombre de cœurs plafonné à 8) ; à remplacer avec DAE_DEC_THREADS=N. La sortie est identique au
niveau octet quel que soit le réglage, car les noms de fichiers et « quelle bibliothèque émet chaque point d'entrée » sont fixés par une pré-passe
séquentielle d'abord. Au-delà de 8 threads, cela devient plus lent et consomme plus de mémoire sur un Mac à 6P+12E cœurs, donc le
plafond est le point d'équilibre, pas une limitation. DART_AOT_PROF=1 affiche une répartition par phase — notez que ses
pourcentages peuvent dépasser 100 % car les phases sont du temps CPU cumulé sur les threads.
Mode progressif — 20 sous-commandes pour interroger le snapshot comme une base de données (libs, classes,
functions, members, strings, findrefs, callers, callees, pp, objs, stubs, ...)
puis décompiler exactement une chose (getclass / getmethod / getlib / decompile --app).
Les requêtes répondent en 15–30 ms sur un petit corpus et 43–311 ms sur une application de 15 796 fonctions ; un export
complet de cette application prend 0,55 s, ou ~1,4 s avec --decompile (~1000 fichiers). La sortie de chaque commande
est collable dans la suivante.
Voir Mode progressif.
Aucune chaîne d'outils requise — un seul binaire autonome : pas de SDK Dart, pas d'installation Flutter, et la cible n'est jamais exécutée, seulement analysée. L'analyse Mach-O/ELF/PE et les 47 profils sont intégrés.
| Méthode | Commande |
|---|---|
| Homebrew (macOS) | brew install ejfkdev/tap/dae |
| cargo | cargo install dae-rs |
| Précompilé | binaire depuis Releases — Windows/macOS/Linux × x64/arm64 |
| Source | cargo build --release |
Les binaires précompilés macOS sont signés ad-hoc ; si Gatekeeper bloque la première exécution : xattr -dr com.apple.quarantine dae.
(Le paquet crates.io est dae-rs car dae était pris ; le dépôt, la bibliothèque et le binaire restent tous dae.)