Offensive

Extending The Covenant: Part 2

Weitere aktuelle Änderungen, die wir in Covenant implementiert haben, wie neue Tasks, geänderte alte Tasks und ein neues Graph-Layout.


Dies ist der dritte Teil einer Reihe von Blogbeiträgen über unsere jüngste Arbeit mit dem Open-Source-C2-Framework Covenant.

Auch hier gibt es drei neue Tasks, die die Community in ihre eigenen Covenant-Instanzen importieren und verwenden kann. Zu beachten ist, dass zwei von den Tasks administrative Rechte auf dem kompromittierten System erfordern. Ich möchte auch auf ein anderes GitHub-Repo hinweisen, das eine Menge hilfreicher Covenant-Tasks enthält, über die ich erst kürzlich gestolpert bin. Ausserdem wurde ProcessList so geändert, dass in der Ausgabe ein grep-ähnliches Matching durchgeführt werden kann. Die erwähnenswerteste Ergänzung ist jedoch das neue Graph-Layout, das vom Standard-Layout von Covenant zu einem hierarchischen Layout mit zusätzlichen Informationen gewechselt wurde.

Beginnen wir mit den neuen Tasks und ihren Einsatzmöglichkeiten bei einem Red Teaming. Manchmal stolpert man auf der Suche nach einer Lösung für ein Problem über eine Goldmine. So ging es mir, als ich auf GitHub von malcomvetter mehrere kleine C#-Snippets fand, die sich auf eine bestimmte Aufgabe während der Post-Exploitation konzentrieren. Die Implementierung dieser Snippets in neue Tasks war schnell und einfach, was ein weiterer Grund ist, warum ich Covenant so mag. Die Links zu den jeweiligen Snippets befinden sich in den Hilfetexten der Aufgaben.

Alle neuen Tasks können von unserem GitHub heruntergeladen werden: Covenant-Additions

ProcessWatcher

Für diesen Task sind Administratorrechte erforderlich. Es wird WMI verwendet, um kontinuierlich Ereignisse zur Erstellung neuer Prozesse zu verfolgen. Der Task gibt die PID, den Namen, den Besitzer und die Befehlszeilenargumente für den Prozess zurück (falls möglich, WMI ist manchmal zu langsam). Dieser Task ist für den Fall gedacht, dass ein System so weit kompromittiert wurde, dass der Operator über Administratorrechte verfügt und darauf wartet, das Kerberos-Ticket oder die Anmeldeinformationen eines anderen Benutzers auszulesen oder in dessen Prozess zu injecten usw.

ProcessWatcher_example

Es ist zwar möglich, ProcessWatcher mit dem Befehl "ProcessWatcher 0" auf unbestimmte Zeit laufen zu lassen, aber davon ist abzuraten, da es einen Fehler in Covenant gibt. Dieser führt dazu, dass die Output-Pipe für den Grunt geschlossen wird, wenn der Task beendet wird. Das bedeutet, dass alle Tasks, die dann ausgeführt werden, keine Ausgabe zurückgeben können. Dies gilt auch für KeyLogger, SecurityWatcher und möglicherweise auch für andere Tasks.

ProcessWatcher_help

SecurityWatcher

Für diesen Task sind Administratorrechte erforderlich. Es wird das Windows-Ereignisprotokoll abonniert, um neue Sicherheitsereignisse zu verfolgen, und sendet Informationen über diese Ereignisse an den Bediener. Dazu gehören unter anderem Anmeldung, Abmeldung und Verwendung von erhöhten Berechtigungen. Dieser Task ist wiederum dafür gedacht, wenn ein Operator bereits über Administratorrechte auf einem System verfügt und nach interessanten Sicherheitsereignissen auf dem Rechner Ausschau halten möchte. Es hilft auch dabei, herauszufinden, was zu einer Unterbrechung der Verbindung des Grunts geführt haben könnte.

SecurityWatcher_example

Es werden viele Ereignisse in kurzer Zeit gesammelt. Im obigen Beispiel wurde ein Notepad-Prozess mit administrativen Rechten gestartet und dann der Benutzer abgemeldet.

SecurityWatcher_help

ListOpenWindows

Zählt alle laufenden Prozesse auf und gibt den Titel des Hauptfensters zurück. Einige wenige Prozesse werden nicht angezeigt, da das Hauptfenster ausgeblendet ist (z. B. explorer.exe), aber insgesamt ermöglicht dieser Task einen schnellen Überblick darüber, woran der Benutzer gerade arbeitet. Da Covenant bereits über eine Screenshot-Funktion verfügt, sollte dieser Task am besten mit dieser kombiniert werden, um die Fenstertitel zu erhalten und dann zu versuchen, alle interessanten Informationen mit einem Screenshot zu sehen.

ListOpenWindows_example

Im obigen Beispiel ist eine verdächtige Textdatei zu sehen. Wenn jedoch das Notepad-Fenster im Hintergrund ist, würde mir ein Screenshot nicht helfen. Mit dem Dateinamen aus dem Fenstertitel wüsste ich jetzt, wonach ich suchen muss. Das ist natürlich ein einfaches Beispiel, aber leider kein unwahrscheinliches.

ListOpenWindows_help

Schauen wir uns nun die Änderungen an ProcessList an.

ProcessList

Ermittelt eine Liste der derzeit laufenden Prozesse. Dieser Task ist nicht neu, sondern bereits in Covenant vorhanden. Wir wollten jedoch die Ausgabe so filtern, dass sie nur einen Suchbegriff enthält, wie bei grep. Daher ist es jetzt möglich, einen Suchbegriff als Parameter an den Befehl anzuhängen (Covenant erlaubt Aliasnamen, "ps" kann anstelle von ProcessList verwendet werden). Wenn der Parameter leer gelassen wird, wird die Standardausgabe (alle laufenden Prozesse) zurückgegeben.

ProcessList_example_1

Alle Zeichenfolgen der Ausgabe können abgeglichen werden, so dass es auch möglich ist, nach bestimmten PIDs, PPIDs, Besitzern, Pfaden usw. zu filtern. Im folgenden Screenshot wird die PPID des zuvor identifizierten Notepad-Prozesses verwendet, um nach dem übergeordneten Prozess und seinen anderen untergeordneten Prozessen zu suchen.

ProcessList_example_2

Das waren die neuen und geänderten Tasks. Wie eingangs geschrieben, ist eine weitere coole Neuerung das geänderte Graph-Layout.

Hierarchischer Graph

Ich wollte das Layout des Graphen schon seit einiger Zeit ändern, da ich etwas deutlicher sehen wollte, wie meine Grunts und Listener miteinander verbunden sind. Covenant verwendet d3's forceSimulation, was mir nicht passend erschien. Ich wechselte es zu d3 tree und einem einfacheren Node-Array, wo jeder Knoten nur eine Parentnode (mit Ausnahme der Root-Node namens "Covenant", diese wurde aufgenommen, um mehrere Listener im Graph zu ermöglichen), eine ID und eine Füllfarbe.

inactive_grunts

Das Bild oben zeigt, wie mein Graph derzeit aussieht. Die Färbung der Knoten ist immer noch die gleiche, aber die ausgegrauten Knoten sind Grunts, die einen anderen Status als "Active" haben. Grunts, die ausgeblendet sind, werden im Graph nicht mehr angezeigt, ebenso wenig wie gelöschte Grunts. Dadurch kann der Graph etwas kompakter gehalten werden.

new_graph_2

Zusätzlich wollte ich mehr Informationen über den Grunt in den Details sehen. Damit mehr Informationen angezeigt werden können, ohne viel Platz zu benötigen, bin ich von den üblichen Textfeldern auf vorformatierten Text umgestiegen.

Es ist nicht mehr möglich, Knoten zu verschieben, sie werden automatisch sortiert und sollten immer an der gleichen Stelle sein.

Soll der Graph mit einem hellen Theme verwendet werden, muss die Zeile 278 in master.js bearbeitet werden:
halo = "#222", // color of label halo

Wenn diese Änderungen zu einer bestehenden Covenant-Installation hinzugefügt wurden, muss dotnet clean vor dem nächsten dotnet run ausgeführt werden, damit die Änderungen an der .razor-Datei übernommen werden.

Weitere Verbesserungen könnten Schwenken, Zoomen und weitere hilfreiche Informationen über die Objekte im Graph umfassen. Ich denke auch darüber nach, die Registerkarte "Dashboard" so zu modifizieren, dass sie unseren Bedürfnissen besser entspricht, und eine kleinere Version des Graphen könnte sehr wohl Teil dieser ersten Seite sein.

Auf der GitHub-Seite von Covenant wurde ein Pull-Request eröffnet, der vorschlägt, diese Änderungen in den dev-Zweig zu implementieren.

Das war es für den Moment! Danke fürs Lesen und wie immer gilt: Falls es Fragen oder Rückmeldungen gibt, können diese gerne per Mail an research@avantguard.io oder im BloodHoundGang Slackchannel an mich (Username @jannlemm0913) direkt gestellt werden.

Similar posts