Skip to content
← Alle Beiträge
· Delta1 Labs Glass.NETDekompilierungLeitfaden

Eine DLL mit Glass.NET zurück in ein baubares Projekt verwandeln

Dekompiliertes C# in einem Fenster zu lesen ist eine Sache; ein .csproj zu bekommen, das Sie öffnen, greppen, refaktorieren und kompilieren können, eine andere. So rekonstruiert der Projekt-Export von Glass.NET ein ganzes Assembly — Quelle, Referenzen, Ressourcen —, was er sauber bewältigt, wo vom Compiler erzeugter Code Nachhilfe braucht, und wie Sie ihn von der CLI aus skripten.

Ein Decompiler, der Ihnen nur Code in einem Bereich zeigt, hält Sie zum Touristen. Sie können schauen, Sie können scrollen, aber Sie können nicht arbeiten. In dem Moment, in dem Sie ein Assembly nach jedem Aufruf von File.Delete greppen, einen statischen Analyzer darüber laufen lassen, einen Haltepunkt in einer lokalen Reproduktion setzen oder eine verlorene Bibliothek zurück in Form refaktorieren wollen, brauchen Sie das Ding als echtes Projekt auf der Festplatte — ein .csproj, das Ihre Toolchain versteht. Dieser Sprung, von „ein Fenster voll C#” zu „einer Lösung, die ich öffnen kann”, ist das, wofür der Projekt-Export von Glass.NET da ist.

Dieser Beitrag ist ein praxisnaher Tiefgang zu diesem Export: was Glass rekonstruiert, wie man ihn sowohl aus der Oberfläche als auch aus der CLI steuert, was sauber kompiliert, wo die ehrlichen Grenzen der Dekompilierung auftauchen und wie man die Lücke schließt.

Von einem schreibgeschützten Bereich zu einem Projekt auf der Festplatte

Öffnen Sie ein Assembly in Glass und Sie bekommen dekompiliertes C#, Navigation und eine Assembly-Informationsansicht — alles, was Sie zum Lesen brauchen. Der Export verwandelt diese Rekonstruktion in Dateien:

MyLib.dllMetadaten + ILGlass.NETICSharpCode.DecompilerC# rekonstruieren./MyLib.Source/MyLib.csproj*.cs (rekonstruiert)Resources/ (extrahiert)baubares Projekt

Ein Projekt, kein Abladen: Das .csproj trägt das Zielframework und die Assembly-Referenzen, die Glass aus den Metadaten gelesen hat, die Namespaces werden zu einer sinnvollen Datei-/Ordnerstruktur, und eingebettete Ressourcen werden daneben extrahiert. Öffnen Sie den Ordner in einer beliebigen IDE, und Ihre normalen Werkzeuge — Suche, Gehe-zu-Definition, Analyzer, der Compiler — liegen wieder auf dem Tisch.

Die zwei Wege zu exportieren

Aus der Oberfläche laden Sie das Assembly und wählen File ▸ Export to Project. Glass schreibt das .csproj und die rekonstruierten .cs-Dateien (plus extrahierte Ressourcen) in den von Ihnen gewählten Ordner. Das ist der richtige Weg beim Erkunden: Sie haben durch das Assembly navigiert, Sie wissen, dass es das gesuchte ist, und Sie möchten es in Ihrem Editor haben.

Aus der CLI macht der Unterbefehl glass export dasselbe kopflos, was Sie in einem Skript, einem Stapel über viele Dateien oder einer Analyse-Pipeline wollen:

glass export MyLibrary.dll --output ./MyLibrary.Source

Das schreibt ein baubares Projekt unter ./MyLibrary.Source. Und weil es ein einfacher Befehl ist, können Sie ihn auffächern — stellen Sie einen Ordner verwaister Assemblys in einem Durchgang wieder her:

for dll in ./legacy-bin/*.dll; do
  name=$(basename "$dll" .dll)
  glass export "$dll" --output "./recovered/$name"
done

Und weil Glass das Assembly nie ausführt — es ist streng statische Analyse über Metadaten und IL — ist das Exportieren eines nicht vertrauenswürdigen oder verdächtigen Binaries sicher. Sie bekommen die Quelle auf der Festplatte zum Greppen, ohne dass das Binary je ausgeführt wird — genau die Situation, in der Sie sie am ehesten wollen: etwas zu auditieren, dem Sie nicht genug trauen, um es auszuführen.

Was sauber zurückkommt

Für eine breite Klasse echter Assemblys kompiliert der Export mit wenig oder keinem Aufwand, weil die moderne Dekompilier-Engine die Konstrukte bewältigt, die früher Müll erzeugten:

  • Gewöhnliche Geschäftslogik — Klassen, Schnittstellen, Generics, Properties, Events, LINQ — wird getreu rekonstruiert.
  • Modernes C#, das die Engine versteht — async/await-Zustandsmaschinen, Iterator-(yield-)Blöcke, Pattern Matching und Switch-Ausdrücke, Records, Lambdas und Closures — kommt als das High-Level-Konstrukt zurück, nicht als die rohe erzeugte Verrohrung. Die Engine erkennt das Lowering des Compilers und kehrt es um.
  • Referenzen und Framework-Targeting werden ins .csproj übernommen, sodass das Projekt weiß, wogegen es baut.
  • Eingebettete Ressourcen werden herausgeschrieben und verdrahtet, sodass eine Bibliothek, die .resx-gestützte Strings oder Binär-Blobs ausliefert, sie behält.

Für eine kleine Hilfsbibliothek oder ein einzelnes Assembly, dessen Quelle Sie verloren haben, funktioniert „exportieren, öffnen, bauen” häufig einfach.

Wo die ehrlichen Grenzen der Dekompilierung auftauchen

Export ist Rekonstruktion, keine Zeitreise, und es lohnt sich, offen darüber zu sein, was IL erhält und was nicht. Die IL kodiert Verhalten exakt; sie kodiert nicht jedes Detail auf Quellebene, also werden einige Dinge rekonstruiert statt wiederhergestellt:

  • Namen lokaler Variablen sind meist weg (IL identifiziert Locals per Slot, nicht per Name), also sehen Sie rekonstruierte Namen. Felder, Methoden, Typen und Parameter behalten ihre Namen, sofern das Assembly nicht obfuskiert war.
  • Manche vom Compiler erzeugten Konstrukte rekonstruieren sich als gültiges-aber-unschönes C#, und das gelegentliche exotische Muster wird ohne ein Anstupsen nicht zu kompilierbarer Quelle zurückkehren.
  • unsafe-Code, P/Invoke-Signaturen und bestimmte Interop können erfordern, dass AllowUnsafeBlocks des Projekts eingeschaltet wird, oder ein manuelles Aufräumen.
  • Fehlende Referenzen — wenn das Assembly von etwas abhängt, das Sie nicht haben, kann der Export die Aufrufstellen rekonstruieren, aber die Abhängigkeit nicht herbeizaubern; Sie liefern sie, bevor der Build grün wird.
  • Obfuskierte Eingabe ist der schwierigste Fall: Wenn Namen von einem Obfuskator verstümmelt wurden, gibt Glass die verstümmelten Namen getreu wieder — es dekompiliert, was da ist, es ent-obfuskiert nicht.

Die realistische Erwartung für ein großes oder ungewöhnliches Assembly lautet also: Glass verschafft Ihnen ein Projekt und den Großteil der Quelle; die letzte Handvoll Kompilierfehler zu schließen ist ein kurzer, gezielter manueller Durchgang. Das ist trotzdem eine Verwandlung — von „ich kann das nur in einem Betrachter ansehen” zu „ich habe ein Projekt, an dem meine ganze Toolchain arbeiten kann”.

Warum ein Projekt einen Bereich schlägt

Sobald das Assembly ein .csproj ist, kommt alles zurück, was Sie ohnehin zu tun wissen:

  • Grep und statische Analyse. Durchsuchen Sie die rekonstruierte Quelle nach den APIs, die zählen — jedes Process.Start, jeden Reflection-Aufruf, jede Netzwerk-Senke — und richten Sie Roslyn-Analyzer oder Ihre eigenen Regeln darauf. Das ist das Rückgrat beim Auditieren einer Abhängigkeit, bei der Sie sich unsicher sind: exportieren, dann systematisch die Teile lesen, die Schaden anrichten können.
  • Eine lokale Reproduktion. Eine Bibliothek wiederhergestellt, deren Quelle verloren war? Das exportierte Projekt lässt Sie sie bauen, referenzieren und — wo die Referenzen sich auflösen — eine Reproduktion debuggen, statt aus einem Stacktrace zu raten.
  • Zwischen Versionen diffen. Exportieren Sie zwei Builds desselben Assemblys und diffen Sie die Bäume, um genau zu sehen, was sich zwischen den Releases geändert hat — praktisch, wenn ein Abhängigkeits-Upgrade Sie zerbrochen hat und der Changelog es nicht erklärte. (Glass bietet für die schnelle Variante auch einen In-App-Assembly-Vergleich mit einem Zeilen-Diff.)
  • Zurück in einen wartbaren Zustand refaktorieren. Für wirklich verlorenen Code ist ein exportiertes Projekt der Ausgangspunkt, um die rekonstruierten Locals umzubenennen, XML-Docs wieder hinzuzufügen und eine tote Bibliothek wiederzubeleben.

Wo es hineinpasst

Der Projekt-Export ist der Schritt, der Glass.NET von einem Betrachter in eine Werkbank verwandelt. Lesen Sie ein Assembly mit dem Navigationsmodell, bestätigen Sie mit der Assembly-Informationsansicht, dass es das gesuchte ist, dann File ▸ Export to Project — oder skripten Sie glass export MyLibrary.dll --output ./src — um ein .csproj zu bekommen, das Ihre Toolchain versteht. Erwarten Sie einen sauberen Build bei unkomplizierten Assemblys und einen kurzen manuellen Durchgang bei großen oder ungewöhnlichen; erwarten Sie die Quelle in jedem Fall auf der Festplatte, ohne das Binary je auszuführen. Siehe die Leitfäden Erste Schritte und Navigation für den Lesefluss, der zu einem Export führt, oder die Glass.NET-Produktseite für das gesamte Werkzeugset. Es ist kostenlos — keine Lizenz, keine Plätze, keine Anmeldung.

Nebula.NET testen

Härten Sie Ihren .NET-Code in wenigen Minuten — starten Sie mit der kostenlosen Edition.