Skip to content
← Tous les articles
· Delta1 Labs Glass.NETDécompilationGuide.NET

Extraire et lire les ressources embarquées d'un assembly .NET avec Glass.NET

Une DLL porte plus que du code. Cuits dans le même fichier se trouvent des ressources .resources et des chaînes ResX embarquées, des chaînes localisées d'assemblys satellites, des fichiers entiers comme config, JSON, SQL et certificats, et des constantes de chaîne et d'octets. Voici comment tout trouver et lire dans Glass.NET — le décompilateur gratuit et purement statique qui n'exécute jamais l'assembly — et l'exporter sur disque pour l'inspecter hors de l'outil.

Un assembly .NET compilé n’est pas que du code. Cuite dans le même fichier, à côté de l’IL, se trouve une quantité surprenante de données : des tables de chaînes .resources compilées depuis .resx, des chaînes localisées dans des assemblys satellites, des fichiers entiers que quelqu’un a choisi d’embarquer — un config, une amorce JSON, un script SQL, un certificat, une icône — et les constantes de chaîne et d’octets écrites directement dans le code. Quand vous devez atteindre ce qu’une DLL distribue en plus de ses méthodes, c’est cette matière que vous visez.

Les raisons reviennent sans cesse. Vous soupçonnez qu’un éditeur a laissé une chaîne de connexion ou un point de terminaison interne codé en dur dans une build de release, et vous voulez le confirmer. Vous avez perdu le code source d’un vieil outil et devez récupérer le config ou la ressource avec lesquels il a été compilé. Vous évaluez une dépendance et voulez voir exactement quels fichiers elle transporte. Ou vous voulez simplement lire les chaînes d’interface localisées d’une bibliothèque pour vérifier une traduction. Tout cela est dans le binaire, lisible sans le code source.

Glass.NET le lit. Il est gratuit, et strictement statique — il lit les métadonnées, l’IL et le blob de ressources et reconstruit le C#, et n’exécute jamais l’assembly qu’il inspecte. Cette distinction compte ici plus que partout ailleurs : lire une ressource embarquée, c’est lire des octets stockés dans le fichier, pas regarder le code s’exécuter. Ainsi, extraire les ressources d’un binaire que vous n’oseriez jamais exécuter est tout à fait sûr — rien en lui ne s’exécute quand vous l’ouvrez, lisez une ressource ou l’exportez.

Ce qu’il y a vraiment là-dedans

Il est utile de connaître les formes que vous rencontrerez avant de partir à la recherche :

.resourcescompilées depuis.resxtables de chaînes,valeurs UTF-8satellitechaînes localiséesfr/, de/, es/ ….resources proprepar culturefichiers embarquésconfig · JSONSQL · certsimages, blobsoctets exactsconstanteslittéraux de chaînetableaux byte[]dans l'IL,dans le C#

Les trois premières sont des ressources managées, stockées dans le manifeste de l’assembly ; la quatrième vit dans l’IL lui-même et apparaît dans le C# décompilé. Glass gère les deux, par des voies légèrement différentes.

Ouvrez l’assembly

Trouvez d’abord la DLL. Pour une dépendance NuGet, elle est dans le cache global des paquets — %USERPROFILE%\.nuget\packages\<id>\<version>\lib\<tfm>\ sous Windows, ~/.nuget/packages/... ailleurs. Pour une livraison d’éditeur ou une vieille build à vous, elle est là où elle a atterri, généralement dans bin/. Ouvrez-la dans Glass.NET en la glissant sur la fenêtre, ou Fichier ▸ Ouvrir un assembly. Une simple .dll managée suffit — sans PDB, sans code source. Et comme ouvrir et lire sont statiques, un binaire auquel vous ne faites pas confiance est sûr à ouvrir : Glass ne l’exécute jamais.

Trouvez les ressources dans l’arbre

Dépliez l’assembly et allez à son nœud de ressources — il se trouve à côté de l’arbre espaces de noms ▸ types ▸ membres. Glass liste chaque ressource embarquée que le manifeste déclare : les flux .resources compilés depuis .resx, et tout fichier brut que l’auteur a embarqué. Cette liste à elle seule est instructive. Un Strings.resources est attendu ; un appsettings.Production.json, un migrations.sql, un private.pfx ou un .bin inexpliqué est précisément ce que vous avez ouvert l’assembly pour trouver.

Sélectionnez un flux .resources et Glass affiche sa table de chaînes — les noms de ressource et leurs valeurs — vous pouvez donc lire directement les chaînes embarquées : messages d’erreur, modèles, libellés d’interface, et l’occasionnel modèle de chaîne de connexion que quelqu’un a garé dans une ressource plutôt que dans le config. Sélectionnez un fichier embarqué brut et vous pouvez inspecter son contenu sur place ; pour un fichier texte comme du JSON ou du SQL, c’est souvent tout ce qu’il faut pour le lire.

Pour les chaînes localisées, les valeurs propres à la culture ne sont pas du tout dans la DLL principale — elles sont dans des assemblys satellites, une MyApp.resources.dll sous un dossier de culture comme fr/ ou de/. Un satellite est simplement un assembly avec son propre flux .resources, alors ouvrez-le dans Glass exactement comme vous avez ouvert le principal et lisez sa table de chaînes de la même façon. C’est ainsi que vous vérifiez ce qu’une traduction donnée distribue réellement.

Lisez les constantes de chaîne et d’octets dans le code

Tout ce qui est « embarqué » n’est pas une ressource managée. Un point de terminaison codé en dur, un mot de passe par défaut, un sel de licence ou un tableau d’octets embarqué vit souvent comme constante dans le code — un littéral de chaîne ou un initialiseur byte[] dans l’IL, pas une entrée dans le blob de ressources. Celles-ci affleurent quand vous décompilez le type : cliquez sur le membre et lisez le C# reconstruit, et le littéral est là, dans le code. Pour les balayer, décompilez le type qui semble pertinent et lisez-le, ou utilisez Rechercher toutes les références (Shift+F12) sur l’API qui consomme la valeur — chaque new SqlConnection, chaque adresse de base HttpClient — pour atterrir sur chaque site d’appel et voir le littéral en contexte. C’est ainsi qu’une chaîne de connexion qu’un éditeur a « cachée » dans un const string ressort tout droit. (Comment décompiler une DLL .NET en C# couvre le flux de lecture en entier.)

Exportez vers un projet pour avoir les fichiers sur disque

Lire une ressource dans l’arbre répond à « qu’y a-t-il là-dedans ? ». Dès l’instant où vous voulez les fichiers de ressource eux-mêmes — pour ouvrir un certificat dans votre propre outillage, passer un script SQL par un vrai client, comparer un config récupéré à l’actuel, ou injecter une amorce JSON dans un test — vous les voulez écrits sur disque, hors de Glass, comme des fichiers ordinaires. C’est ce que fait l’export.

Fichier ▸ Exporter vers un projet reconstruit tout l’assembly vers un .csproj compilable, et extrait les ressources embarquées à côté du code — les .resources et les fichiers embarqués bruts sont écrits comme fichiers dans le dossier du projet. Depuis un script, le sous-commande glass export fait la même chose sans interface :

glass export Vendor.Sync.dll --output ./Vendor.Sync.Source

Maintenant les ressources sont sur disque à côté du .cs reconstruit, et vos outils habituels reviennent : ouvrez le dossier, greppez les fichiers extraits pour un secret soupçonné, chargez le certificat, exécutez le SQL. Comme l’export reste de la reconstruction statique, il n’a jamais exécuté le binaire pour produire quoi que ce soit — vous pouvez exporter une DLL non fiable et inspecter sa charge entièrement selon vos propres termes. L’analyse approfondie de l’export, y compris là où un grand assembly nécessite une courte passe manuelle, est dans transformer une DLL en un projet compilable.

La partie honnête : stocké n’est pas protégé

Tout ce qui précède fonctionne parce que le CLR ne chiffre pas les ressources embarquées. Une table de chaînes .resources est du texte UTF-8 avec préfixes de longueur ; un fichier embarqué brut est ses octets exacts ; une constante est un littéral dans l’IL. Le ResourceReader du framework lui-même et GetManifestResourceStream existent pour parcourir cela, et tout visualiseur de ressources — Glass compris — est une façade sur les mêmes données stockées. « Je l’ai embarqué dans la DLL » n’est pas la même chose que « je l’ai protégé ». Le lire est un double-clic, pas un cassage.

La conséquence pratique coupe des deux côtés. Quand vous auditez le binaire d’un autre, cela signifie que la charge est trivialement récupérable, ce qui est précisément ce qui rend un lecteur statique utile — voyez inspecter un paquet NuGet avant de lui faire confiance pour le flux d’évaluation plus large. Mais retournez l’objectif vers vos propres assemblys distribués : si vous pointez Glass vers votre build de release et trouvez une chaîne de connexion vivante, une clé d’API ou un certificat dans une ressource ou un const, c’est une anomalie, pas une curiosité. Traitez-la comme vous traiteriez toute information d’identification fuitée — faites tourner le secret et sortez-le du binaire. Distribuer un secret dans un assembly, c’est le distribuer à quiconque télécharge l’assembly.

Si vous devez vraiment transporter dans le binaire des données que vous préféreriez ne pas remettre en clair — un fichier de données sous licence, des modèles que vous jugez propriétaires — c’est là que l’obfuscateur frère Nebula.NET gagne sa place : il peut chiffrer les ressources et les chaînes embarquées à la compilation et les déchiffrer de façon transparente derrière vos appels existants à ResourceManager et GetManifestResourceStream, de sorte qu’un visualiseur de ressources voit du texte chiffré au lieu de votre SQL. L’analyse approfondie de cela est chiffrer les ressources embarquées, et le traitement équivalent pour les littéraux dans le code est le chiffrement de chaînes en .NET. C’est une protection Nebula standard — chiffrement de ressources et de chaînes, pas un niveau élevé. Mais soyez clair sur ce que cela achète : cela élève la récupération de « lire » à « faire de la rétro-ingénierie ». Cela ne rend pas sûr un secret que vous avez déjà distribué. Un secret qu’on a fait tourner est le correctif ; le chiffrement est la façon d’éviter de distribuer le prochain en clair.

L’essentiel

Une DLL distribue ses ressources aussi platement que son code. Ouvrez-la dans Glass.NET, dépliez le nœud de ressources pour lister les .resources, les chaînes satellites et les fichiers embarqués, lisez les chaînes et inspectez les fichiers sur place, décompilez les types pour attraper les constantes cuites dans l’IL, et exportez vers un projet quand vous voulez les fichiers sur disque pour les inspecter hors de l’outil. En quelques minutes, vous pouvez récupérer un config perdu, lire la charge d’une dépendance ou confirmer le point de terminaison codé en dur que vous soupçonniez — le tout sans exécuter une seule ligne, car lire une ressource stockée, c’est lire des octets, pas du comportement. Et si ce que vous trouvez est un secret dans votre propre build, vous avez trouvé le bug qui vaut la peine d’être corrigé. Téléchargez Glass.NET, ouvrez l’assembly et voyez ce qu’il transporte vraiment.

Essayez Nebula.NET

Renforcez votre code .NET en quelques minutes — commencez avec l'édition gratuite.