
Vorlage für die Entwicklung benutzerdefinierter C2-Kanäle für Cobalt Strike unter Verwendung von IAT-Hooks, die von einem Reflective Loader angewendet werden.
Dies ist ein einfacher PoC und eine Vorlage für die Entwicklung benutzerdefinierter C2-Kanäle für Cobalt Strike unter Verwendung von IAT-Hooks, die von einem reflektiven Loader angewendet werden.
Blogbeitrag: https://codex-7.gitbook.io/codexs-terminal-window/red-team/cobalt-strike/building-custom-c2-channels-by-hooking-wininet
Demo-GIF des TCP-Kanals

Die Dateien customCallback.h, hook.c, hash.h und hook.h sind grobe Vorlagen, können aber in Crystal Kit eingefügt werden, um als PoC direkt verwendet zu werden. Lege sie in den Ordner udrl/src und ersetze die vorhandenen Kopien. tcg.h bleibt unverändert (aus Raphael Mudge's Tradecraft Garden).
Die Beispiele im Ordner examples/ können direkt verwendet werden, sind jedoch Beispiele und wurden nicht unter operativen Gesichtspunkten erstellt. Vorsicht bei der Verwendung.
Aktuelle Beispiele sind:
Beachte, dass die ursprünglichen Evasion-Fähigkeiten in Crystal Kit, wie die Draugr-Implementierung und Sleep Masking, aus hook.c entfernt wurden, um diesen Code sauber und portabel zu halten. Falls du diese Funktionen behalten möchtest, kannst du sie aus den Originalkopien in Crystal Kit wieder hinzufügen.
Du musst die entsprechende HTTP-Bibliothek (WinHTTP/WinInet) als HTTP-Bibliothek auswählen, die bei der Generierung der Beacon-DLL verwendet werden soll.
Das Malleable-Profil, mit dem dies getestet wurde, ist im Repository enthalten – theoretisch sollten (die meisten) anderen Malleable-Profile funktionieren, aber diese Vorlage wurde mit diesem Profil (aus GraphStrike) getestet.
Das offizielle ExternalC2-Interface ist umständlich zu verwenden – es erfordert das Staging eines SMB-Beacons ÜBER den ExternalC2-Kanal und unterstützte (bis Version 4.10) keine Kommunikation mit einem vorab erstellten SMB-Beacon ohne vorheriges Staging über den ExternalC2-Agenten. Selbst im aktuellen Zustand ist es immer noch an die Architektur gebunden:
smb beacon --named pipe--> externalc2 agent --custom channel--> externalc2 handler --> teamserver
Ja, mir ist bewusst, dass UDC2 in Cobalt Strike 4.12 hinzugefügt wurde. Dies ist dennoch ein lustiges Experiment, um diese Fähigkeit im UDRL nachzubilden.
Das Konzept ist einfach: Wenn man die WinAPIs, die für den Rückruf verwendet werden, hooken kann, hat man bereits alle für einen Rückruf notwendigen Daten. Diese Methode zur Implementierung benutzerdefinierter C2-Kanäle wurde bereits zuvor verwendet, wie in GraphStrike zu sehen ist.
Allerdings ist GraphStrikes Implementierung immer noch stark an das HTTP-Protokoll selbst gebunden. Das Ziel dieses Repos ist es, eine einfach zu verwendende, modifizierbare und erweiterbare Vorlage für die Implementierung beliebiger benutzerdefinierter Kanäle bereitzustellen – HTTP oder anderweitig – mit minimalen Änderungen am umgebenden Code.
Diese Vorlage ist offensichtlich nicht dafür gedacht, in ihrem Standardzustand verwendet zu werden. Um deinen bevorzugten C2-Kanal zu implementieren, musst du Folgendes anpassen:
Die Funktion customCallback, um die folgenden Dinge zu tun:
Du kannst den ursprünglichen Host und Port der HTTP-Anfrage (die du von Cobalt aus festlegst) über die Argumente verwenden:
const char *host
INTERNET_PORT port
und modifiziere die Funktion handleCallback() in broker.py, um Folgendes zu tun:
Das war's.
Als Beispiel macht die PoC-Funktion customCallback() in der Datei customCallback.h derzeit Folgendes:
Die PoC-Funktion handleCallback in broker.py macht derzeit Folgendes:
process_encoded_request(encoded_request) aufusage: broker.py [-h] --host HOST --port PORT
wobei Host und Port auf den HTTP-Listener auf deinem Teamserver verweisen. Der Broker extrahiert die HTTP-Anfrage und sendet sie an den tatsächlichen Listener.
Dies ist wahrscheinlich der "faulste" Weg, dies zu tun, aber auch einer der stabileren. Es verpackt im Wesentlichen die gesamte HTTP-Anfrage und überträgt sie auf beliebige Weise an den Broker, der sie dann zur Ausführung als HTTP-Beacon an den Teamserver sendet – völlig transparent für den Teamserver.
Es gibt eine (technisch) sauberere Implementierung, die ich ausprobiert habe, bei der ich ein abgespecktes Malleable-C2-Profil verwendet habe (ich habe tatsächlich das von GraphStrike genommen) und die verschiedenen Beacon-Datenkomponenten gemäß der Malleable-Spezifikation direkt in den WinInet-Hooks analysiert habe (ID, Metadaten, Output usw.). Dies hätte die Rückruf-Blob-Größen etwas verkleinert, aber diese Implementierung wurde aufgegeben, da die Codebasis aufgrund der Anfrageanalyse unnötig unübersichtlich wurde und die Verwendung dieses spezifischen Profils erforderte (was an sich kein großes Problem ist, aber etwas hacky).
Ich fand diese Implementierung besser, weil sie weniger von einem hackigen Malleable-Profil abhängt (technisch gesehen erfordert sie immer noch, dass die Beacon-Antwortausgabe im Antwortbody gesendet wird, aber das ist die einzige Anforderung) und der Code war zehnmal einfacher zu lesen.
Erwähnenswert ist auch, dass es keine Verschleierung oder Verschlüsselung des HTTP-Anfrage-JSONs gibt, abgesehen von der Base64-Kodierung – du kannst gerne deine eigene hinzufügen, aber da Beacon-Rückrufe bereits verschlüsselt sind, sind die Daten technisch gesehen nicht gefährdet. Das Schlimmste, was passieren könnte, ist, dass der Base64-Blob, falls abgefangen, als HTTP-Anfrage identifiziert werden könnte. Mach mit dieser Information, was du willst.
Ja, ich habe ein LLM verwendet, um einen Teil des Codes und der Kommentare zu schreiben – niemand schreibt gerne Dokumentation oder kocht JSON-Parsing in C von Grund auf neu. Verklagt mich.
Üblicher Haftungsausschluss: Ich bin nicht verantwortlich für irgendwelche Verbrechen gegen die Menschlichkeit, die du begehen könntest, oder für einen nuklearen Krieg, den du mit diesem schlecht geschriebenen Code auslösen könntest.