
Agente C2 multipiattaforma per Mythic con caricamento dinamico delle funzioni, proxy SOCKS5, operazioni sui file, iniezione di shellcode e moduli di post-esplorazione per macOS/Windows.
Medusa è un agente cross-platform compatibile sia con Python 3.8 che con Python 2.7.
Per installare Medusa, avrai bisogno di Mythic v3 installato su un computer remoto. Puoi trovare le istruzioni di installazione per Mythic nella pagina del progetto Mythic.
Dalla directory principale di installazione di Mythic, esegui il comando:
./mythic-cli install github https://github.com/MythicAgents/Medusa.git
Una volta installato, riavvia Mythic per creare un nuovo agente.
Il file Payload_Type/medusa/rabbitmq_config.json è un template e deve corrispondere al tuo ambiente Mythic.
rabbitmq_password sul valore del tuo Mythic RABBITMQ_PASSWORD (solitamente dal file .env di Mythic).rabbitmq_host sul nome dell'host/container RabbitMQ (spesso mythic_rabbitmq nelle configurazioni docker-compose, oppure 127.0.0.1 per binding locali).mythic_server_host sul nome dell'host/container del server Mythic (spesso mythic_server nelle configurazioni docker-compose, oppure 127.0.0.1 per binding locali).L'agente base e i comandi inclusi utilizzano tutti librerie Python integrate, quindi non richiedono pacchetti aggiuntivi per funzionare. Gli agenti eseguono i comandi in thread, quindi upload o download di lunga durata non bloccheranno l'agente principale.
Entrambe le versioni dell'agente Medusa utilizzano un'implementazione AES256 HMAC scritta con librerie integrate (adattata da qui), eliminando la necessità di dipendenze aggiuntive oltre a un'installazione Python standard. L'agente dovrebbe quindi funzionare su host Windows, Linux e macOS. Vale la pena menzionare che questa implementazione crittografica introduce un certo overhead nella gestione di file di grandi dimensioni (screenshot, download, ecc.) ma è comunque utilizzabile.
All'interno della directory Payload_Type/Medusa/agent_code, vedrai file base_agent con suffissi py2 e py3. Allo stesso modo, estensioni simili si possono notare anche per i singoli file di funzione.
Questi vengono letti dallo script builder.py per selezionare prima la giusta versione Python di base dell'agente Medusa. builder.py includerà poi i comandi specifici per la versione Python scelta. Nel caso in cui un comando abbia solo estensione .py, questo verrà usato come default, presupponendo che non sia necessario alcun codice alternativo tra le versioni Py2 e Py3.
Medusa usa il threading di base per l'esecuzione dei job. Dove i job potenzialmente durano a lungo, possono essere implementati con uno 'stop check' per rispondere a un segnale dal task jobkill. Questo può essere implementato con uno snippet di codice simile a quello mostrato di seguito:
if [task for task in self.taskings if task["task_id"] == task_id][0]["stopped"]:
# Alcune operazioni di pulizia specifiche del job
return "Job stopped."
Questo handler può essere visto implementato nei comandi download, upload, watch_dir e screenshot.
Inoltre, se ci si aspetta che il job di lunga durata fornisca output continuo, la funzione sendTaskOutputUpdate - inclusa nell'agente base - può essere usata per aggiornare Mythic prima del completamento del task. Una funzione fittizia che fornisce output continuo e che può essere terminata con jobkill è visibile di seguito.
def dummyFunction(self, task_id):
while(True):
# Controlla se abbiamo ricevuto un segnale di stop.
if [task for task in self.taskings if task["task_id"] == task_id][0]["stopped"]: return "Job stopped."
# Invia l'output di nuovo a Mythic
self.sendTaskOutputUpdate(task_id, "We're still running")
time.sleep(10)
Medusa supporta attualmente due profili C2: http (sia con che senza crittografia AES256 HMAC) e azure_blob.
Il profilo HTTP effettua il callback al server Mythic tramite il profilo base non dinamico. Richieste GET per i task, richieste POST con le risposte.
| Comando | Sintassi | Descrizione |
|---|
| cat | cat path/to/file | Legge e restituisce il contenuto di un file. |
| cd | cd [.. dir] | Cambia la directory di lavoro (.. per salire di una directory). |
| cp | cp src_file_or_dir dst_file_or_dir | Copia un file o una cartella nella destinazione. |
| cwd | cwd | Stampa la directory di lavoro. |
| download | download [path] | Scarica un file dal sistema di destinazione. |
| download_bulk | download_bulk [path1] [path2] ... | Scarica più file dal sistema di destinazione in un unico task. |
| exit | exit | Termina una callback. |
| env | env | Stampa le variabili d'ambiente. |
| eval_code | eval_code [commands] | Esegue codice Python e restituisce l'output. |
| jobkill | jobkill [task id] | Invia un segnale di stop a un task di lunga durata. |
| jobs | jobs | Elenca i task di lunga durata, come i download. |
| list_modules | list_modules [module_name] | Elenca i moduli in memoria o l'elenco completo dei file per un modulo specifico. |
| load | load command | Carica una nuova capacità in un agente. |
| load_module | load_module | Carica un modulo Python compresso in memoria (adattato da qui e qui). |
| load_script | load_script | Carica ed esegue uno script Python tramite l'agente. |
| ls | ls [. path] | Elenca file e cartelle in [path] oppure usa . per la directory di lavoro corrente. |
| mv | mv src_file_or_dir dst_file_or_dir | Sposta un file o una cartella nella destinazione. |
| pip_freeze | pip_freeze | Elenca programmaticamente i pacchetti installati sul sistema. |
| pty | pty [/bin/bash] / pty self / pty fork | Apre una sessione PTY interattiva. Modalità: spawn esegue un programma con una PTY, self apre una REPL Python in-process con lo stato live dell'agente, fork crea un fork dell'agente in una REPL Python con stato snapshot (solo Linux/macOS). |
| rm | rm file_or_dir | Elimina un file o una cartella. |
| shell | shell [command] | Esegue un comando shell che verrà avviato usando subprocess.Popen(). Nota: attenderà il completamento del comando, quindi fai attenzione a non bloccare l'agente. |
| socks | socks start/stop [port] | Avvia/ferma il proxy SOCKS5 tramite l'agente Medusa. |
| sleep | sleep [seconds] [jitter percentage] | Imposta l'intervallo di callback dell'agente in secondi. |
| unload | unload command | Rimuove una capacità esistente da un agente. |
| unload_module | unload_module module_name | Rimuove un modulo Python precedentemente caricato in memoria. |
| upload | upload | Carica un file in un percorso remoto sulla macchina. |
| watch_dir | watch_dir path seconds | Monitora le modifiche nella directory di destinazione, effettuando polling delle modifiche a un intervallo specificato. |
| Comando | Sintassi | Descrizione |
|---|
| clipboard | clipboard | Restituisce il contenuto degli appunti (usa l'API Objective-C, come descritto da Cedric Owens qui. Solo macOS, solo Python 2.7). |
| list_apps | list_apps | Elenca le applicazioni macOS (solo Python 2.7, solo macOS). |
| list_tcc | list_tcc [path] | Elenca le voci nel database TCC di macOS (richiede accesso completo al disco e per ora solo Big Sur). |
| screenshot | screenshot | Acquisisce uno screenshot (usa l'API Objective-C, solo macOS, solo Python 2.7). |
| spawn_jxa | spawn_jxa | Avvia un processo osascript e invia contenuto Javascript tramite pipe. |
| vscode_list_recent | vscode_list_recent [state_db] | Elenca i file e le cartelle aperti di recente con VSCode. |
| vscode_open_edits | vscode_open_edits [backup_dir_path] | Elenca le modifiche non salvate apportate ai file in VSCode. |
| vscode_watch_edits | vscode_watch_edits [path to remote dir] [poll_interval] | Sottopone a polling la directory dei backup di VSCode a un intervallo specificato per individuare modifiche non salvate. |
| Comando | Sintassi | Descrizione |
|---|
| shinject | shinject | Inietta shellcode nel PID di destinazione usando CreateRemoteThread (solo Windows - adattato da qui). |
| load_dll | load_dll dll_path dll_export | Carica una DLL su disco ed esegue una funzione esportata (NOTA: questa DLL deve restituire un valore int al completamento; ad esempio, una DLL creata con msfvenom ucciderà il tuo agente al termine). |
| list_dlls | list_dlls [pid] | Legge la memoria del processo (PEB) del processo locale o di destinazione per ottenere l'elenco delle DLL caricate (solo Python 3) |
| ps | ps | Ottiene informazioni limitate sui processi, ad es. PID, nomi dei processi, architettura e percorsi dei binari (solo Python 3) |
| ps_full | ps_full | Ottiene informazioni complete sui processi, inclusi PPID, livello di integrità e riga di comando (solo Python 3) |
| kill | kill | Termina un processo tramite ID processo (solo Python 3) |