
Polymorpher Verschlüsseler, der Shellcode, PE- und COFF-Dateien in verschleierte, positionsunabhängige Payloads mit RC4- und zufälliger Blockchiffre-Verschlüsselung sowie der Erzeugung von Müll-Instruktionen unter Verwendung der AsmJit-Bibliothek umwandelt.
Vorgestellt auf
Shoggoth ist ein Open-Source-Projekt, das auf C++ und der asmjit-Bibliothek basiert und verwendet wird, um übergebene Shellcode-, PE- und COFF-Dateien polymorph zu verschlüsseln.
Shoggoth generiert eine Ausgabedatei, die die Nutzlast und den zugehörigen Loader in einer obfuskierten Form speichert. Da der Inhalt der Ausgabe positionsunabhängig ist, kann er direkt als Shellcode ausgeführt werden. Während der Ausführung entschlüsselt sich die Nutzlast selbst zur Laufzeit. Zusätzlich zur Verschlüsselungsroutine fügt Shoggoth zwischen den Routinen nutzlose Anweisungen (Garbage-Instructions) ein, die nichts bewirken.
Ich begann mit der Entwicklung dieses Projekts, um verschiedene Ansätze zur dynamischen Anweisungsgenerierung, Assembly-Praktiken und Signaturerkennung zu untersuchen. Ich plane, das Repository regelmäßig mit meinen neuen Erkenntnissen zu aktualisieren.
Die aktuellen Funktionen sind unten aufgeführt:
Der allgemeine Ausführungsablauf von Shoggoth für eine Eingabedatei ist im folgenden Bild dargestellt. Sie können diesen Ablauf mit den Standardkonfigurationen beobachten.
Grundsätzlich kombiniert Shoggoth zunächst den vorkompilierten Loader-Shellcode entsprechend des gewählten Modus (COFF- oder PE-Datei) mit der Eingabedatei. Anschließend fügt es mehrere selbst erstellte nutzlose Anweisungen zu dieser kombinierten Nutzlast hinzu. Der Stub, der den Loader, die nutzlosen Anweisungen und die Nutzlast enthält, wird zuerst mit RC4-Verschlüsselung und dann mit einer zufällig generierten Blockverschlüsselung verschlüsselt, indem die entsprechenden Entschlüsselungsroutinen kombiniert werden. Schließlich wird dem resultierenden Block eine nutzlose Anweisung hinzugefügt.
Während Shoggoth zufällig Anweisungen für nutzlose Stubs oder Verschlüsselungsroutinen generiert, verwendet es die AsmJit-Bibliothek.
AsmJit ist eine leichte Bibliothek zur Generierung von Maschinencode, geschrieben in C++. Sie kann Maschinencode für die Architekturen X86, X86_64 und AArch64 generieren und unterstützt Basisbefehle sowie alle aktuellen Erweiterungen. AsmJit ermöglicht die Angabe von Operationscodes, Registern, unmittelbaren Operanden, Aufrufmarken und das Einbetten beliebiger Werte an beliebigen Positionen im Code. Bei der Generierung von Assembly-Anweisungen mit AsmJit reicht es aus, die API-Funktion aufzurufen, die der gewünschten Assembly-Operation mit Operanden aus der Assembler-Klasse entspricht. Für jeden API-Aufruf speichert AsmJit Code- und Relokationsinformationen in seiner internen CodeHolder-Struktur. Nach dem Aufruf der API-Funktionen aller zu generierenden Assembly-Befehle kann die JitRuntime-Klasse verwendet werden, um den Code aus dem CodeHolder mit Ausführungsberechtigung in den Speicher zu kopieren und zu relozieren.
Während ich nach einer Bibliothek zur Codegenerierung suchte, stieß ich auf AsmJit und sah, dass es von vielen populären Projekten weit verbreitet eingesetzt wird. Aus diesem Grund entschied ich mich, es für meine Zwecke zu verwenden. Ich weiß nicht, ob Shoggoth das erste Projekt ist, das es im Red-Team-Kontext einsetzt, aber ich glaube, dass es als Referenz für zukünftige Implementierungen dienen kann.
Shoggoth kann verwendet werden, um übergebene PE- und COFF-Dateien zu verschlüsseln, sodass beide dank vorkompilierter positionsunabhängiger Loader als Shellcode ausgeführt werden können. Ich habe einfach die C to Shellcode-Methode verwendet, um die PIC-Version bekannter PE- und COFF-Loader zu erhalten, die ich für meine alten Projekte modifiziert habe. Für die Kompilierung habe ich das Makefile aus dem HandleKatz-Projekt verwendet, einem LSASS-Dumper in PIC-Form.
Grundsätzlich habe ich, um mit der C-to-Shellcode-Technik Shellcode zu erhalten, alle globalen Variablen im Loader-Quellcode entfernt, alle Zeichenfolgen auf dem Stack gespeichert und die Adressen der Windows-API-Funktionen durch Laden und Parsen der erforderlichen DLLs zur Laufzeit aufgelöst. Anschließend habe ich den Einsprungpunkt mit einem Linker-Script bestimmt und den Code mit MinGW unter Verwendung verschiedener Kompilierungsflags kompiliert. Ich extrahierte den .text-Abschnitt der generierten ausführbaren Datei und erhielt den Loader-Shellcode. Da die nach obiger Bearbeitung erhaltene ausführbare Datei außer dem .text-Abschnitt keine weiteren Abschnitte enthält, kann der Code in diesem Abschnitt als positionsunabhängig verwendet werden.
Der Quellcode dieser Loader kann in den Verzeichnissen COFFLoader und PELoader eingesehen und bearbeitet werden. Kompilierte Versionen dieser Quellcodes finden Sie im Verzeichnis stub. Wenn Sie diese Loader bearbeiten oder ändern möchten, müssen Sie derzeit die Signaturen einhalten und die vorkompilierten Binärdateien aus dem stub-Verzeichnis ersetzen.
Um Argumente an ein BOF zu übergeben, verwenden Sie die Option '--coff-arg'. Shoggoth erwartet eine vorformatierte Hex-Zeichenfolge mit den gepackten Argumenten, die mit dem Skript beacon_generate.py von TrustedSec erstellt werden kann. Eine Kopie dieses Skripts wurde als COFFArgGenerator/beacon_generate.py beigefügt. (Vielen Dank an @Octoberfest7)
Shoggoth verwendet zunächst einen der Stromchiffren, den RC4-Algorithmus, um die erhaltene Nutzlast zu verschlüsseln. Nachdem der hier verwendete Schlüssel zufällig generiert wurde, verschlüsselt es die Nutzlast mit diesem Schlüssel. Der Entschlüsselungs-Stub, der die Nutzlast zur Laufzeit entschlüsselt, wird dynamisch mit AsmJit erstellt und assembliert. Die im Stub verwendeten Register werden für jedes Sample zufällig ausgewählt.
Für die Implementierung des in Shoggoth verwendeten RC4-Algorithmus habe ich mich auf Nayukis Code bezogen.
Nach der ersten Verschlüsselung verwendet Shoggoth die zweite Verschlüsselung, eine zufällig generierte Blockchiffre. Mit der zweiten Verschlüsselung werden sowohl der RC4-Entschlüsseler als auch optional der Stub verschlüsselt, der die mit RC4 verschlüsselte Nutzlast, nutzlose Anweisungen und Loader enthält. Es teilt den zu verschlüsselnden Block in 8-Byte-Blöcke auf und verwendet für jeden Block zufällig generierte Anweisungen. Zu diesen Anweisungen gehören ADD, SUB, XOR, NOT, NEG, INC, DEC, ROL und ROR. Die Operanden für diese Anweisungen werden ebenfalls zufällig ausgewählt.
Die Logik zur Generierung nutzloser Anweisungen ist stark von Ege Balcis großartigem SGN-Projekt inspiriert. Shoggoth kann nutzlose Anweisungen basierend auf dem Überspringen zufälliger Bytes, Anweisungen ohne Nebenwirkungen, falschen Funktionsaufrufen und Anweisungen mit Nebenwirkungen, die jedoch Anfangswerte beibehalten, auswählen. Alle diese Anweisungen werden zufällig ausgewählt und durch Aufrufen der entsprechenden API-Funktionen der AsmJit-Bibliothek generiert. Um sowohl die Größe als auch verschiedene Kombinationen zu erhöhen, werden diese Generierungsfunktionen rekursiv aufgerufen.
Es gibt viele Stellen, an denen in der ersten Version von Shoggoth nutzlose Anweisungen eingefügt werden können. Beispielsweise können nutzlose Anweisungen zwischen Blockchiffre-Anweisungen oder RC4-Chiffre-Anweisungen platziert werden. Für Demonstrationszwecke habe ich sie jedoch für die folgenden Versionen vorgesehen, um die zusätzliche Komplexität der generierten Nutzlasten zu vermeiden.
Ich habe das Hauptprojekt nicht kompiliert. Daher müssen Sie es selbst kompilieren. Wenn Sie optional den Quellcode des PE-Loaders oder COFF-Loaders bearbeiten möchten, sollten Sie MinGW auf Ihrem Rechner haben, um sie mit den mitgelieferten Makefiles zu kompilieren.
______ _ _
/ _____) | _ | |
( (____ | |__ ___ ____ ____ ___ _| |_| |__
\____ \| _ \ / _ \ / _ |/ _ |/ _ (_ _) _ \
_____) ) | | | |_| ( (_| ( (_| | |_| || |_| | | |
(______/|_| |_|\___/ \___ |\___ |\___/ \__)_| |_|
(_____(_____|
by @R0h1rr1m
"Tekeli-li! Tekeli-li!"
Usage of Shoggoth.exe:
-h | --help Show the help message.
-v | --verbose Enable more verbose output.
-i | --input <Input Path> Input path of payload to be encrypted. (Mandatory)
-o | --output <Output Path> Output path for encrypted input. (Mandatory)
-s | --seed <Value> Set seed value for randomization.
-m | --mode <Mode Value> Set payload encryption mode. Available mods are: (Mandatory)
[*] raw - Shoggoth doesn't append a loader stub. (Default mode)
[*] pe - Shoggoth appends a PE loader stub. The input should be valid x64 PE.
[*] coff - Shoggoth appends a COFF loader stub. The input should be valid x64 COFF.
--coff-arg <Argument> Set argument for COFF loader. Generate this string using COFFArgGenerator/beacon_generate.py.
example: --coff-arg 0a0000000600000068656c6c6f00
Only used in COFF loader mode. (Thanks to @Octoberfest7)
-k | --key <Encryption Key> Set first encryption key instead of random key.
--dont-do-first-encryption Don't do the first (stream cipher) encryption.
--dont-do-second-encryption Don't do the second (block cipher) encryption.
--encrypt-only-decryptor Encrypt only decryptor stub in the second encryption.
„Es war ein furchtbares, unbeschreibliches Ding, größer als jeder U-Bahn-Zug – eine formlose Ansammlung protoplasmatischer Blasen, schwach selbstleuchtend, mit Myriaden vorübergehender Augen, die sich als Pusteln grünlichen Lichts auf der den gesamten Tunnel füllenden Front bildeten und wieder auflösten, die auf uns zukam, die verzweifelten Pinguine zermalmte und über den glitzernden Boden glitt, den sie und ihresgleichen so böse von allem Abfall befreit hatten.“ ~ H. P. Lovecraft, Berge des Wahnsinns
Ein Shoggoth ist ein fiktives Monster im Cthulhu-Mythos. Die Wesen wurden beiläufig in H. P. Lovecrafts Sonettzyklus Fungi from Yuggoth (1929–30) erwähnt und später in seiner Novelle Berge des Wahnsinns (1931) detailliert beschrieben. Sie können alle Organe oder Anhängsel formen, die sie für die jeweilige Aufgabe benötigen, obwohl ihr üblicher Zustand eine wogende Masse von Augen, Mündern und zappelnden Tentakeln ist.
Da diese Kreaturen wie ein empfindungsfähiger Klumpen aus selbstformendem, gallertartigem Fleisch sind und in Lovecrafts Beschreibungen keine feste Form haben, möchte ich diesen Namen einem Tool zur polymorphen Verschlüsselung geben. 🙂
Nur für autorisierte Sicherheitstests. Missbrauch dieses Tools gegen Systeme ohne ausdrückliche Erlaubnis ist illegal.