Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
Inline-Execute-PE — Esegui eseguibili Windows non gestiti nei Beacon di CobaltStrike | Kitploit
Strumenti/GitHubGitHub/octoberfest7/inline-execute-pe
Escalation di Privilegi
GitHuboctoberfest7/inline-execute-pe

Inline-Execute-PE

Esegui eseguibili Windows non gestiti nei Beacon di CobaltStrike

Vedi Repository
7231033 anni faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

Inline-Execute-PE

DICHIARAZIONE DI NON RESPONSABILITÀ:

Questo progetto è complesso e la mancata comprensione del suo funzionamento e un test adeguato possono causare il crash dei Beacon e la perdita di accesso!

Ti consiglio vivamente di leggere tutta la documentazione fino alla sezione "Considerazioni progettuali e commento"!

Introduzione

Inline-Execute-PE è una suite di file oggetto Beacon (BOF) e un corrispondente script Aggressor per CobaltStrike che consente agli Operatori di caricare eseguibili Windows non gestiti nella memoria del Beacon ed eseguirli, recuperando l'output e visualizzandolo nella console del Beacon.

Questo consente agli Operatori di utilizzare molti strumenti di terze parti (Mimikatz, Dsquery, strumenti Sysinternals, ecc.) senza doverli scrivere su disco, riformattarli in codice indipendente dalla posizione usando uno strumento come Donut, o creare un nuovo processo per eseguirli.

Questi eseguibili vengono mappati nella memoria del Beacon in modo da poter essere eseguiti ripetutamente senza doverli inviare sulla rete, allocare nuova memoria e creare un nuovo processo conhost.exe ogni volta.

Gli eseguibili caricati nei Beacon sono accessibili e possono essere eseguiti da tutti i client CobaltStrike connessi al Team Server di CobaltStrike.

Inline-Execute-PE è stato progettato per Beacon x64 ed eseguibili Windows C o C++ x64 compilati con Mingw o Visual Studio. Questo progetto non supporta eseguibili x86 o eseguibili x64 scritti in un linguaggio diverso o compilati con un compilatore diverso.

Configurazione

Clona il repository ed esegui opzionalmente make per ricompilare i BOF.

Carica Inline-Execute-PE.cna nel client CobaltStrike. Assicurati che la directory in cui è in esecuzione CobaltStrike sia scrivibile dal tuo utente; Inline-Execute-PE crea lì un file di testo (petable.txt) per garantire la disponibilità dei dati necessari al funzionamento di Inline-Execute-PE.

Comandi

Inline-Execute-PE comprende 3 comandi orientati al target che eseguono BOF e 3 comandi interni che manipolano la struttura dati del progetto:

Orientati al target:

  1. peload
  2. perun
  3. peunload

Struttura dati interna:

  1. petable
  2. peconfig
  3. pebroadcast

peload

peload è l'inizio di Inline-Execute-PE. Questo comando viene utilizzato per caricare un PE nella memoria del Beacon. Esegue le seguenti azioni principali:

  1. Invia il PE specificato sulla rete al Beacon OPPURE invia il nome del PE da leggere dal disco sulla macchina target
  2. Crea una struttura nella memoria del Beacon per contenere vari puntatori e handle necessari a Inline-Execute-PE durante il suo ciclo di vita
  3. Alloca memoria nel Beacon e scrive il PE con protezione RW
  4. Cifra XOR il PE in memoria usando una chiave specificata dall'utente
  5. Alloca un altro blocco di memoria e copia il PE cifrato XOR in esso. Ciò è necessario per poter "ripristinare" il PE per le esecuzioni successive
  6. Genera un processo figlio conhost.exe sotto il Beacon per inizializzare stdin/stdout/stderr
  7. Reindirizza stdout e stderr a una pipe anonima in modo che l'output del PE possa essere catturato

perun

perun è il secondo passo di Inline-Execute-PE. Esegue le seguenti azioni principali:

  1. Invia gli argomenti della riga di comando sulla rete al Beacon
  2. Decifra XOR il PE in memoria
  3. Corregge la tabella di importazione del PE, hookando determinate API relative agli argomenti della riga di comando e all'uscita dai processi
  4. Cambia la protezione della memoria del PE in RWX
  5. Esegue il PE in un proprio thread
  6. Cattura l'output dal PE e lo restituisce a CobaltStrike
  7. Ripristina la protezione della memoria del PE in RW
  8. Sovrascrive il PE in memoria con la copia XOR creata durante peload

peunload

peunload viene chiamato per rimuovere il PE dalla memoria del Beacon quando un Operatore ha finito o desidera caricare un PE diverso. Esegue le seguenti azioni principali:

  1. Chiude gli handle e i puntatori a file creati durante peload
  2. Termina il processo conhost.exe creato durante peload
  3. Azzera e poi libera entrambe le copie del PE in memoria
  4. Tenta di scaricare eventuali DLL caricate dal PE nel processo Beacon (opzionale)

petable

petable viene utilizzato per visualizzare informazioni riguardanti tutti i PE attualmente caricati nei Beacon.

Ogni client CobaltStrike ha il proprio petable; Inline-Execute-PE fa di tutto per garantire la sincronizzazione dei suoi dati tra tutti i client CobaltStrike connessi in modo che i PE possano essere utilizzati da tutti gli Operatori. Per maggiori informazioni, vedi "Considerazioni progettuali e commento".

image

peconfig

peconfig viene utilizzato per configurare le opzioni relative al funzionamento di Inline-Execute-PE. Le due opzioni attuali che possono essere modificate sono:

  1. Timeout. Questo stabilisce quanto tempo perun attenderà il completamento del PE prima di terminarlo. Esiste come salvaguardia nel caso in cui vengano forniti argomenti errati a un PE che ne causino l'esecuzione senza fine/il mancato completamento. Questa impostazione è di 60 secondi per impostazione predefinita, ma può essere modificata per supportare PE con tempi di esecuzione più lunghi.
  2. UnloadLibraries. Questa opzione controlla se peunload tenterà di liberare le DLL dal processo Beacon caricate dal PE. È impostata su TRUE per impostazione predefinita. Alcuni PE causano problemi quando le DLL vengono scaricate dal processo Beacon e possono causare il crash del Beacon, nel qual caso è meglio lasciare tutte le DLL caricate dal PE nel processo Beacon. Ciò è stato osservato quando si utilizza powershell.exe (forse perché carica il CLR .NET nel processo Beacon).

pebroadcast

pebroadcast può essere utilizzato per trasmettere manualmente il contenuto del petable di un client a tutti gli altri client CobaltStrike connessi.

Ogni altro client CobaltStrike aggiornerà il proprio petable con i dati trasmessi. Non dovrebbe mai essere realmente necessario, ma la funzione esiste per sicurezza.

Utilizzo

Usa peload per caricare un PE nella memoria del Beacon image

In alternativa, se c'è un PE sulla macchina target che vuoi usare senza creare un nuovo processo, fornisci il percorso e lo switch --local image

Chiama perun, passando eventuali argomenti al PE caricato image

I doppi apici negli argomenti devono essere escaped con backslash image

Se hai identificato che un PE causa problemi quando si tenta di liberare le DLL durante lo scaricamento, usa peconfig per impostare unloadlibraries su false image

Una volta che hai finito di usare un PE, chiama peunload per pulirlo dal Beacon image

Un PE diverso ora può essere caricato nel Beacon image

Timeout di perun

Devi prestare attenzione agli argomenti della riga di comando che passi al PE; alcuni PE si bloccheranno immediatamente se forniti con argomenti errati, mentre altri verranno eseguiti all'infinito, causando la mancata ricontattazione del Beacon anche se il processo è ancora in esecuzione.

Ciò può essere visto con Mimikatz.exe quando 'exit' non viene specificato alla fine dell'elenco degli argomenti image

...

image

Inline-Execute-PE terminerà il thread del PE in esecuzione dopo che è stato raggiunto il valore di timeout specificato. Ciò consente al Beacon di riprendere le comunicazioni normali (il Beacon non ricontatta fino al completamento del BOF perun). Mentre i normali comandi di CobaltStrike e altri BOF possono ancora essere utilizzati in questo Beacon, Inline-Execute-PE è ora disabilitato; quando un PE in esecuzione viene terminato in questo modo, sembra danneggiare stdout e stderr nel processo Beacon, e i PE caricati successivamente non funzionano correttamente.

Il PE può (e dovrebbe) essere comunque scaricato dalla memoria del Beacon, tuttavia guardando petable si vedrà che questo Beacon potrebbe non avere più PE aggiuntivi caricati al suo interno. image

È fondamentale testare i PE che si desidera eseguire utilizzando Inline-Execute-PE e prestare attenzione quando si forniscono argomenti della riga di comando a perun. Alcuni PE sono più tolleranti di altri.

Suggerimenti, Trucchi e Osservazioni

Di seguito sono riportate, in nessun ordine particolare, alcune osservazioni fatte durante i test e lo sviluppo riguardo a determinati PE che gli utenti potrebbero voler caricare nel Beacon.

  1. Usare peunload su Powershell.exe di solito provoca il crash del Beacon quando UnloadLibraries è TRUE; credo che ciò sia dovuto al fatto che Powershell.exe carica il CLR.
  2. Cmd.exe farà crashare il Beacon a meno che '/c' non venga utilizzato come primo argomento. Ad esempio 'perun /c cd' è ok, 'perun cd' no.
  3. Mimikatz.exe farà crashare il Beacon se è stato caricato, usato, scaricato e poi caricato di nuovo SE UnloadLibraries era TRUE durante il primo peunload.
  4. Alcuni PE sono programmati per stampare il loro menu di aiuto quando escono; questi non verranno visualizzati perché le chiamate a ExitProcess e exit() e simili vengono hookate e reindirizzate a ExitThread in modo che il PE non faccia uscire il nostro processo Beacon.
  5. Alcuni PE non sono molto bravi a liberare la memoria quando hanno finito e si affidano al fatto che la memoria venga liberata quando il processo termina; poiché il PE è in esecuzione all'interno del processo Beacon (e quindi il processo non esce quando il PE termina), il Beacon può tendere ad ingrossarsi man mano che più PE vengono caricati ed eseguiti al suo interno. Osserva questo durante i test usando qualcosa come Process Explorer e tienilo presente durante le operazioni.
  6. Psexec di Sysinternals non sembra funzionare; mentre viene eseguito, lamenta che l'handle alla macchina remota non è valido. In pratica, se si volesse usare qualcosa come psexec, sarebbe probabilmente meglio ottenerlo usando il proxy socks di CobaltStrike e una versione da attack-box di psexec comunque.
  7. Generare un nuovo beacon da usare con Inline-Execute-PE probabilmente non è una cattiva idea, specialmente mentre si prende confidenza con come diversi PE interagiscono e funzionano all'interno del framework. Due è uno, uno è nessuno.
  8. Se c'è un LOLBIN che vuoi usare senza la telemetria della creazione di un nuovo processo, usa lo switch --local con peload e leggi dal disco sul sistema target. Questo può essere utile anche per evitare problemi di versione.

IOC e AV/EDR

Gli IOC associati a Inline-Execute-PE includono, ma non sono limitati a:

  1. Allocazione di memoria usando VirtualAlloc
  2. Modifica delle protezioni di memoria sulla memoria allocata tra RW e RWX
  3. Creazione di un processo figlio conhost.exe
  4. Caricamento di DLL richieste dal PE mappato
  5. Qualsiasi azione eseguita dal PE effettivo; ad esempio, Mimikatz che tocca LSASS

AV/EDR

Non ho sottoposto questo a un test completo contro un EDR durante lo sviluppo, in parte per pigrizia e in parte per mancanza di disponibilità di un ambiente di test. Tuttavia è stato testato contro l'ultima patch di Windows Defender (che nella mia esperienza è un buon prodotto AV).

Mimikatz.exe è probabilmente il PE più sospetto e conosciuto che viene in mente come candidato per l'uso con Inline-Execute-PE. Ho scoperto che la capacità di Windows Defender di rilevare Mimikatz in esecuzione usando Inline-Execute-PE dipendeva dal processo in cui era in esecuzione Beacon.

Un beacon in esecuzione in un eseguibile standalone (pensa a beacon.exe con artifact kit in modo che possa eseguire e funzionare normalmente oltre Defender) verrà rilevato quando si utilizza Mimikatz.exe con Inline-Execute-PE.

Un beacon in esecuzione in un processo Windows (iniettato in Explorer.exe, notepad.exe, ecc. o DLL sideloaded in un processo legittimo) NON verrà rilevato quando si utilizza Mimikatz.exe con Inline-Execute-PE.

Per quanto riguarda gli EDR che eseguono hooking a livello utente, come ho detto, non ho testato ma ho i seguenti pensieri generali:

Dato che il PE è in esecuzione all'interno del processo Beacon, che presumibilmente hai già disancorato/aggiornato NTDLL al suo interno, penso che non dovresti avere troppi problemi con le chiamate API effettuate dal PE che vengono segnalate. Gli stessi problemi riguardanti ciò che il PE effettivamente fa (tocca processi, modifica chiavi di registro, ecc.) si applicano ancora.

Considerazioni progettuali e commento

Un paio di mesi fa mi sono imbattuto in RunPE-In-Memory e ho pensato di provare a convertirlo in un BOF per CobaltStrike. Il viaggio che ne è seguito è stato molto più complesso e ha richiesto molto più tempo del previsto. Questo progetto è stato particolarmente impegnativo perché non è uno strumento autonomo di per sé, ma è uno strumento utilizzato per eseguire altri strumenti. Ciò richiede una grande flessibilità e sforzo verso la compatibilità con un'ampia gamma di PE e tutti i diversi modi in cui quei PE potrebbero svolgere lo stesso compito (ottenere argomenti, terminare, ecc.).

All'inizio, Inline-Execute-PE era stato immaginato come un BOF tutto-in-uno, responsabile del caricamento, dell'esecuzione e della liberazione di un PE in un Beacon. Circa 3 settimane dopo l'inizio del progetto, quando avevo un POC completato al ~75%, ho trovato Pezor che era stato rilasciato ~1,5 anni fa e faceva già quasi tutto ciò che stavo cercando di fare; la differenza principale era che Pezor chiamava Donut internamente per trasformare il PE in shellcode, piuttosto che mappare manualmente il PE originale in memoria.

Questa scoperta è stata gradita sotto un certo aspetto e deludente sotto un altro; era fenomenale avere un progetto maturo da cui trarre ispirazione e aiutarmi a superare alcuni punti critici nel mio codice, ma scoraggiante perché avevo effettivamente reinventato la ruota senza saperlo. Dopo aver letto su Pezor e aver pensato al suo design, ad alcuni aspetti di tradecraft e alle esigenze operative della mia organizzazione, ho modificato il corso di Inline-Execute-PE in quello che vedi oggi. Questa decisione è stata guidata da diversi fattori che verranno discussi di seguito, così come alcune delle scelte progettuali più curiose che potrebbero aver sollevato qualche sopracciglio per coloro che hanno letto fino a qui.

Inline-Execute-PE vs Pezor

Esaminando la mia esperienza operativa, mi sono imbattuto in molteplici casi e strumenti in cui dovevo eseguire lo strumento ripetutamente; con Pezor, un Operatore deve inviare ripetutamente il PE sulla rete, creare un conhost.exe, allocare nuova memoria nel Beacon, ecc., il che mi è sembrato potenzialmente indesiderabile considerando AV/EDR. Questo modo di pensare ha portato all'idea di 'caricare' un PE nel Beacon, in modo simile a come puoi caricare un .PS1 nel Beacon per uso ripetuto. Il conhost.exe viene creato quando il PE viene caricato per la prima volta e persiste finché il PE è caricato in memoria; analogamente, la nuova memoria per il PE viene allocata una volta quando viene caricato per la prima volta, e ovviamente eviti di dover inviare il PE sulla rete ogni volta che vuoi usarlo. Il modello adottato da Inline-Execute-PE non è privo di difetti, che ho cercato di affrontare con vari gradi di successo.

Due copie del PE

Una scelta progettuale che dovrebbe saltare all'occhio è il fatto che Inline-Execute-PE mappa il PE nel Beacon DUE VOLTE. Ciò non è certamente desiderabile o una scelta che ho fatto volontariamente, ma è nata dalla necessità. Come accennato in precedenza, Inline-Execute-PE deve hookare diverse funzioni relative agli argomenti della riga di comando nel PE. Poiché il PE mappato viene eseguito all'interno del processo Beacon, il PE tenterà di utilizzare gli argomenti della riga di comando specificati nella sezione PROCESS_PARAMETERS del PEB; per aggirare questo problema, quando il PE chiama una delle varie funzioni che recuperano gli argomenti della riga di comando, dobbiamo indirizzare il PE verso le nostre funzioni personalizzate dove possiamo fornire gli argomenti desiderati così come passati da CobaltStrike usando perun.

Questo funziona bene, ma durante lo sviluppo ho notato qualcosa di strano con diversi PE. La prima volta che il PE veniva eseguito, la funzione personalizzata che abbiamo fornito all'IAT del PE veniva chiamata correttamente, tuttavia in tutte le volte successive in cui il PE veniva eseguito e venivano forniti argomenti diversi, il PE non chiamava la funzione personalizzata e quindi non riceveva gli argomenti passati da CobaltStrike. Non sono sicuro di cosa stia effettivamente accadendo sotto il cofano, ma sono portato a credere che dopo che il PE è stato eseguito una volta, copia gli argomenti della riga di comando da qualche parte in memoria, e nelle esecuzioni successive cerca quella posizione in memoria prima di chiamare le funzioni hookate per recuperare gli argomenti della riga di comando come ha fatto la prima volta. Ho corroborato questa teoria recuperando la posizione in memoria dove risiedeva un puntatore a un altro puntatore all'array di puntatori contenente gli argomenti, e modificando manualmente questa posizione in memoria per contenere il puntatore corretto ad ogni esecuzione. Questo ha funzionato per le funzioni __getmainargs e __wgetmainargs, ma altri PE chiamano funzioni alternative come __p___argv e __p___argc per le quali questo metodo non ha funzionato.

Per poter "ripristinare" il PE in uno stato in cui avrebbe effettivamente chiamato le funzioni hookate per recuperare gli argomenti, ho dovuto creare una seconda copia del PE in memoria durante peload. Anche questa copia è cifrata XOR e rimane con protezioni RX per l'intera durata del ciclo di vita di Inline-Execute-PE, semplicemente utilizzata per sovrascrivere la copia del PE che viene effettivamente eseguita usando perun. Come accennato, non è una soluzione perfetta, ma è una soluzione generica che copre tutti i PE senza bisogno di perdersi tra le erbacce cercando di trovare una soluzione per tutti i diversi PE là fuori e le diverse API che utilizzano.

Conhost.exe

Con uno dei principali punti di forza di Inline-Execute-PE che è la possibilità di eseguire strumenti senza creare nuovi processi, è un duro colpo dover... creare un nuovo processo (conhost.exe) per farlo. Questo requisito deriva dal fatto che i flussi standard (stdin/stdout/stderr) non vengono inizializzati nei programmi Windows a meno che non sia presente una console. Nel nostro caso non abbiamo affatto bisogno della console; i flussi standard vengono reindirizzati a una pipe anonima e catturati in questo modo, ma senza il conhost i flussi non vengono inizializzati e non possono essere reindirizzati.

Inline-Execute-PE affronta il problema del conhost nello stesso modo di Pezor, chiama AllocConsole e immediatamente dopo la nasconde alla vista usando ShowWindow. Su una VM Windows 11 con 8 GB di RAM non vedo mai la finestra della console lampeggiare e poi scomparire, ma il risultato può variare a seconda del sistema target.

Ho parlato con uno sviluppatore che lavora su un C2 commerciale molto avanzato che ha recentemente rilasciato un equivalente nativo (ok, una versione molto più avanzata) di Inline-Execute-PE e mi ha detto che sono riusciti a evitare di generare un conhost.exe "ingannando Windows facendogli credere di avere una console". Con questo indizio ho passato circa una settimana a setacciare Internet per documentazione su come i programmi Windows interagiscono con conhost, cercando di tracciare le chiamate API associate alle funzioni di scrittura e alla console in WinDBG, e persino esaminando il codice sorgente di Windows Terminal che sorprendentemente è disponibile su Github. Anche se ho imparato molto sul PEB e sulle cose relative ai flussi standard, sono uscito dall'altra parte di questo a mani vuote. Sospetto che la strada da percorrere potrebbe coinvolgere il patching di alcune funzioni relative alla console in kernel32, ma non lo so. Onestamente sono piuttosto deluso di non essere riuscito a trovare una soluzione qui, ma essendo autodidatta e con solo pochi anni di carriera alle spalle, è probabilmente prevedibile.### Timeout PE e Recupero

Tutti coloro che hanno mai provato a scrivere un BOF sanno che, nonostante tutti i vantaggi che ne derivano, un grande pericolo risiede nel fatto che un errore o un crash nel tuo BOF può e ucciderà il tuo Beacon. Il pericolo è amplificato in questo progetto dalla natura di quanto controllo gli utenti abbiano sui dati passati a Inline-Execute-PE e da quante poche misure di sicurezza possano essere facilmente o in modo affidabile messe in atto da me, lo sviluppatore. Gli utenti potrebbero, ad esempio, far crashare il loro Beacon caricando un PE x86 in un Beacon x64, o, molto più comunemente, passando argomenti errati al PE mappato, come ho accennato in precedenza. Sebbene non possa impedire agli utenti di far crashare i loro Beacon con argomenti errati per i loro PE, posso provare a recuperare il loro Beacon nel caso di un PE in esecuzione infinita, come nel caso di Mimikatz quando 'exit' non è specificato.

Idealmente sarei in grado di fermare l'esecuzione del PE, consentendo al Beacon di riprendere le normali funzioni, e poi immediatamente lasciare che l'utente riprovi con gli argomenti (si spera) corretti questa volta. In pratica, ho scoperto che terminare il PE sembra rompere i FILE* associati a stdout/stderr, e anche scaricare completamente il PE e poi ricaricarlo da capo non risolve il problema; sono rotti a livello di processo.

Per terminare un PE che continua a funzionare oltre l'opzione 'timeout', viene chiamato TerminateThread sull'handle restituito da CreateThread. Questo non consente al thread di uscire in modo pulito da nulla, quindi ha senso che alcune cose possano rompersi. Ho provato a mitigare questo implementando thread hijacking, con l'obiettivo di sospendere il thread del PE e reindirizzare la sua esecuzione all'API ExitThread(). La speranza era che, se fosse stato il thread ad avviare le procedure di uscita (al contrario di essere terminato forzatamente dall'esterno), ciò potesse consentire a stdout/stderr di continuare a funzionare, ma ho finito per avere lo stesso problema (oltre a sperimentare l'incapacità di sospendere il thread del PE nel caso di Mimikatz).

Non riuscendo a mitigare questo problema, ho scelto semplicemente di impedire agli utenti di continuare a eseguire il PE o di caricare ulteriori PE nel Beacon interessato (il che COMPORTEREBBE un crash). Questo è un altro caso in cui Inline-Execute-PE non raggiunge il livello che vorrei, ma mi sono accontentato del fatto che l'Operatore avrebbe almeno ancora il suo Beacon e potrebbe usarlo per le normali funzionalità.

Struttura Dati di Inline-Execute-PE

Una parte impegnativa di questo progetto è stata garantire la disponibilità dei PE caricati nei Beacon a tutti i Client CobaltStrike connessi al Team Server. I dati di Inline-Execute-PE sono memorizzati in strutture create da Inline-Execute-PE.cna, che devono essere caricate in ogni Client che desidera utilizzare lo strumento; di conseguenza, queste strutture dati risiedono all'interno di ogni Client, non sul Team Server. Se questi dati risiedessero in un'unica posizione centrale (TS), sarebbe banale recuperarli da ogni Client e tutto ciò sarebbe un non problema; se il Team di CobaltStrike integrasse formalmente una funzionalità come Inline-Execute-PE in CobaltStrike, sono certo che questa sarebbe la direzione che prenderebbero. Ma essendo questo un add-on della comunità, ci accontentiamo di ciò che abbiamo.

Ci sono un paio di scenari diversi di cui preoccuparsi per garantire che ogni Client CobaltStrike abbia i dati più recenti e accurati riguardanti i PE caricati nei Beacon:

  1. Nuovi Client che si connettono al TS e necessitano della petable corrente
  2. Casi in cui un solo Client è connesso al TS e riavvia CobaltStrike (perdendo così la petable memorizzata nella memoria del Client)
  3. Il Client A apporta una modifica ai dati di Inline-Execute-PE che deve essere comunicata al Client B

È stato adottato un approccio multi-prong per affrontare questi scenari. Per gestire il caso in cui un solo Client CobaltStrike è connesso al TS (ed è quindi l'unica entità che possiede i dati della petable), ogni volta che il Client altera la petable (peload, peconfig, peunload, ecc.), scrive anche il contenuto della sua petable in un file di testo locale situato nella directory di CobaltStrike. Se il Client esce/riavvia, o quando Inline-Execute-PE.cna viene ricaricato, tenterà prima di leggere dal file petable.txt locale per popolare la sua petable in memoria.

Quando più Client sono connessi a un TS e un nuovo Client si unisce (come da Event Log), ogni Client recupera un elenco di tutti gli utenti connessi al TS e lo ordina alfabeticamente. Il Client che è il primo in quell'elenco viene selezionato come Client "Broadcast" e, dopo aver aspettato 5 secondi (per consentire al nuovo Client di inizializzarsi e leggere il suo petable.txt locale), invierà messaggi (Actions) nell'Event Log per ogni voce nella sua petable. Tutti i client (eccetto quello che fa il broadcast) leggeranno questi messaggi e aggiorneranno le loro petable con le informazioni trasmesse; questo include l'aggiornamento delle voci esistenti e l'aggiunta di eventuali voci aggiuntive che le loro rispettive petable non contengono.

Le operazioni normali che coinvolgono Inline-Execute-PE si basano anche sull'invio di messaggi nell'Event Log. Quando il Client A esegue peload, viene trasmesso un messaggio contenente tutte le informazioni pertinenti della petable; TUTTI i client aggiornano le loro rispettive petable analizzando questi messaggi dell'Event Log trasmessi usando l'hook "on Event_Action". Vengono apportate modifiche anche ai dati di Inline-Execute-PE quando peload e peunload terminano l'esecuzione dei loro BOF; queste modifiche vengono comunicate da Beacon (ad esempio, dopo aver eseguito peload, Beacon richiama con la posizione di memoria della struct pMemAddrs) e come tali sono visibili a tutti i Client connessi, che aggiornano le loro rispettive petable usando l'hook "on Beacon_Output".

Questi sforzi separati combinati consentono a Inline-Execute-PE di sincronizzare in modo efficiente e affidabile i dati critici tra più Client.

Crediti

Questo progetto non sarebbe stato possibile senza i seguenti progetti e risorse che sono stati ampiamente consultati e da cui hanno avuto origine parti fondamentali di questo progetto. Un grande ringraziamento agli autori per il loro codice e la loro visione.

  1. RunPE-In-Memory
  2. Pezor
  3. Molto StackOverflow
Scarica lo strumento