
Ghidra-Skripte zum Wiederherstellen von String-Definitionen in Go-Binärdateien
Skripte zum Wiederherstellen von String-Definitionen in Go-Binaries mit P-Code-Analyse. Getestet mit x86, x86-64, ARM und ARM64.
Diese finden Sie in der Kategorie Golang im Skript-Manager.
GoDynamicStrings.java
GoFuncCallStrings.java
GoStaticStrings.java
GoKnownStrings.java
data/known_strings.json geladen.GoStringFiller.java
go.string.* auf, basierend auf der aufsteigenden Längenreihenfolge der String-Daten.Es gibt außerdem ein paar spezielle Varianten des Skripts zur dynamischen String-Analyse:
GoDynamicStringsSingle.java
GoDynamicStrings.java durch, verwendet jedoch einen einzelnen Dekompilierungsprozess. Verwenden Sie dies, wenn die Analyse einer Binärdatei dazu führt, dass die parallelen Dekompilierungsprozesse den Systemspeicher erschöpfen.GoDynamicStringsHigh.java
Dieses finden Sie in der Kategorie PCode im Skript-Manager.
PrintHighPCode.java
Hier ist der allgemeine Ablauf für die Verwendung dieser Skripte, um String-Definitionen in einer Go-Binary wiederherzustellen:
.rodata, .rdata oder __rodata auszuwählen. Klicken Sie dann in der Code-Listing mit der rechten Maustaste und wählen Sie „Clear Code Bytes“.GoKnownStrings.java aus, um einige Standard-Strings zu erkennen.GoStaticStrings.java aus.GoFuncCallStrings.java aus (falls die Golang-Binärversion von Ghidras integrierten Golang-Funktionen unterstützt wird).GoDynamicStrings.java aus.GoStringFiller.java aus.
go.string.* beim ersten Ein-Byte-String.In Ghidra:
Für Eclipse mit dem GhidraDev-Plugin:
Mit Eclipse erstellen:
Direkt mit Gradle erstellen:
$ cd Ghostrings
$ gradle -PGHIDRA_INSTALL_DIR=<ghidra_install_dir>
Ein bekanntes Problem beim Reverse Engineering von Go-Programmen ist, dass das Fehlen von Nullterminatoren in Go-Strings die Wiederherstellung von String-Definitionen aus kompilierten Binaries erschwert. Viele der konstanten String-Werte eines Go-Programms werden zusammen in einem einzigen großen Block im kompilierten Build gespeichert, ohne dass in den String-Daten Terminatorzeichen eingebaut sind, die markieren, wo ein String endet und ein anderer beginnt. Selbst ein einfaches Programm, das nur „Hello world!“ ausgibt, enthält über 1.500 Strings, die mit dem Go-Laufzeitsystem und anderen Standardbibliotheken zusammenhängen. Dies kann dazu führen, dass typische ASCII-String-Erkennungsimplementierungen, wie die von Ghidra, falsch-positive String-Definitionen erzeugen, die zehntausende von Zeichen lang sind.
Anstelle von nullterminierten Strings verwendet Go eine String-Struktur, die aus einem Zeiger und einem Längenwert besteht. Viele dieser String-Strukturen werden zur Laufzeit auf dem Stack des Programms erstellt, daher erfordert die Wiederherstellung einzelner String-Startpositionen und Längenwerte die Analyse des kompilierten Maschinencodes. Es gibt einige vorhandene Skripte, die diese Analyse durchführen, indem sie nach bestimmten Mustern von x86-64-Anweisungen suchen, aber sie übersehen Strukturen, die mit nicht behandelten Anweisungsvarianten erstellt wurden, die letztlich denselben Effekt auf den Stack haben, und sie sind außerdem auf eine bestimmte ISA beschränkt.
Ghostrings umgeht beide Probleme, indem es mit den vereinfachten, architekturunabhängigen P-Code-Operationen arbeitet, die von Ghidras Dekompilierer-Analyse erzeugt werden.
Copyright 2022 NCC Group. Veröffentlicht unter der GPLv3-Lizenz (siehe LICENSE).
Hauptautor des Projekts: James Chambers [email protected]
go.string.* und definieren Sie alle Strings mit offensichtlichen Start- und Endpunkten.
GoStringFiller.java optimal zu nutzen, identifizieren Sie, wo sich die String-Längen in undefinierten String-Daten ändern, und definieren Sie die Strings, die dieser Grenze am nächsten liegen. Führen Sie dann GoStringFiller.java erneut aus, um Stellen automatisch aufzufüllen, an denen die Länge der verbleibenden undefinierten Strings korrekt bestimmt werden kann.