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

Voyez de quoi dépend un assembly .NET et ce qu'il appelle avec Glass.NET

Avant de distribuer une DLL tierce, vous voulez connaître sa surface externe : quels assemblys et paquets elle référence, pour quel framework elle est compilée, quelles bibliothèques natives elle appelle par P/Invoke, et où elle se connecte au réseau, au système de fichiers ou à un autre processus. Voici comment auditer tout cela de façon statique dans Glass.NET — le décompilateur gratuit qui lit le binaire et ne l'exécute jamais.

Vous êtes sur le point de distribuer une DLL tierce dans votre propre produit, et vous voulez trancher une chose d’abord : vers quoi se connecte-t-elle vraiment ? Pas ce que prétend le README — ce à quoi le binaire est câblé. Quels autres assemblys et paquets elle embarque, pour quel framework elle s’attend à s’exécuter, si elle appelle du code natif, et si elle ouvre un socket, écrit un fichier ou lance un processus quelque part dans son corps. C’est la surface externe d’une dépendance, et c’est précisément ce que vous ne pouvez pas voir depuis la page du paquet.

Vous pouvez tout voir sans exécuter la DLL. Un assembly .NET compilé enregistre ses dépendances et ses appels dans les métadonnées et l’IL, et Glass.NET lit cela et reconstruit du C# lisible. Il est gratuit, et strictement statique — il lit les métadonnées et l’IL et reconstruit le C#, et n’exécute jamais l’assembly qu’il inspecte. C’est toute la raison pour laquelle c’est sûr : auditer une dépendance dont vous n’êtes pas sûr consiste à la lire, pas à l’exécuter, et lire est la seule chose que Glass fait.

Rendons cela concret. Supposons que vous évaluez Contoso.ImageKit — un paquet NuGet qui redimensionne des images — avant de l’ajouter à un service qui gère les téléversements de clients. Une bibliothèque d’images pure devrait référencer une pile d’imagerie et rien d’alarmant, cibler un framework que vous pouvez exécuter et s’en tenir aux pixels. Si elle référence System.Net.Http, appelle par P/Invoke un codec natif que vous n’attendiez pas, ou cache un Process.Start dans un coin, vous voulez le savoir avant de la distribuer, pas après. Voici le flux.

Ouvrez-la et lisez d’abord les informations sur l’assembly

Trouvez 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 elle est là où elle a atterri, en général dans bin/. Ouvrez-la dans Glass.NET en la glissant sur la fenêtre, ou Fichier ▸ Ouvrir l’assembly. Une simple .dll managée suffit — sans PDB, sans code source, sans restauration.

Avant de lire une ligne de code, ouvrez la vue d’informations sur l’assembly. C’est là que commence la surface externe, et elle répond à deux questions aussitôt :

  • Que cible-t-elle ? La vue affiche le framework cible et les attributs de produit. Une référence compilée contre un framework que vous n’exécutez pas — un assembly uniquement net48 qui atterrit dans un service net8.0 sans build compatible dans le paquet — est une incompatibilité que vous voulez attraper ici, au moment de l’audit, et non comme un échec de chargement en production. Le framework cible est un fait enregistré dans l’assembly, c’est donc la réponse faisant autorité, pas une supposition d’après le nom du paquet.
  • Que référence-t-elle ? La vue liste les assemblys référencés — le jeu de dépendances directes contre lequel le binaire a été compilé. Pour une bibliothèque d’images vous attendez une pile d’imagerie et les bibliothèques de base. Si System.Net.Http, System.Net.Sockets ou System.Diagnostics.Process apparaissent dans cette liste, une bibliothèque qui prétend ne toucher que des pixels vient de vous dire qu’elle est liée au réseau ou à l’API de processus, et vous l’avez appris avant de lire le moindre code.

Le rapport d’exposition de Glass est un bon compagnon ici. Lancez-le pour jauger la lisibilité de l’assembly. Un paquet de style open source ordinaire devrait se lire clairement ; si un auxiliaire d’image quelconque revient fortement obscurci, ce décalage mérite en soi d’être questionné — les bibliothèques utilitaires légitimes ont rarement besoin de se cacher. (C’est la vue depuis l’autre côté de l’obfuscateur frère Nebula.NET, dont la virtualisation de code est une fonction Pro — mais une dépendance ordinaire n’a aucune raison de ressembler à cela.)

Parcourez les références et l’arbre des types

La liste des assemblys référencés vous dit contre quoi le binaire se lie ; l’arbre vous dit quelle part de tout cela vous devez surveiller. Dépliez l’assembly dans son nœud de références et son arbre espaces de noms ▸ types ▸ membres. Le nœud des références est le même jeu de dépendances sous forme navigable — et dans Glass vous pouvez poursuivre, en ouvrant un assembly référencé pour inspecter à son tour sa surface, ce qui vous permet de suivre une dépendance-d’une-dépendance que la page du paquet n’a jamais mentionnée.

L’arbre des types vous donne la forme du code lui-même : trois types bien rangés ou un fouillis d’une centaine, une petite API publique sur une poignée d’auxiliaires internes ou quelque chose de bien plus affairé qu’un redimensionneur ne devrait avoir besoin. Vous lisez ici pour la proportion — la surface correspond-elle au travail annoncé ?

Trouvez les sites d’appel qui se connectent vers l’extérieur

Maintenant le vrai audit : où le code appelle-t-il hors de lui-même ? C’est là qu’un décompilateur axé sur la navigation transforme une liste de contrôle en quelques sauts plutôt qu’en un défilement.

La méthode est la même pour chaque capacité qui vous importe : trouvez l’API, puis utilisez Rechercher toutes les références (Maj+F12) pour lister chaque site d’appel, se déversant dans le panneau de résultats, et lisez la méthode autour de chacun.

  • Réseau. Cherchez HttpClient, WebClient, les Socket/TcpClient bruts, et toute URL ou adresse codée en dur. Pourquoi un redimensionneur ouvrirait-il un socket ? Rechercher toutes les références sur le constructeur ou SendAsync vous montre chaque endroit où cela se produit et vous laisse lire le code environnant.
  • Lancements de processus. Process.Start, ou tout ce qui exécute en ligne de commande cmd, powershell ou un binaire embarqué. Une bibliothèque pure a rarement besoin de lancer quoi que ce soit.
  • Système de fichiers. File, FileStream, Directory — lectures et écritures au-delà du scratch temporaire dont un redimensionneur a légitimement besoin, en particulier les lectures de chemins qui ressemblent à des identifiants ou à de la configuration.
  • Bibliothèques natives. C’est la surface de P/Invoke. Une méthode [DllImport] ou [LibraryImport] générée par la source nomme le module natif auquel elle se lie là, dans l’attribut, elle se décompile donc proprement et la dépendance native est visible dans le code. Une bibliothèque d’images liant un codec natif peut être tout à fait attendue — mais un [DllImport("kernel32")] inattendu faisant du travail de processus ou de mémoire est exactement le genre de chose que vous auditez pour l’attraper. Pour la terminologie et pourquoi le nom du point d’entrée est critique, voyez obscurcir P/Invoke et DllImport sans casser l’interopérabilité.

Utilisez Atteindre tout (Ctrl+T) pour sauter vers un type ou un membre par son nom, et Atteindre la définition (F12) pour suivre un appel jusqu’à l’auxiliaire qui fait le vrai travail. La hiérarchie des appels répond à la question qui compte le plus pour un audit : est-ce atteignable depuis l’API que j’utilise réellement, ou est-ce du code mort ? Un Process.Start qu’aucun de vos chemins d’appel n’atteint est une tout autre trouvaille qu’un que votre première méthode touche.

Une chose à garder claire : trouver un appel à HttpClient ou Process.Start est une preuve statique que l’appel existe dans le code et est atteignable. Ce n’est pas Glass qui regarde une requête partir — Glass n’exécute jamais l’assembly. Cette distinction est précisément pourquoi c’est sûr de le faire sur une dépendance à laquelle vous ne faites pas confiance : vous lisez le câblage, vous ne le mettez pas sous tension. La même discipline sous-tend analyser en toute sécurité un assembly .NET suspect et inspecter un paquet NuGet avant de lui faire confiance.

Descendez à l’IL où vous avez besoin de certitude

La plupart du temps, le C# décompilé à un site d’appel est assez clair pour juger. Parfois non — un appel routé par réflexion, ou une méthode obscurcie où la reconstruction du C# est irrégulière. Quand la vue de haut niveau arrondit un détail qui compte, basculez le même membre sur la vue IL. L’IL est ce qui s’exécute réellement, c’est donc la vérité de terrain, et il reste lisible même là où le C# propre ne se reconstruit pas. (Lire l’IL détaille ce que vous regardez.) Vous n’avez pas besoin d’y vivre — recourez-y sur la poignée de sites d’appel où vous devez être sûr de ce que le code atteint.

L’essentiel

La surface externe d’une dépendance n’est pas cachée — elle est enregistrée dans le binaire, et un lecteur statique la révèle entièrement. Ouvrez la DLL, lisez les informations sur l’assembly pour son framework cible et ses assemblys référencés, parcourez les références et l’arbre des types pour la proportion, et utilisez Rechercher toutes les références pour atterrir sur chaque site d’appel réseau, fichier, processus et P/Invoke afin de juger chacun en contexte. En quelques minutes vous pouvez confirmer que Contoso.ImageKit ne parle qu’à ce qu’une bibliothèque d’images devrait — ou trouver le seul appel qui prouve le contraire. Et comme Glass.NET est gratuit et strictement statique, vous avez fait tout l’audit sans exécuter une seule ligne d’une dépendance à laquelle vous n’aviez pas encore décidé de faire confiance. Pour le flux complémentaire consistant à lire ce que le code fait, voyez comprendre du code .NET tiers inconnu. Téléchargez Glass.NET, ouvrez la DLL que vous êtes sur le point de distribuer, et voyez vers quoi elle tend la main.

Essayez Nebula.NET

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