
Python-API für die Verwendung mit der External C2-Spezifikation von cobalt strike
Python-Framework zur Verwendung mit der External C2-Spezifikation von Cobalt Strike, wie in der Spezifikation beschrieben.
Das primäre Designziel ist eine sehr modulare Implementierung der External-C2-Spezifikation, die genügend Abstraktion bietet, um C2-Kanäle für Cobalt Strike einfach zu implementieren. Idealerweise muss ein Benutzer lediglich ein transport-Modul, ein encoder-Modul erstellen und eine Konfigurationsdatei ausfüllen, um einen neuen Kanal zu implementieren.
Sie müssen mehrere Konfigurationsänderungen vornehmen, bevor Sie loslegen können. Sie benötigen:
builds/client/dbox/dbox_client.py das token zu dem in Schritt 2 generierten.builds/server/utils/transports/transport_dbox.pycd builds/client/dbox && ./compile_dll.shstart_externalc2.cna von Ihrem CS-Client.cd builds/server/ && ./dbox_server.pyLink zur Videodemo: https://www.youtube.com/watch?v=nTRHSh_uCcA
Dieses Projekt besteht aus drei Hauptteilen:
Der Builder erstellt dynamisch Client- und Server-Bereitstellungen basierend auf der angegebenen Konfiguration. Idealerweise könnte der Client als einzelne kompilierte Datei wie eine DLL oder EXE verteilt werden.
Der Client ist im Wesentlichen die Payload, die auf dem Endpoint läuft und in der Spezifikation als third-party client bezeichnet wird. Die Logik des Clients ist hauptsächlich statisch:
transport erforderlich sind.transport an den C2-Server weiter.transport auf neue Tasks.transport weiter.Die für den Transport und die Kodierungsmechanismen benötigten Konfigurationen werden statisch in den Client kopiert. Die Funktionslogik für Transport- und Kodierungsmechanismen wird ebenfalls statisch aus den jeweiligen Modulen kopiert.
Die Logik der Prozessinjektion wird vom Builder bestimmt.
Der Server ist die Anwendung, die die Kommunikation zwischen dem client und dem c2 server vermittelt und in der Spezifikation als third-party Client Controller bezeichnet wird. Die Serverlogik ist hauptsächlich statisch, unterstützt jedoch ausführliche und Debug-Ausgaben zur Unterstützung der Entwicklung:
encoder-Modul.transport-Modul.transport empfangen wird.encoder-Modul.transport an den Client weiter.transport empfangen wird.encoder-Modul.Die Bestimmung, welches encoder- und transport-Modul der Server importiert, erfolgt anhand der in config.py gespeicherten Werte.
Es werden keine Importe ungenutzter transport- oder encoder-Module durchgeführt.
Die folgenden Tabellen beschreiben gemeinsame Funktionen zwischen den encoding- und transport-Modulen und dem Client. Gemeinsame Funktionen sind im Wesentlichen exakt derselbe Code.
EIN SEHR WICHTIGER HINWEIS: Die Daten, die an die sendData- und recvData-Funktionen des Clients gesendet werden, sollten Rohdaten sein, während Daten, die an die sendData- und retrieveData-Funktionen des Transportmoduls gesendet werden, bereits nach Bedarf kodiert oder dekodiert sein sollten.
| Transportfunktion | Client-Funktion | Beschreibung |
|---|---|---|
| prepTransport | prepTransport | Führt alle Vorkonfigurationen aus, die zur Nutzung des Transportmechanismus erforderlich sind |
| sendData | sendData | Definiert, wie Daten über den Transportmechanismus gesendet werden |
| retrieveData | recvData | Definiert, wie Daten über den Transportmechanismus empfangen werden |
| Encoder-Funktion | Client-Funktion | Beschreibung |
|---|---|---|
| encode | encode | Definiert Änderungen an Rohdaten, um sie für den Transport vorzubereiten |
| decode | decode | Definiert Änderungen an Rohdaten, die vom Transport empfangen wurden, um sie an ihr Ziel weiterzuleiten |
Bestimmen Sie zunächst, welches Transport- und Kodierungsmodul Sie verwenden möchten. Wir verwenden für das folgende Beispiel transport_gmail und encoder_b64url.
Ändern Sie als Nächstes server/config.py entsprechend Ihren Anforderungen und stellen Sie sicher, dass ENCODER_MODULE und TRANSPORT_MODULE korrekt konfiguriert und auf Ihre gewünschten Module zeigen:
EXTERNAL_C2_ADDR = "127.0.0.1"
EXTERNAL_C2_PORT = "2222"
C2_PIPE_NAME = "foobar"
C2_BLOCK_TIME = 100
C2_ARCH = "x86"
IDLE_TIME = 5
ENCODER_MODULE = "encoder_b64url"
TRANSPORT_MODULE = "transport_gmail"
verbose = False
debug = False
Ändern Sie als Nächstes den Konfigurationsabschnitt für Ihr ausgewähltes transport- und encoder-Modul.
Stellen Sie sicher, dass der Konfigurationsabschnitt von client/mechanism/$mechanism_client.py mit allen bisher definierten Konfigurationen übereinstimmt.
Führen Sie auf dem Rechner, auf dem der Server läuft, Folgendes aus:
python server.py
Für eine ausführlichere Ausgabe können Sie Folgendes ausführen:
python server.py -v
Für eine ausführlichere Ausgabe und zusätzliche Ausgaben, die für das Debugging nützlich sind, können Sie Folgendes ausführen:
python server.py -d
Führen Sie als Nächstes den Client auf dem Ziel-Endpoint aus.
Wenn alles funktioniert hat, wird ein neuer Beacon in der Cobalt-Strike-Konsole registriert, mit dem Sie interagieren können.
Warum haben Sie das geschrieben?: Es gab nicht sehr viele veröffentlichte Implementierungen der Spezifikation, und von den veröffentlichten sind sie entweder nicht in einer Sprache, die ich kenne, oder sie besitzen nicht die Modularität und Abstraktion, die ich gesucht habe.
Warum Python 2?: Ich bin faul und es ist einfach, neue Transport- und Kodierungskanäle darin zu implementieren.
Dein Code ist Mist: Das ist keine Frage.
Kann ich neue Transport- und/oder Encoder-Module einreichen?: Ja, bitte! Reichen Sie einen Pull-Request ein, und ich werde ihn gerne überprüfen.
Ähnliche Abstraktion und Modularität werden auch in der Client-Komponente implementiert, um verschiedene Methoden der Prozessinjektion für die Beacon-Payload und andere auf der Roadmap befindliche Funktionen zu unterstützen.
Derzeit fehlt die Builder-Funktionalität, die geplant ist, um Client- und Server-Bereitstellungen dynamisch zu erstellen, aber sie steht auf der Roadmap.