Sehen Sie mit Glass.NET, wovon ein .NET-Assembly abhängt und was es aufruft
Bevor Sie eine fremde DLL ausliefern, wollen Sie ihre externe Oberfläche kennen: welche Assemblys und Pakete sie referenziert, für welches Framework sie kompiliert ist, welche nativen Bibliotheken sie per P/Invoke aufruft und wo sie ins Netzwerk, ins Dateisystem oder zu einem anderen Prozess greift. So prüfen Sie all das statisch in Glass.NET — dem kostenlosen Decompiler, der die Binärdatei liest und nie ausführt.
Sie sind im Begriff, eine fremde DLL in Ihrem eigenen Produkt auszuliefern, und wollen zuerst eines klären: Wonach greift sie eigentlich? Nicht das, was die README behauptet — das, wofür die Binärdatei verdrahtet ist. Welche anderen Assemblys und Pakete sie einschleppt, für welches Framework sie zu laufen erwartet, ob sie nativen Code aufruft und ob sie irgendwo in ihrem Rumpf einen Socket öffnet, eine Datei schreibt oder einen Prozess startet. Das ist die externe Oberfläche einer Abhängigkeit, und genau das sehen Sie auf der Paketseite nicht.
Sie können all das sehen, ohne die DLL auszuführen. Ein kompiliertes .NET-Assembly zeichnet seine Abhängigkeiten und seine Aufrufe in Metadaten und IL auf, und Glass.NET liest das und rekonstruiert lesbares C#. Es ist kostenlos und streng statisch — es liest Metadaten und IL und rekonstruiert C#, und führt das inspizierte Assembly nie aus. Das ist der ganze Grund, warum das sicher ist: eine Abhängigkeit zu prüfen, bei der Sie unsicher sind, heißt sie zu lesen, nicht sie auszuführen, und Lesen ist alles, was Glass je tut.
Machen wir es konkret. Angenommen, Sie bewerten Contoso.ImageKit — ein NuGet-Paket, das Bilder skaliert — bevor Sie es einem Dienst hinzufügen, der Kunden-Uploads verarbeitet. Eine reine Bildbibliothek sollte einen Imaging-Stack und nichts Alarmierendes referenzieren, auf ein Framework zielen, das Sie ausführen können, und bei Pixeln bleiben. Wenn sie System.Net.Http referenziert, per P/Invoke einen nativen Codec aufruft, den Sie nicht erwartet haben, oder ein Process.Start in einer Ecke versteckt, wollen Sie das vor dem Ausliefern wissen, nicht danach. Hier ist der Ablauf.
Öffnen Sie sie und lesen Sie zuerst die Assembly-Informationen
Finden Sie die DLL. Für eine NuGet-Abhängigkeit liegt sie im globalen Paket-Cache — %USERPROFILE%\.nuget\packages\<id>\<version>\lib\<tfm>\ unter Windows, ~/.nuget/packages/... sonst. Für eine Anbieterlieferung liegt sie dort, wo sie gelandet ist, meist in bin/. Öffnen Sie sie in Glass.NET, indem Sie sie auf das Fenster ziehen, oder Datei ▸ Assembly öffnen. Eine schlichte verwaltete .dll genügt — ohne PDB, ohne Quellcode, ohne Restore.
Bevor Sie eine Zeile Code lesen, öffnen Sie die Assembly-Informationsansicht. Hier beginnt die externe Oberfläche, und sie beantwortet sofort zwei Fragen:
- Worauf zielt sie? Die Ansicht zeigt das Zielframework und die Produktattribute. Eine Referenz, die gegen ein Framework kompiliert wurde, das Sie nicht ausführen — ein reines
net48-Assembly, das in einennet8.0-Dienst fällt, ohne kompatiblen Build im Paket — ist eine Inkompatibilität, die Sie hier, zur Prüfzeit, abfangen wollen, nicht als Ladefehler in der Produktion. Das Zielframework ist eine im Assembly aufgezeichnete Tatsache, also die maßgebliche Antwort, keine Vermutung aus dem Paketnamen. - Was referenziert sie? Die Ansicht listet die referenzierten Assemblys — den Satz direkter Abhängigkeiten, gegen den die Binärdatei gebaut wurde. Für eine Bildbibliothek erwarten Sie einen Imaging-Stack und die Basisklassenbibliotheken. Tauchen
System.Net.Http,System.Net.SocketsoderSystem.Diagnostics.Processin dieser Liste auf, hat Ihnen eine Bibliothek, die behauptet, nur Pixel anzufassen, gerade verraten, dass sie gegen das Netzwerk oder die Prozess-API gelinkt ist — und Sie haben es erfahren, bevor Sie Code gelesen haben.
Der Expositionsbericht von Glass ist hier ein guter Begleiter. Lassen Sie ihn laufen, um abzuschätzen, wie lesbar das Assembly ist. Ein gewöhnliches Paket im Open-Source-Stil sollte sich klar lesen; kehrt ein unauffälliger Bild-Helfer stark obfuskiert zurück, ist dieses Missverhältnis selbst eine Frage wert — legitime Hilfsbibliotheken müssen sich selten verstecken. (Das ist der Blick von der anderen Seite des Schwester-Obfuskators Nebula.NET, dessen Code-Virtualisierung eine Pro-Funktion ist — aber eine gewöhnliche Abhängigkeit hat keinen Grund, so auszusehen.)
Durchstöbern Sie die Verweise und den Typbaum
Die Liste der referenzierten Assemblys sagt Ihnen, wogegen die Binärdatei linkt; der Baum sagt Ihnen, wie viel davon Ihre Sorge ist. Klappen Sie das Assembly in seinen Verweise-Knoten und seinen Baum Namespaces ▸ Typen ▸ Member auf. Der Verweise-Knoten ist derselbe Abhängigkeitssatz in durchstöberbarer Form — und in Glass können Sie weitergehen und ein referenziertes Assembly öffnen, um wiederum dessen Oberfläche zu inspizieren, und so eine Abhängigkeit-einer-Abhängigkeit verfolgen, die die Paketseite nie erwähnt hat.
Der Typbaum gibt Ihnen die Form des Codes selbst: drei ordentliche Typen oder ein Wust von hundert, eine kleine öffentliche API über einer Handvoll interner Helfer oder etwas weit Betriebsameres, als ein Skalierer brauchen sollte. Sie lesen hier auf Verhältnismäßigkeit — passt die Oberfläche zur angegebenen Aufgabe?
Finden Sie die Aufrufstellen, die nach außen greifen
Nun die eigentliche Prüfung: Wo ruft der Code aus sich selbst heraus? Hier verwandelt ein navigationsorientierter Decompiler eine Checkliste in ein paar Sprünge statt in ein Scrollen.
Die Methode ist für jede Fähigkeit, die Sie interessiert, dieselbe: Finden Sie die API, und nutzen Sie dann Alle Verweise suchen (Umschalt+F12), um jede Aufrufstelle aufzulisten, die ins Ergebnisfenster strömt, und lesen Sie die Methode um jede herum.
- Netzwerk. Suchen Sie nach
HttpClient,WebClient, rohenSocket/TcpClientund jeder fest codierten URL oder Adresse. Warum sollte ein Skalierer einen Socket öffnen? Alle Verweise suchen auf dem Konstruktor oderSendAsynczeigt Ihnen jede Stelle, an der es passiert, und lässt Sie den umgebenden Code lesen. - Prozessstarts.
Process.Startoder alles, wascmd,powershelloder eine mitgelieferte Binärdatei über die Kommandozeile aufruft. Eine reine Bibliothek muss selten etwas starten. - Dateisystem.
File,FileStream,Directory— Lese- und Schreibzugriffe jenseits des temporären Scratch, den ein Skalierer legitim braucht, besonders Lesezugriffe auf Pfade, die wie Anmeldedaten oder Konfiguration aussehen. - Native Bibliotheken. Das ist die P/Invoke-Oberfläche. Eine
[DllImport]- oder quellgenerierte[LibraryImport]-Methode nennt das native Modul, an das sie bindet, genau dort im Attribut, dekompiliert also sauber, und die native Abhängigkeit ist im Code sichtbar. Eine Bildbibliothek, die einen nativen Codec bindet, kann völlig erwartbar sein — aber ein unerwartetes[DllImport("kernel32")], das Prozess- oder Speicherarbeit leistet, ist genau die Art Sache, auf die Sie prüfen, um sie abzufangen. Zur Terminologie und warum der Name des Einstiegspunkts kritisch ist, siehe P/Invoke und DllImport obfuskieren, ohne die Interop zu brechen.
Nutzen Sie Gehe zu allem (Strg+T), um per Name zu einem Typ oder Member zu springen, und Gehe zu Definition (F12), um einem Aufruf in den Helfer zu folgen, der die eigentliche Arbeit macht. Die Aufrufhierarchie beantwortet die für eine Prüfung wichtigste Frage: Ist das von der API erreichbar, die ich tatsächlich nutze, oder ist es toter Code? Ein Process.Start, das kein Pfad Ihres Aufrufwegs erreicht, ist ein ganz anderer Befund als eines, das Ihre erste Methode trifft.
Eines sollten Sie klar halten: einen Aufruf von HttpClient oder Process.Start zu finden ist statischer Beleg, dass der Aufruf im Code existiert und erreichbar ist. Es ist nicht Glass, das eine Anfrage hinausgehen sieht — Glass führt das Assembly nie aus. Genau diese Unterscheidung macht es sicher, das an einer Abhängigkeit zu tun, der Sie nicht vertrauen: Sie lesen die Verdrahtung, Sie setzen sie nicht unter Strom. Dieselbe Disziplin trägt ein verdächtiges .NET-Assembly sicher analysieren und ein NuGet-Paket prüfen, bevor Sie ihm vertrauen.
Steigen Sie zur IL hinab, wo Sie Gewissheit brauchen
Meist ist das dekompilierte C# an einer Aufrufstelle klar genug, um zu urteilen. Gelegentlich nicht — ein Aufruf, der über Reflexion geleitet wird, oder eine obfuskierte Methode, bei der die C#-Rekonstruktion lückenhaft ist. Wenn die übergeordnete Ansicht ein Detail abrundet, auf das es ankommt, schalten Sie denselben Member auf die IL-Ansicht. Die IL ist das, was tatsächlich läuft, also die Grundwahrheit, und sie bleibt lesbar, selbst wo sauberes C# nicht rekonstruiert. (IL lesen führt durch das, was Sie dort sehen.) Sie müssen nicht dort wohnen — greifen Sie an der Handvoll Aufrufstellen danach, an denen Sie sicher sein müssen, wonach der Code greift.
Der Punkt
Die externe Oberfläche einer Abhängigkeit ist nicht verborgen — sie ist in der Binärdatei aufgezeichnet, und ein statischer Leser bringt sie vollständig ans Licht. Öffnen Sie die DLL, lesen Sie die Assembly-Informationen für ihr Zielframework und ihre referenzierten Assemblys, durchstöbern Sie Verweise und Typbaum auf Verhältnismäßigkeit, und nutzen Sie Alle Verweise suchen, um auf jeder Netzwerk-, Datei-, Prozess- und P/Invoke-Aufrufstelle zu landen und jede im Kontext zu beurteilen. In wenigen Minuten können Sie bestätigen, dass Contoso.ImageKit nur mit dem spricht, womit eine Bildbibliothek sprechen sollte — oder den einen Aufruf finden, der das Gegenteil bedeutet. Und weil Glass.NET kostenlos und streng statisch ist, haben Sie die ganze Prüfung durchgeführt, ohne eine einzige Zeile einer Abhängigkeit auszuführen, der zu vertrauen Sie noch nicht entschieden hatten. Für den ergänzenden Ablauf, zu lesen, was der Code tut, siehe unbekannten .NET-Fremdcode verstehen. Laden Sie Glass.NET herunter, öffnen Sie die DLL, die Sie ausliefern wollen, und sehen Sie, wonach sie greift.
Nebula.NET testen
Härten Sie Ihren .NET-Code in wenigen Minuten — starten Sie mit der kostenlosen Edition.