
modello per sviluppare canali C2 personalizzati per Cobalt Strike utilizzando hook IAT applicati da un caricatore riflessivo.
Questo è un semplice PoC e template per sviluppare canali C2 personalizzati per Cobalt Strike utilizzando hook IAT applicati da un reflective loader.
Post del blog: https://codex-7.gitbook.io/codexs-terminal-window/red-team/cobalt-strike/building-custom-c2-channels-by-hooking-wininet
Gif dimostrativa del canale TCP

I file customCallback.h, hook.c, hash.h e hook.h sono template grezzi, ma possono essere inseriti in Crystal kit per essere usati così come sono come PoC. Posizionateli nella cartella udrl/src, sostituendo le copie esistenti. tcg.h è invariato (dal tradecraft garden di Raphael Mudge).
Gli esempi nella cartella examples/ possono essere usati così come sono, ma sono esempi e non sono state prese in considerazione considerazioni operative durante la loro scrittura. Usare con cautela.
Gli esempi attuali sono:
Nota che le capacità di evasione originali di Crystal kit come l'implementazione Draugr e il sleep masking sono state rimosse da hook.c per mantenere questo codebase pulito e portabile. Se desideri mantenere queste funzionalità, puoi aggiungerle nuovamente dalle copie originali in Crystal kit.
Devi selezionare la libreria http appropriata winhttp/wininet come libreria http da utilizzare durante la generazione della DLL del beacon.
Il profilo malleable con cui è stato testato è fornito nel repo - in teoria (la maggior parte) degli altri profili malleable dovrebbero funzionare, ma questo template è stato testato usando questo profilo (preso da GraphStrike).
L'interfaccia ufficiale ExternalC2 è un problema da usare - richiede lo staging di un beacon SMB SUL canale externalc2, e (fino alla 4.10) non supportava la comunicazione con un beacon SMB predefinito senza staging tramite l'agente externalc2 prima. Anche nel suo stato attuale, è ancora legato all'architettura di:
smb beacon --named pipe--> externalc2 agent --custom channel--> externalc2 handler --> teamserver
Sì, sono a conoscenza di UDC2 aggiunto in Cobalt Strike 4.12. Questo è solo un esperimento divertente per replicare quella capacità nell'UDRL.
Il concetto è semplice - se puoi hookare le WinAPI utilizzate per il callback, hai già tutti i dati necessari per un callback. Questo metodo di implementazione di canali C2 personalizzati è già stato fatto in precedenza, come visto in GraphStrike.
Tuttavia, l'implementazione di GraphStrike è ancora abbastanza legata al protocollo HTTP stesso. L'obiettivo di questo repo è fornire un template facile da usare, modificare ed estendere per implementare qualsiasi canale personalizzato, HTTP o meno, con poche modifiche al codice circostante.
Ovviamente questo template non è pensato per essere usato nel suo stato predefinito, quindi per implementare il canale C2 desiderato, devi modificare quanto segue:
La funzione customCallback per eseguire le seguenti operazioni:
Puoi usare l'host e la porta originali della richiesta http (impostati da cobalt) tramite gli argomenti:
const char *host
INTERNET_PORT port
e modificare la funzione handleCallback() in broker.py per fare quanto segue:
Tutto qui.
Ad esempio, il PoC nella funzione customCallback() in customCallback.h attualmente fa quanto segue:
Il PoC nella funzione handleCallback in broker.py attualmente fa quanto segue:
process_encoded_request(encoded_request)usage: broker.py [-h] --host HOST --port PORT
dove host e port puntano al listener http sul tuo teamserver. Il broker analizza la richiesta http e la invia al listener effettivo.
Questo è probabilmente il modo "più pigro" di farlo, ma anche uno dei più stabili. Fondamentalmente avvolge l'intera richiesta HTTP e la spedisce al broker come preferisci, che poi la invia al teamserver per davvero, per essere eseguita come un beacon HTTP, totalmente trasparente per il teamserver.
C'è un'implementazione (tecnicamente) più pulita che ho provato che prevedeva l'uso di un profilo Malleable C2 minimale (ho usato quello di GraphStrike, in realtà) e l'estrazione dei diversi componenti dei dati del beacon secondo le specifiche malleable all'interno degli hook di wininet (id, metadata, output, ecc.). Questo avrebbe reso le dimensioni dei blob di callback leggermente più piccole, ma quell'implementazione è stata abbandonata perché il codebase diventava inutilmente disordinato a causa del parsing delle richieste e richiedeva anche l'uso di quel profilo specifico (che non è un grosso problema, ma è un po' hacky).
Ho ritenuto che questa implementazione fosse migliore perché è meno dipendente dal profilo malleable hacky (tecnicamente richiede ancora che l'output della risposta del beacon sia inviato nel corpo della risposta, ma è l'unico requisito) e il codice era 10 volte più facile da leggere.
Vale anche la pena notare che non c'è offuscamento o crittografia sul json della richiesta http oltre alla codifica base64 - sei libero di aggiungere la tua, ma poiché i callback di Beacon sono già crittografati, tecnicamente nessun dato è a rischio di essere decifrato. La cosa peggiore che potrebbe accadere è che il blob base64, se recuperato, potrebbe essere identificato come una richiesta HTTP. Fate con queste informazioni ciò che volete.
Sì, ho usato un LLM per scrivere parte del codice e dei commenti, a nessuno piace scrivere documentazione o scrivere parsing JSON di boilerplate in C da zero. Fate causa.
Solito disclaimer, non sono responsabile per eventuali crimini contro l'umanità che potresti commettere o per il modo nucleare che potresti causare usando questo pezzo di codice mal scritto.