
Plattformübergreifender C2-Agent für Mythic mit dynamischem Funktionsladen, SOCKS5-Proxy, Dateioperationen, Shellcode-Injektion sowie Post-Exploitation-Modulen für macOS/Windows.
Medusa ist ein plattformübergreifender Agent, der sowohl mit Python 3.8 als auch mit Python 2.7 kompatibel ist.
Zur Installation von Medusa benötigst du Mythic v3, das auf einem entfernten Computer installiert ist. Installationsanweisungen für Mythic findest du auf der Mythic-Projektseite.
Führe vom Mythic-Installationsverzeichnis aus den folgenden Befehl aus:
./mythic-cli install github https://github.com/MythicAgents/Medusa.git
Starte Mythic nach der Installation neu, um einen neuen Agenten zu erstellen.
Die Datei Payload_Type/medusa/rabbitmq_config.json ist eine Vorlage und muss deiner Mythic-Umgebung entsprechen.
rabbitmq_password auf deinen Mythic-RABBITMQ_PASSWORD-Wert (in der Regel aus der Mythic-.env).rabbitmq_host auf deinen RabbitMQ-Host/Containernamen (häufig mythic_rabbitmq bei docker-compose-Setups oder 127.0.0.1 für lokale Bindungen).mythic_server_host auf deinen Mythic-Server-Host/Containernamen (häufig mythic_server bei docker-compose-Setups oder 127.0.0.1 für lokale Bindungen).Der Basisagent und die enthaltenen Befehle verwenden ausschließlich in Python integrierte Bibliotheken, sodass keine zusätzlichen Pakete benötigt werden. Die Agenten führen die Befehle in Threads aus, sodass länger laufende Uploads oder Downloads den Hauptagenten nicht blockieren.
Beide Versionen des Medusa-Agenten verwenden eine AES256-HMAC-Implementierung, die mit integrierten Bibliotheken geschrieben wurde (angepasst von hier). Dadurch entfällt die Notwendigkeit zusätzlicher Abhängigkeiten über eine Standard-Python-Installation hinaus. Der Agent sollte daher auf Windows-, Linux- und macOS-Hosts funktionieren. Erwähnenswert ist, dass diese Crypto-Implementierung bei der Verarbeitung großer Dateien (Screenshots, Downloads usw.) einen gewissen Overhead verursacht, aber das ist praktikabel.
Im Verzeichnis Payload_Type/Medusa/agent_code findest du base_agent-Dateien mit den Suffixen py2 und py3. Ebenso sind ähnliche Dateierweiterungen auch für einzelne Funktionsdateien zu sehen.
Diese werden vom Skript builder.py gelesen, um zunächst die richtige Basis-Python-Version des Medusa-Agenten auszuwählen. builder.py bindet anschließend Befehle ein, die für die gewählte Python-Version spezifisch sind. Falls ein Befehl nur eine .py-Endung hat, wird diese standardmäßig verwendet, wobei angenommen wird, dass für die Py2- und Py3-Versionen kein alternativer Code erforderlich ist.
Medusa verwendet einfaches Threading für die Auftragsausführung. Bei potenziell lang laufenden Aufträgen kann eine „Stop-Check“-Logik implementiert werden, um auf ein Signal der jobkill-Aufgabe zu reagieren. Dies kann mit einem Codeausschnitt ähnlich dem folgenden umgesetzt werden:
if [task for task in self.taskings if task["task_id"] == task_id][0]["stopped"]:
# Some job-specific tidy up
return "Job stopped."
Dieser Handler ist in den Befehlen download, upload, watch_dir und screenshot implementiert.
Zusätzlich kann für einen lang laufenden Auftrag, der kontinuierliche Ausgabe liefern soll, die Funktion sendTaskOutputUpdate – im Basisagenten enthalten – verwendet werden, um Mythic vor Abschluss der Aufgabe zu aktualisieren. Eine Dummy-Funktion, die kontinuierliche Ausgabe liefert und per jobkill beendet werden kann, ist unten zu sehen.
def dummyFunction(self, task_id):
while(True):
# Check if we've got a stop signal.
if [task for task in self.taskings if task["task_id"] == task_id][0]["stopped"]: return "Job stopped."
# Send output back to Mythic
self.sendTaskOutputUpdate(task_id, "We're still running")
time.sleep(10)
Medusa unterstützt derzeit zwei C2-Profile: http (sowohl mit als auch ohne AES256-HMAC-Verschlüsselung) und azure_blob.
Das HTTP-Profil meldet sich über das grundlegende, nicht-dynamische Profil beim Mythic-Server zurück. GET-Anfragen für Taskings, POST-Anfragen mit Antworten.
| Befehl | Syntax | Beschreibung |
|---|
| cat | cat path/to/file | Dateiinhalt lesen und ausgeben. |
| cd | cd [.. dir] | Arbeitsverzeichnis wechseln (.., um ein Verzeichnis nach oben zu gehen). |
| cp | cp src_file_or_dir dst_file_or_dir | Datei oder Ordner zum Ziel kopieren. |
| cwd | cwd | Arbeitsverzeichnis ausgeben. |
| download | download [path] | Eine Datei vom Zielsystem herunterladen. |
| download_bulk | download_bulk [path1] [path2] ... | Mehrere Dateien in einem Auftrag vom Zielsystem herunterladen. |
| exit | exit | Einen Callback beenden. |
| env | env | Umgebungsvariablen ausgeben. |
| eval_code | eval_code [commands] | Python-Code ausführen und Ausgabe zurückgeben. |
| jobkill | jobkill [task id] | Stoppsignal an einen lang laufenden Auftrag senden. |
| jobs | jobs | Lang laufende Aufträge auflisten, z. B. Downloads. |
| list_modules | list_modules [module_name] | Listet im Speicher befindliche Module oder die vollständige Dateiliste für ein bestimmtes Modul auf. |
| load | load command | Eine neue Fähigkeit in einen Agenten laden. |
| load_module | load_module | Ein gezipptes Python-Modul in den Speicher laden (angepasst von hier und hier). |
| load_script | load_script | Ein Python-Skript über den Agenten laden und ausführen. |
| ls | ls [. path] | Dateien und Ordner in [path] auflisten oder . für das aktuelle Arbeitsverzeichnis verwenden. |
| mv | mv src_file_or_dir dst_file_or_dir | Datei oder Ordner zum Ziel verschieben. |
| pip_freeze | pip_freeze | Installierte Pakete auf dem System programmatisch auflisten. |
| pty | pty [/bin/bash] / pty self / pty fork | Eine interaktive PTY-Sitzung öffnen. Modi: spawn führt ein Programm mit einer PTY aus, self öffnet eine prozessinterne Python-REPL mit Live-Agentenstatus, fork gabelt den Agenten in eine Python-REPL mit gespeichertem Status (nur Linux/macOS). |
| rm | rm file_or_dir | Datei oder Ordner löschen. |
| shell | shell [command] | Einen Shell-Befehl ausführen, der mittels subprocess.Popen() gestartet wird. Beachte, dass dieser Befehl auf seine Fertigstellung wartet; blockiere deinen Agenten also nicht. |
| socks | socks start/stop [port] | SOCKS5-Proxy über den Medusa-Agenten starten/stoppen. |
| sleep | sleep [seconds] [jitter percentage] | Das Callback-Intervall des Agenten in Sekunden festlegen. |
| unload | unload command | Eine vorhandene Fähigkeit aus einem Agenten entfernen. |
| unload_module | unload_module module_name | Ein zuvor in den Speicher geladenes Python-Modul entladen. |
| upload | upload | Eine Datei an einen entfernten Pfad auf dem Rechner hochladen. |
| watch_dir | watch_dir path seconds | Ein Zielverzeichnis in einem festgelegten Intervall auf Änderungen überwachen. |
| Befehl | Syntax | Beschreibung |
|---|
| clipboard | clipboard | Inhalt der Zwischenablage ausgeben (verwendet die Objective-C-API, wie von Cedric Owens hier beschrieben. Nur macOS, nur Python 2.7). |
| list_apps | list_apps | macOS-Anwendungen auflisten (nur Python 2.7, nur macOS). |
| list_tcc | list_tcc [path] | Einträge in der macOS-TCC-Datenbank auflisten (erfordert derzeit Vollzugriff auf die Festplatte und Big Sur). |
| screenshot | screenshot | Einen Screenshot erstellen (verwendet die Objective-C-API, nur macOS, nur Python 2.7). |
| spawn_jxa | spawn_jxa | Einen osascript-Prozess starten und JavaScript-Inhalt übergeben. |
| vscode_list_recent | vscode_list_recent [state_db] | Listet kürzlich mit VSCode geöffnete Dateien und Ordner auf. |
| vscode_open_edits | vscode_open_edits [backup_dir_path] | Listet nicht gespeicherte Änderungen an Dateien in VSCode auf. |
| vscode_watch_edits | vscode_watch_edits [path to remote dir] [poll_interval] | Das VSCode-Backup-Verzeichnis in einem festgelegten Intervall auf nicht gespeicherte Änderungen abfragen. |
| Befehl | Syntax | Beschreibung |
|---|
| shinject | shinject | Shellcode mithilfe von CreateRemoteThread in eine Ziel-PID injizieren (nur Windows – angepasst von hier). |
| load_dll | load_dll dll_path dll_export | Eine auf der Festplatte befindliche DLL laden und eine exportierte Funktion ausführen (HINWEIS: Diese DLL muss nach Abschluss einen int-Wert zurückgeben; eine mit msfvenom erstellte DLL würde beispielsweise deinen Agenten nach Abschluss beenden). |
| list_dlls | list_dlls [pid] | Prozessspeicher (PEB) des lokalen oder Zielprozesses lesen, um eine Liste der geladenen DLLs abzurufen (nur Python 3). |
| ps | ps | Eingeschränkte Prozessinformationen abrufen, z. B. PID, Prozessnamen, Architektur und Binärpfade (nur Python 3). |
| ps_full | ps_full | Vollständige Prozessinformationen abrufen, einschließlich PPID, Integritätsstufe und Befehlszeile (nur Python 3). |
| kill | kill | Einen Prozess anhand der Prozess-ID beenden (nur Python 3). |