- rev.ng a publié le backend de décompilation revng-c, faisant passer son moteur de décompilation en open source, tout en lançant une bêta fermée de son UI, un nouveau site web, rev.ng Hub et de la documentation
- En local, on peut configurer la CLI avec un script d’installation, puis utiliser
revng artifact et revng ptml pour examiner un résultat de décompilation sous forme de code C valide
- L’UI interactive, basée sur VSCode, vise à fonctionner à la fois dans le navigateur et comme application autonome, et est proposée dans une bêta fermée avec invitations FIFO pour les abonnés à la newsletter
- La récupération automatique des structures de données, le reverse engineering collaboratif, la prise en charge de nombreuses architectures et l’extensibilité sont les objectifs clés, mais la QA se concentre actuellement surtout sur les binaires Linux x86-64
- Le framework et la CLI sont open source, l’UI cloud est gratuite pour les projets publics, tandis que les projets privés et l’UI autonome hors ligne relèvent d’un modèle payant
Passage en open source et bêta fermée
- rev.ng a publié en open source
revng-c, le backend de son décompilateur
- Cette publication fait passer l’ensemble du moteur de décompilation en open source
- Une première documentation est également disponible
- L’UI va commencer à envoyer des invitations à une bêta fermée aux abonnés de la newsletter
- Un nouveau site web et rev.ng Hub sont également lancés
- rev.ng Hub est le point d’entrée de la version cloud
- Les bêta-testeurs peuvent créer des projets, lancer l’UI dans le navigateur et collaborer avec d’autres utilisateurs
- Même sans accès à la bêta fermée, il est possible de parcourir les projets publics
- rev.ng propose aussi des démos privées pour les utilisateurs qui veulent voir concrètement ses capacités
Essayer rev.ng via la CLI
revng peut être installé dans un seul répertoire sans privilèges root, et il suffit de supprimer ce répertoire pour le désinstaller
curl -L -s https://rev.ng/downloads/revng-distributable/master/install.sh | bash
cd revng
source ./environment
- L’exemple
example.c est un programme simple qui renvoie argc * 3
int main(int argc, char *argv[]) {
return argc * 3;
}
- Après compilation avec
gcc, l’exécution de revng artifact permet d’obtenir un résultat de décompilation sous forme de fichier unique
gcc example.c -o example -O2
revng artifact \
--analyze \
--progress \
decompile-to-single-file \
example \
| revng ptml --color \
| grep -A2 -B1 '[^_]main\b' \
> decompiled.c
Périmètre de la bêta et cibles de test
- Pour utiliser l’UI, il faut s’inscrire à la newsletter, les invitations étant envoyées par petits lots
- Cette version met l’accent sur des démonstrations de l’UI et des résultats de décompilation sur certains binaires, ainsi que sur la collecte de retours et de rapports de bugs à partir de vrais usages
- Les binaires non triviaux utilisés pour les tests et la taille de leur section
.text sont les suivants
- rev.ng prend en charge plusieurs ABI et plateformes, mais à ce stade la QA initiale se concentre sur les binaires Linux x86-64
- En cas de problème, de l’aide est disponible sur Discourse
L’expérience de décompilation visée par rev.ng
- Les priorités de rev.ng sont la récupération automatique des structures de données, une UX moderne, le reverse engineering collaboratif, une large prise en charge des plateformes et l’extensibilité
-
Récupération automatique des structures de données
- Grâce à la Data Layout Analysis, il est possible de reconstruire automatiquement la disposition des
struct via une analyse interprocédurale
- L’exemple du nœud de liste chaînée concerne une structure avec un tableau
int64_t data[5] et un pointeur vers le nœud suivant
- La sortie de rev.ng génère automatiquement une structure et du code de fonction détectant la taille 5 du tableau et l’accès au pointeur vers l’élément suivant
- La sortie du décompilateur est un code C syntaxiquement valide
- Cette fonctionnalité est disponible dès maintenant
-
UI interactive basée sur VSCode
- L’UI étant basée sur VSCode, les utilisateurs de VSCode y retrouveront des repères familiers
- Elle peut fonctionner à la fois dans un onglet de navigateur et dans une application autonome
- Les principaux raccourcis sont les suivants
Ctrl + Click : aller à la définition de la fonction ou du type sous le curseur
N : renommer
Y : modifier le type
X : afficher les références
- rev.ng est un décompilateur interactif qui ne recalcule que les parties affectées lorsqu’une modification survient
- L’UI est actuellement réservée aux participants de la bêta fermée
-
Reverse engineering collaboratif
- L’UI de rev.ng utilise une architecture client-serveur
- Plusieurs utilisateurs peuvent se connecter à la même instance de démon et travailler simultanément sur le même projet
- Dans la version cloud, rev.ng Hub sert d’application de gestion de projets, dans un esprit proche de GitHub
- Les fonctions collaboratives sont opérationnelles, mais l’expérience utilisateur doit encore être améliorée, point suivi dans la roadmap #797
Prise en charge des architectures et des plateformes
- rev.ng utilise la partie amont de la pipeline QEMU pour relever le code exécutable en tiny code, puis le convertir en LLVM IR avant la décompilation
- Cette architecture permet de prendre en charge relativement facilement les architectures supportées par QEMU
- Au-delà de l’architecture, la prise en charge des plateformes, et notamment des ABI, est tout aussi importante
- rev.ng utilise un format de description d’ABI pour décrire déclarativement les propriétés des ABI
- Ce format a été conçu de manière suffisamment générale pour faciliter l’ajout de nouveaux ABI
- L’état actuel du support est le suivant
- Architectures : x86, x86-64, ARM, AArch64, MIPS, s390x, avec des niveaux de maturité variables
- Formats binaires : prise en charge de ELF, PE/COFF et Mach-O
- Import : prise en charge de
.idb, des informations de debug DWARF et des informations de debug PDB
- L’essentiel de la QA a été réalisé sur des binaires Linux x86-64, le reste nécessitant davantage de validation
- Un effort de QA sur davantage de plateformes est suivi dans la roadmap #58
Extensibilité et scripting
- rev.ng vise à être un framework pour les outils de reverse engineering, et l’ensemble du projet, à l’exception de l’UI interactive, est open source
- Le fichier de projet model étant un document YAML, il est possible de piloter rev.ng par script dès lors qu’on sait parser du JSON ou du YAML
- Le modèle contient notamment l’architecture du binaire à décompiler, l’ABI par défaut, les segments, la liste des fonctions et la liste des types
- Il est possible de modifier le modèle via des wrappers pour Python et TypeScript
- Des wrappers de manipulation du modèle existent déjà, mais il n’y a pas encore de moyen simple d’exécuter des analyses et de récupérer des artefacts
- Un client Python complet est suivi dans la roadmap #17
- Les représentations internes reposent largement sur LLVM IR, ce qui permet d’utiliser des outils de l’écosystème LLVM
Distinction entre CLI open source et UI payante
- Le framework rev.ng est entièrement open source, et la CLI permet de décompiler la cible de son choix
- L’UI est proposée selon trois modalités
- l’UI cloud pour les projets publics est utilisable gratuitement
- l’UI cloud pour les projets privés nécessite un abonnement
- l’UI entièrement autonome et totalement hors ligne est proposée sous forme payante
- Le fonctionnement côté cloud est le suivant
- création d’un projet et invitation de collaborateurs depuis rev.ng Hub
- exécution de l’UI dans le navigateur
- exécution du backend dans le cloud rev.ng
- Si publier les fichiers de projet ne pose pas de problème, il est possible d’utiliser gratuitement la version cloud de rev.ng avec son UI
- L’installation d’un service de cloud privé on-premise utilisant Kubernetes peut également être discutée
Roadmap 1.0 et canaux de contact
- La roadmap jusqu’à la version 1.0 est divisée en 4 niveaux
- Tier 1 : version alpha, démos auprès de personnes proches, terminé
- Tier 2 : version bêta, accès à la version cloud pour les abonnés à la newsletter, démarrage en cours
- Tier 3 : bêta ouverte, prévu
- Tier 4 : sortie 1.0, prévu
- La progression détaillée est disponible sur la page roadmap
- Les actualités du projet et les canaux de support sont les suivants
- X/Twitter : actualités de développement et annonces majeures
- Discord : échanges en temps réel avec l’équipe de développement
- Discourse : support utilisateur et rapports de bugs
- GitHub : développement open source et remontée d’issues
- Monthly newsletter : accès à la bêta fermée et nouvelles mensuelles
- E-mail : demandes privées
1 commentaires
Avis Hacker News
Le modèle tarifaire repose sur le fait que le framework rev.ng est entièrement open source, et que la CLI permet de décompiler n’importe quoi
L’UI sera gratuite dans le cloud pour les projets publics, proposée sous forme d’abonnement cloud pour les projets privés, et une application hors ligne totalement autonome sera payante
À titre de comparaison, Hopper coûte 100 dollars avec un an de mises à jour incluses https://www.hopperapp.com/index.html, Ghidra et Radare2 sont libres et open source, donc entièrement gratuits, tandis qu’IDA Pro est très cher
D’après mon expérience, il est assez proche d’IDA, mais plus convivial, avec beaucoup de fonctionnalités bien conçues qui améliorent la productivité
Je n’ai pas essayé Hopper, mais mon expérience de développement avec Ghidra et Radare2 a été assez mauvaise, et le code C généré n’était pas très lisible. Cela dit, je les ai utilisés il y a quelques années
Binja coûte 300 dollars, 1500 dollars pour un usage commercial, et il existe aussi une réduction étudiante : https://binary.ninja/features
Cela dit, les bons décompilateurs C sont toujours rares, donc toute nouvelle tentative est toujours bienvenue
Je me demande toutefois comment ils l’appliquent sans rendre l’accès à Internet obligatoire pour l’application
En regardant la page de l’équipe https://rev.ng/about et les contributions au code https://github.com/revng/revng/graphs/contributors, il est un peu inhabituel de voir que le CEO (aleclearmind) a beaucoup plus de commits que le CTO (pfez)
D’autres CEO disent souvent qu’ils n’ont presque pas le temps de coder, et les CTO aussi sont généralement davantage du côté management et codent moins directement
Mais si cette approche fonctionne bien, ça doit être assez intéressant pour l’équipe. Modification : je n’ai pas vérifié la chronologie
À terme, les deux dépôts seront fusionnés
Et je développe tous les jours, mais pour une raison quelconque GitHub ne reconnaît pas correctement mon utilisateur
Et oui, c’est effectivement amusant
Au contraire, j’aimais bien cet aspect, et je le trouvais intéressant parce que c’était différent de ce que j’avais vu ailleurs
Est-ce que ça a été downvoté parce que ce n’était pas intéressant ou pas inhabituel ?
Ça ressemble à une belle entreprise inspirée par l’un des meilleurs livres de théorie des langages de programmation existants : https://link.springer.com/book/10.1007/978-3-662-03811-6
« Il a aussi rencontré Pietro, qui allait devenir son complice. De façon assez romantique, il l’a rencontré grâce au livre qui allait poser les bases de l’entreprise. »
https://rev.ng/about
Puis je suis tombé sur ce livre, dense mais apparemment clair, et quand j’ai demandé à mon directeur de thèse si je pouvais l’acheter, il m’a répondu : « vérifie d’abord à la bibliothèque de l’université »
La bibliothèque en avait un exemplaire, mais il était déjà emprunté, et comme j’étais dans le seul groupe qui faisait de la recherche sur les compilateurs, je me suis demandé : « qui ose faire des compilateurs en dehors de notre groupe ? »
Je suis allé à la bibliothèque demander qui l’avait emprunté, mais on m’a dit qu’on ne pouvait pas me le dire pour des raisons de confidentialité ; j’ai seulement demandé la troisième lettre du nom et la deuxième lettre du prénom, et j’ai obtenu Z et I
Je l’ai retrouvé ici : https://www.deib.polimi.it/ita/personale-lista-alfabetica
Avec le temps, nous sommes devenus amis et avons lancé une entreprise ensemble
Il a vraiment fallu énormément de travail pour arriver jusqu’au lancement
Ce serait bien d’attribuer automatiquement des noms de variables et de membres de structures à partir de la façon dont le code les utilise
Par exemple, le pointeur suivant d’une liste chaînée devrait être facile à identifier comme
nextIl semble possible de télécharger tout GitHub, de chercher dans le code les variables dont la disposition et les interactions sont les plus similaires, puis d’utiliser leur nom si le niveau de confiance est suffisamment élevé
Par exemple, détecter les variables d’induction et les renommer en
iMais aujourd’hui, il semble assez clair que la bonne façon de faire ce genre de choses consiste à utiliser des LLM
Cela dit, à ce stade, nous sommes plutôt les gens qui construisent des fondations solides ; une fois ces fondations en place, renommer des éléments ou ajouter des commentaires avec des modèles prêts à l’emploi devient relativement simple
L’idée clé, c’est que nous nous chargeons de la partie difficile de la décompilation, qui exige une exactitude de 100 %, tandis que les LLM peuvent intervenir sur les parties où une approximation est acceptable, comme les noms et les commentaires
Dans tous les cas, écrire un script de renommage est assez simple, donc vous pouvez consulter la documentation : https://docs.rev.ng/user-manual/model-tutorial/
L’article qui explique ce que JSNice fait en interne : https://files.sri.inf.ethz.ch/website/papers/jsnice15.pdf
Ne fonctionne pas avec mon fichier ELF
Quand j’exécute
./revng artifact --analyze --progress decompile-to-single-file ../maytag.ko, j’obtiensOnly ELF executables and ELF dynamic libraries are supported, et le fichier est indiqué commeELF 64-bit LSB relocatable, x86-64, version 1 (FreeBSD), not strippedEst-ce que les binaires FreeBSD ne sont pas pris en charge ?
Modification : j’avais manqué le fait que les modules noyau ne sont pas pris en charge ; on dirait que c’est plutôt parce que ce n’est pas un simple exécutable, plus que pour une question liée à FreeBSD
Charger ça ne devrait pas être si difficile
J’aimerais qu’on s’intéresse beaucoup aux workflows collaboratifs
Je n’ai jamais utilisé quelque chose comme IDA Teams, mais si une expérience de reverse engineering aussi fluide que Google Docs était possible, ce serait génial
Avant, on utilisait QtCreator pour l’UI, et c’était un choix horrible
Ensuite, on est passés à VSCode, qui pouvait justement aussi s’exécuter dans le navigateur
On a donc ajouté un peu de Kubernetes et créé un décompilateur cloud avec exactement la même expérience utilisateur que la version entièrement autonome
La partie collaboration a encore besoin de plus de QA, mais elle fonctionne globalement
L’architecture est très simple : un démon avec plusieurs clients
Je pense que l’inspiration vient d’une ancienne expérience en CTF où l’on « collaborait » avec plusieurs fenêtres IDA et plusieurs curseurs au-dessus de la session X du serveur. C’était une méthode vraiment maudite, mais ça marchait
Avez-vous prévu de prendre en charge l’inférence de types ?
Pour l’instant, il me semble que toutes les variables apparaissent comme
generic64_t, et ce serait bien de détecter automatiquement les types comme Ghidra. Même si Ghidra se trompe parfois, bien sûrÉlément de la roadmap : https://rev.ng/roadmap#feature-798
Pad de conception : https://pad.rev.ng/s/eDHi2PUoP#
Ça a l’air intéressant
J’aimerais essayer la version entièrement autonome
Avez-vous des infos sur le prix approximatif ? J’espère que ce sera suffisamment abordable pour les utilisateurs amateurs
C’est toujours réjouissant de voir se multiplier les outils de hacking de binaires
Comme je pourrais vouloir l’essayer moi-même, je laisse des suggestions très pointilleuses sur le format de packaging choisi
source ./environmentest un mauvais signe. J’ai récupéré le tar et, effectivement, il définit plusieurs variables d’environnement, dont PATH ; heureusement, pasLD_LIBRARY_PATHLa plupart ont le préfixe
HARD_, qui est sans doute unique, maisREVNGme semblerait plus clair, et entrer en conflit avec des variables d’environnement existantes est une mauvaise choseIl définit aussi
AWS_EC2_METADATA_DISABLED="true"; je n’utilise pas AWS donc ça ne casse rien chez moi, mais de manière générale c’est suspectRPATH_PLACEHOLDER,HARD_FLAGS_CXX_CLANG, un PATH très long, des chaînes mingw32/gentoo/mips, etc. semblent fragilesQuand les instructions d’exécution disent « maintenant, modifiez vos variables d’environnement », j’abandonne généralement ; c’est fortement corrélé avec des programmes qui ne fonctionnent pas correctement sur des systèmes non Ubuntu
Lier le flot de contrôle de l’application à l’environnement d’exécution crée plus de modes de défaillance qu’il n’y paraît au premier abord, et c’est très proche des variables globales
Clang peut intégrer à la compilation des valeurs par défaut comme
-DCLANG_DEFAULT_CXX_STDLIB=libc++, etDEFAULT_SYSROOTest aussi utileMême en utilisant
rpath, si l’utilisateur lance le binaire avecLD_LIBRARY_PATHdéfini, leDT_RUNPATHdu binaire peut être écraséAujourd’hui,
-Wl,rpathsignifie en réalité runpath, pas rpath, ce qui est moins utile ; l’appel voulu est probablement-Wl,rpath -Wl,--disable-new-dtags, afin que le loader ignoreLD_LIBRARY_PATHlors de la recherche des bibliothèquesEn combinant des flags de build Clang, du linking statique, l’intégration de binaires dans le binaire, etc., il y a de fortes chances de pouvoir éliminer complètement la manipulation des variables d’environnement
Le fait que le binaire
clang-16soit lié dynamiquement et cherche à l’exécution des choses commelibLLVMAArch64CodeGen.so.16augmente aussi les modes de défaillanceLLVM_BUILD_STATIC=ONpeut réduire le risque de récupérer les mauvaises bibliothèques dans un environnement où une toolchain de modules HPC est activéeLes outils sont liés à
libc++.so,libc++abi.so, etc. ; envisager une libc++ statique vaudrait le coup, et à tout le moins il vaut mieux lier statiquementlibc++abietlibunwinddans libc++Je n’ai plus aucune patience pour la distribution de programmes liés dynamiquement sous Linux
Si le
source ourhackdu README ou des variables d’environnement laissées par un système de modules modifient les bibliothèques runtime de mon application, l’expérience utilisateur et le coût des rapports de bugs qui suivent deviennent catastrophiquesÀ côté de ça, le linking statique est vraiment appréciable
source environmentEn fait, si nous l’avons proposé, c’est seulement pour utiliser le GCC que nous distribuons pour les binaires de démonstration ; le mode d’utilisation prévu est le script
./revngDans ce cas, les modifications d’environnement n’affectent que l’appel à
revngLa documentation est ici : https://docs.rev.ng/user-manual/working-environment/
Il serait bon d’ajouter un avertissement à propos de
source ./environmentNous avons passé beaucoup de temps à éviter d’utiliser
LD_LIBRARY_PATH, et nous avons produit un ensemble de binaires entièrement autonomes où chaque ELF référence ses dépendances par des chemins relatifs.LD_LIBRARY_PATHest le malLes variables
HARD_ne sont utilisées que dans les wrappers de compilateur, et je pense qu’elles ont très peu de chances d’entrer réellement en conflitLa discussion d’origine sur
AWS_EC2_METADATA_DISABLED="true"se trouve ici : https://github.com/revng/revng/pull/309#discussion_r12805759...On pourrait l’éviter en patchant le SDK AWS, mais de toute façon cela n’a d’effet que lorsque rev.ng s’exécute dans le cloud
RPATH_PLACEHOLDERetHARD_FLAGS_CXX_CLANGsont utilisés quand revng lie des binaires traduits, et n’ont pas d’importance si l’on ne s’intéresse pas à la traduction binaire de bout en boutNous voulons intentionnellement
DT_RUNPATH.DT_RPATHest déprécié, et il peut exister des cas d’usage où l’on doit remplacer nos bibliothèques viaLD_LIBRARY_PATHJe pense que la remarque sur la « manipulation de l’environnement » n’est valable que s’il ne s’agit pas de variables d’environnement privées
RPATH_PLACEHOLDER,HARD_*etREVNG_*sont des variables privées, toutes destinées à la traduction binaireOn pourrait les déplacer dans un wrapper de compilateur au périmètre plus réduit, mais comme nous distribuons aussi Python, nous ne pouvons pas supprimer complètement l’environnement
Il ne suffit pas d’intégrer certains flags dans Clang. Ces flags affectent aussi l’éditeur de liens, et certaines fonctions du wrapper ne peuvent pas simplement être intégrées en dur
Cela dit, on peut les déplacer vers un emplacement plus privé
Vous semblez vous méfier du linking dynamique, mais nous y avons consacré des efforts, et maintenant cela fonctionne plutôt bien en trouvant toujours le bon emplacement
Nous ne codons pas de chemins absolus en dur, et il n’y a pas non plus d’étape d’installation qui « patche » les binaires. Le répertoire décompressé peut être déplacé n’importe où
La solution que nous utilisons n’emploie pas
LD_LIBRARY_PATH; tous les binaires se référencent mutuellement de manière robuste via$ORIGINEssayez d’exécuter
./root/bin/python ./root/bin/revng artifact --help: cela fonctionneEncore une fois,
source environmentest presque uniquement destiné à la démo ; en utilisation réelle, il suffit d’exécuter./revnget l’environnement reste intactNous distribuons aussi Python, mais vous n’êtes pas obligé de l’utiliser. Vous pouvez utiliser
./revng, ou interagir par le réseau en mode daemonL’approche consiste à parser et modifier le fichier de projet YAML avec l’outil de scripting de votre choix, puis à appeler
./revng artifactou à interagir avec le daemon : https://docs.rev.ng/user-manual/model-tutorial/Au final, nous utilisons une version récente de Python, et l’utilisateur peut utiliser le langage qu’il souhaite
Par la suite, nous prévoyons de fournir sur PyPI un wrapper auxiliaire compatible avec différentes versions de Python
En résumé, inutile de faire
source ./environment: utilisez./revngJe suis content qu’il y ait des gens qui prêtent attention à ce genre de détail
Lors de la prochaine grande itération, l’introduction de nix + mount namespace pourrait permettre d’utiliser
/nix/storesans droits root, ce qui simplifierait beaucoup de chosesIl vaudrait peut-être mieux poursuivre ce genre de discussion sur le serveur Discord plutôt qu’ici
Regrettes-tu d’avoir confié le lifting à QEMU TCG, ou est-ce que cela a bien fonctionné ?
Premièrement, nous n’avons pas rebasé notre fork de QEMU pendant plusieurs années, ce qui nous a mis dans une mauvaise situation
Malgré tout, pas plus tard qu’aujourd’hui, un membre de l’équipe a réussi le lifting avec la dernière version de QEMU, et nous avons aussi pu lifter le code Qualcomm Hexagon pour lequel nous avions aidé à ajouter le support dans QEMU
Au final, nous serons le premier véritable décompilateur Hexagon
Deuxièmement, comme nous nous sommes trop concentrés sur QEMU, le frontend est fortement couplé à QEMU
Désormais, prendre en charge des frontends supplémentaires non basés sur QEMU demandera un peu d’effort, mais ce n’est pas impossible
L’idée est que, lorsqu’un utilisateur ajoute le support d’une nouvelle architecture, il n’ait qu’à définir en C la structure d’état du CPU et quelques fonctions qui opèrent dessus
Il n’a pas besoin d’apprendre la représentation interne
En résumé, QEMU a été un excellent choix, et il a tellement bien fonctionné que nous n’avons pas touché à cette partie de la codebase pendant longtemps, ce qui a créé de la dette technique, mais nous sommes en train de la résorber