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
BeatRev — POC per frustrare/sconfiggere gli analisti di malware | Kitploit
Strumenti/GitHubGitHub/octoberfest7/beatrev
Reverse EngineeringAnalisi MalwareApprendimento e FormazioneSviluppo Payload
GitHuboctoberfest7/beatrev

BeatRev

POC per frustrare/sconfiggere gli analisti di malware

Vedi Repository
1542214 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

BeatRev Versione 2

Dichiarazione di non responsabilità

Il lavoro che segue è un Proof of Concept (POC) per consentire al malware di "chiave" stessa a una particolare vittima al fine di frustrare gli sforzi degli analisti di malware.

Non mi assumo alcuna responsabilità per l'uso malevolo di qualsiasi idea o codice contenuto in questo progetto. Fornisco questa ricerca per istruire ulteriormente i professionisti della sicurezza informatica e fornire formazione/spunti di riflessione aggiuntivi per Analisti di Malware, Reverse Engineers e Blue Team in generale.

TLDR

La prima volta che il malware viene eseguito su una vittima, crittografa AES il payload effettivo (una RDLL) utilizzando dati ambientali di quella vittima. Ogni volta successiva in cui il malware viene eseguito, raccoglie le stesse informazioni ambientali, decrittografa AES il payload memorizzato come array di byte all'interno del malware e lo esegue. Se la decrittografia fallisce o il payload non viene eseguito, il malware si elimina da solo. Protezione contro i reverse engineer e gli analisti di malware.

Aggiornato il 6 GIUGNO 2022

image

Non mi sentivo soddisfatto di questo progetto, quindi ci sono tornato e ho fatto una riscrittura piuttosto sostanziale. La ricerca originale e le tecniche sono disponibili Qui.

Le modifiche principali sono le seguenti:

  1. Ho rilasciato tutto il codice sorgente
  2. Ho integrato la ReflectiveDLL di Stephen Fewer nel progetto per sostituire Stage2
  3. Ho formattato alcuni array di byte in questo progetto in formato stringa e li ho analizzati con UuidFromStringA. Questo Repo è stato usato come modello. Questo è stato fatto per ridurre l'entropia di Stage0 e Stage1
  4. Stage0 ha ricevuto una buona dose di elusione dell'antivirus integrata. Grazie al Progetto Ares di Cerbersec per l'ispirazione
  5. L'applicazione builder per produrre Stage0 è stata inclusa

Ci sono diverse cose che potrebbero essere prese dal codice sorgente di questo progetto per essere utilizzate altrove. Si spera che possa essere utile a qualcuno.

Problemi con la release originale e mitigazioni

C'erano alcune carenze nella release originale di BeatRev che ho deciso di cercare di risolvere.

Stage2 era in precedenza un eseguibile autonomo memorizzato come flusso di dati alternativo (ADS) di Stage1. Per ottenere la crittografia AES per vittima e la successiva decrittografia ed esecuzione, ogni volta che Stage1 veniva eseguito, leggeva l'ADS, lo decrittografava, riscriveva nell'ADS, chiamava CreateProcess, e poi ri-crittografava Stage2 e lo riscriveva su disco nell'ADS. C'erano molte operazioni di I/O e la chiamata CreateProcess ovviamente non era ideale.

Mi sono imbattuto nella ricerca di Steven Fewer riguardante le Reflective DLL e sembrava essere una buona soluzione. Stage2 ora è una RDLL; il nostro malware/runner di shellcode/qualsiasi cosa vogliamo proteggere può essere portato in formato RDLL e memorizzato come array di byte all'interno di Stage1 che viene poi decrittografato in fase di esecuzione ed eseguito da Stage1. Questo rimuove tutte le operazioni di I/O e la chiamata CreateProcess della Versione 1 ed è un cambiamento gradito.

Stage1 non aveva alcun tipo di misura di elusione dell'antivirus programmata; questo era intenzionale, poiché è un lavoro extra e non era realmente lo scopo di questa ricerca. Durante la riscrittura l'ho preso come una sfida aggiuntiva e ho aggiunto l'hashing delle API per rimuovere le funzioni dalla tabella degli indirizzi di importazione di Stage1. Questo ha aiutato con il rilevamento e Stage1 ha un tasso di rilevamento di 4/66 su VirusTotal. Mi sentivo a mio agio nel caricare Stage1 dato che è già associato al computer originale su cui è stato eseguito e la firma del file cambia costantemente a causa della crittografia AES che avviene.

Di recente ho iniziato a prestare attenzione all'entropia come mezzo per rilevare il malware; per cercare di abbassare l'entropia altrimenti molto alta che un enorme blob binario crittografato AES dà a un eseguibile, ho esaminato l'integrazione di shellcode memorizzato come UUID. Poiché il binario è memorizzato in rappresentazione stringa, c'è un'entropia complessiva inferiore nell'eseguibile. Utilizzando questa tecnica, l'entropia di Stage0 è ora ~6.8 e Stage1 ~4.5 (su una scala massima di 8).

Infine, è una grande seccatura integrare e produrre uno Stage0 completo a causa di tutti i pezzi che devono essere manipolati. Per semplificare, ho creato un'applicazione builder che accetta un file template Stage0.c, uno stub di Stage1, uno stub di Stage2 e un file raw shellcode (questo è stato costruito attorno a Stage2 come runner di shellcode contenente shellcode CobaltStrike) e produce un payload Stage0 compilato da utilizzare sul target.

Dettagli tecnici

Il codice della Reflective DLL di Stephen Fewer contiene alcune istruzioni specifiche del compilatore Visual Studio; sono sicuro che sia possibile portare la tecnica su MingW ma non ho le competenze per farlo. Il problema principale qui è che lo shellcode di CobaltStrike (senza stato è ~265K) deve andare all'interno della RDLL e essere compilato. Per aggirare questo e integrarlo bene con il resto del processo, ho scritto la mia RDLL Stage2 in modo che contenga una variabile globale di memoria delle dimensioni dello shellcode CS; questo blocco di memoria di ~265K ha un piccolo segnaposto al suo interno che può essere individuato nel binario compilato. Il codice in src/Stage2 ha già questo aggiunto.

Una volta compilato, questo Stage2stub viene trasferito su kali dove può essere eseguita una patch binaria per inserire il vero shellcode CS nel posto di memoria che gli spetta. Questo produce lo Stage2 completo.

Per evitare il disastro di I/O e CreateProcess descritto in precedenza, lo Stage2 completo deve anche essere applicato come patch nello Stage1 compilato da parte di Stage0; questo è necessario per permettere a Stage2 di essere crittografato una volta sul target, oltre a impedire che Stage2 venga memorizzato separatamente su disco. Lo stesso concetto descritto in precedenza per Stage2 viene eseguito da Stage0 sul target per assemblare il payload finale Stage1. Va notato che la funzione memmem viene utilizzata per individuare il segnaposto all'interno di ogni stub; questa funzione non è disponibile su Windows, quindi è stata utilizzata un'implementazione personalizzata. Grazie a Foxik384 per il suo codice.

Per eseguire una patch binaria, dobbiamo allocare la memoria necessaria in anticipo; questo ha un effetto cumulativo, poiché Stage1 deve ora essere abbastanza grande da contenere anche Stage2. Con il passaggio aggiuntivo di convertire Stage2 in una stringa UUID, Stage2 aumenta di dimensioni, così come Stage1 per contenerlo. Una RDLL Stage2 con una dimensione compilata di ~290K produce un payload Stage0 di ~1.38M e un payload Stage1 di ~700K.

L'applicazione builder supporta solo la creazione di EXE x64. Tuttavia, con un po' più di lavoro, in teoria si potrebbe fare Stage0 come DLL, così come Stage1, e far sì che l'intero ciclo di vita esista come un hijack di DLL invece di un eseguibile autonomo.

Istruzioni

Queste istruzioni ti guideranno nell'utilizzo di questo POC.

  1. Compila Builder usando gcc -o builder src/Builder/BeatRevV2Builder.c
  2. Modifica la variabile sc_length in src/Stage2/dll/src/ReflectiveDLL.c in modo che corrisponda alla lunghezza del file raw shellcode utilizzato con il builder (ho incluso fakesc.bin come esempio)
  3. Compila Stage2 (in Visual Studio, il progetto ReflectiveDLL utilizza alcune istruzioni specifiche del compilatore VS)
  4. Sposta il stage2stub.dll compilato su kali, modifica src/Stage1/newstage1.c e definisci stage2size come la dimensione di stage2stub
  5. Compila stage1stub usando x86_64-w64-mingw32-gcc newstage1.c -o stage1stub.exe -s -DUNICODE -Os -L /usr/x86_64-w64-mingw32/lib -l:librpcrt4.a
  6. Esegui il builder usando la sintassi: ./builder src/Stage0/newstage0_exe.c x64 stage1stub.exe stage2stub.dll shellcode.bin
  7. Il builder produrrà dropper.exe. Questo è un payload Stage0 formattato e compilato da utilizzare sul target.

Release originale di BeatRev

Introduzione

Circa 6 mesi fa mi sono reso conto che, sebbene avessi imparato e fatto molto riguardo al malware e all'elusione di AV/EDR, avevo speso pochissimo tempo a preoccuparmi di eludere o sconfiggere il reverse engineering e l'analisi del malware. Questo per alcune buone ragioni:

  1. Non so nulla di analisi del malware o reverse engineering
  2. Quando si parla di lavoro Red Team legale e autorizzato, non c'è davvero bisogno di cercare di frustrare o sconfiggere un reverse engineer perché l'attività dovrebbe essere stata deconflittata molto prima di arrivare a quella fase.

Tuttavia, è stato un interessante esperimento mentale e avevo alcuni colleghi che SAPEVANO di analisi del malware con cui confrontarmi. Sembrava una sfida di una portata completamente diversa rispetto all'elusione di AV/EDR e ho deciso di tentare.

Premessa

La mia premessa iniziale era che il malware, la prima volta che veniva eseguito, si sarebbe in qualche modo "chiave" a quella macchina vittima; eventuali tentativi successivi di eseguirlo avrebbero valutato qualcosa nell'ambiente target e lo avrebbero confrontato con una corrispondenza nel malware. Se questi due fattori corrispondevano, veniva eseguito come previsto. Se non corrispondevano (come nel caso in cui il campione fosse stato trasferito in una sandbox di un analista di malware), il malware si eliminava da solo (ancora una volta basandomi pesantemente sul lavoro di LloydLabs e il suo delete-self-poc).

Questa "chiave" deve essere qualcosa di "unico" per il computer vittima. Idealmente sarà una combinazione di diverse informazioni, e ulteriormente offuscata. Ad esempio, potremmo raccogliere il nome host del computer e la quantità di RAM installata; questi due valori possono poi essere concatenati (es. Client018192MB) e quindi hashizzati utilizzando una funzione definita dall'utente per produrre un numero (es. 5343823956).

Ci sono una miriade di scelte su quali informazioni raccogliere, ma bisogna considerare quali valori un Blue Teamer potrebbe facilmente falsificare; un indirizzo MAC, ad esempio, può sembrare un identificatore "unico" attraente per una vittima, ma gli indirizzi MAC possono essere facilmente impostati manualmente in modo che un Reverse Engineer possa far corrispondere la propria sandbox alla vittima originale. Idealmente, i valori scelti e enumerati dovrebbero essere quelli difficili da replicare per un reverse engineer nel proprio ambiente.

Con un po' di magia di auto-eliminazione, il malware potrebbe leggere se stesso in un buffer, individuare una variabile segnaposto e sostituirla con questo numero, eliminarsi, e poi riscrivere il malware modificato su disco nella stessa posizione. Combinato con un'istruzione if/else in Main, la volta successiva che il malware viene eseguito, rileverà che è già stato eseguito in precedenza e quindi andrà a raccogliere di nuovo il nome host e la quantità di RAM per produrre il numero hashizzato. Questo verrebbe quindi valutato rispetto al numero memorizzato nel malware durante la prima esecuzione (5343823956). Se corrisponde (come nel caso in cui il malware venga eseguito sulla stessa macchina originale), viene eseguito come previsto, ma se viene restituito un valore diverso, chiamerà nuovamente la funzione di auto-eliminazione per rimuovere se stesso dal disco e proteggere l'autore dall'analista di malware.

Questa sembrava un'idea valida in teoria finché non ho parlato con un collega che ha una reale esperienza di analisi del malware e reverse engineering. Mi è stato detto che un reverse engineer sarebbe in grado di osservare l'istruzione condizionale nel malware (if ValorePrimaEsecuzione != GetNomeHostERam()), e visto che il valore atteso è hard-coded da un lato dell'istruzione condizionale, semplicemente modificare i registri per contenere il valore atteso, bypassando completamente l'intero meccanismo di protezione.

Questa nuova conoscenza ha completamente deragliato l'esperimento mentale e, visto che non avevo comunque un uso concreto per una capacità del genere, il progetto si è fermato per circa 6 mesi.

Panoramica

Questo progetto è riemerso alcune volte nei 6 mesi successivi, ma ogni volta è stato poco più che un pensiero fugace, poiché non avevo acquisito nuove conoscenze sul reverse engineering/analisi del malware e ancora non avevo bisogno di una tale capacità. Qualche giorno fa l'idea è riemersa e, sebbene nessuno di questi fattori sia realmente cambiato, suppongo di avere un po' più di conoscenze e questa volta non ho potuto lasciar perdere l'idea.

Tenendo presente il problema menzionato riguardo all'hard-coding dei valori, ho deciso di optare per un design multi-stadio. Li chiamerò Stage0, Stage1 e Stage2.

Stage0: Configurazione. Eseguito sull'infezione iniziale e cancellato successivamente

Stage1: Esecutore. Eseguito ogni volta successiva in cui il malware viene eseguito

Stage2: Payload. Il malware che si desidera proteggere. Genera un processo e inietta shellcode per restituire un Beacon.

Ciclo di vita

Stage0

Stage0 è l'eseguibile fresco consegnato al target dall'attaccante. Contiene Stage1 e Stage2 come array di byte crittografati AES; questo viene fatto per proteggere il malware in transito, o nel caso in cui un difensore riesca in qualche modo a ottenere una copia di Stage0 (cosa che non dovrebbe accadere). La chiave AES e il IV sono contenuti in Stage0, quindi in realtà questo non proteggerà Stage1 o Stage2 da un Blue Teamer competente.

Stage0 esegue le seguenti azioni:

  1. Evasione sandbox.
  2. Si elimina dal disco. È ancora in esecuzione in memoria.
  3. Decrittografa Stage1 utilizzando la chiave AES/IV memorizzata e lo scrive su disco al posto di Stage0.
  4. Raccoglie il nome del processore e il ProductID di Microsoft.
  5. Crea un hash di questo valore e lo riempie per adattarlo a una lunghezza di chiave AES di 16 byte. Questo valore invertito funge da IV AES.
  6. Decrittografa Stage2 utilizzando la chiave AES/IV memorizzata.
  7. Crittografa Stage2 utilizzando la nuova chiave AES/IV specifica della vittima.
  8. Scrive Stage2 su disco come flusso di dati alternativo (ADS) di Stage1.

Alla conclusione di questa sequenza di eventi, Stage0 termina. Poiché è stato eliminato dal disco al passo 2 e non è più in esecuzione in memoria, Stage0 è effettivamente sparito; senza una conoscenza preventiva di questa tecnica, il resto del ciclo di vita del malware sarà molto più confuso di quanto già non sia.

Nel passo 4 vengono raccolti il nome del processore e il ProductID di Microsoft; il ProductID viene recuperato dal Registro, e questo valore può essere modificato manualmente, il che offre una facile opportunità per un Blue Teamer di far corrispondere la propria sandbox all'ambiente target. A seconda delle informazioni ambientali raccolte, questo può diventare più facile o più difficile.

Stage1

Stage1 è stato rilasciato da Stage0 e si trova esattamente nella stessa posizione di Stage0 (incluso il nome). Stage2 è memorizzato come ADS di Stage1. Quando l'attaccante/persistenza esegue successivamente il malware, sta eseguendo Stage1.

Stage1 esegue le seguenti azioni:

  1. Evasione sandbox.
  2. Raccoglie il nome del processore e il ProductID di Microsoft.
  3. Crea un hash di questo valore e lo riempie per adattarlo a una lunghezza di chiave AES di 16 byte. Questo valore invertito funge da IV AES.
  4. Legge Stage2 dall'ADS di Stage1 in memoria.
  5. Decrittografa Stage2 utilizzando la chiave AES/IV specifica della vittima.
  6. Controlla i primi due byte del buffer di Stage2 decrittografato; se non è MZ (decrittografia non riuscita), elimina Stage1/Stage2, termina.
  7. Scrive Stage2 decrittografato di nuovo su disco come ADS di Stage1.
  8. Chiama CreateProcess su Stage2. Se fallisce (decrittografia non riuscita), elimina Stage1/Stage2, termina.
  9. Attende 5 secondi per permettere a Stage2 di eseguire e terminare in modo da poter essere sovrascritto.
  10. Crittografa Stage2 utilizzando la chiave AES/IV specifica della vittima.
  11. Scrive Stage2 crittografato di nuovo su disco come ADS di Stage1.

Si noti che Stage2 DEVE terminare per poter essere sovrascritto; il trucco dell'auto-eliminazione non sembra funzionare su file che sono già ADS, poiché la tecnica di auto-eliminazione si basa sulla rinomina del flusso di dati primario dell'eseguibile. Stage2 sarà idealmente un eseguibile di iniezione o spawn+iniezione.

Ci sono due punti in cui Stage1 potrebbe rilevare di non essere eseguito dalla stessa vittima e eliminare se stesso/Stage2 per proteggere l'attaccante. Il primo è il controllo dell'intestazione eseguibile dopo aver decrittografato Stage2 utilizzando le informazioni ambientali raccolte; in teoria questo passo potrebbe essere bypassato da un reverse engineer, ma è un primo buon controllo. Il secondo punto di protezione è il risultato della chiamata CreateProcess: se fallisce perché Stage2 non è stato decrittografato correttamente, il malware viene eliminato allo stesso modo. Il risultato di questa chiamata potrebbe anche essere modificato per prevenire l'eliminazione da parte del reverse engineer, ma ciò non cambia il fatto che Stage2 è crittografato e inaccessibile.

Stage2

Stage2 è il cuore della catena del malware; è un vero e proprio runner di shellcode/pezzo di malware. Crittografandolo e proteggendolo nel modo in cui abbiamo fatto, le azioni del malware finale sono molto meglio offuscate e protette da reverse engineer e analisti di malware. Durante lo sviluppo ho utilizzato uno dei miei runner di shellcode esistenti contenente shellcode CobaltStrike, ma potrebbe essere qualsiasi cosa l'attaccante voglia eseguire e proteggere.

Impatto, mitigazione e ulteriori lavori

Quindi cosa si ottiene effettivamente con un ciclo di vita del malware come questo? Ci sono alcune caratteristiche interessanti di cui parlare.

I flussi di dati alternativi sono una caratteristica unica dei file system NTFS; ciò significa che la maggior parte dei modi di trasferire il malware dopo l'infezione iniziale rimuoveranno e perderanno Stage2 perché è un ADS di Stage1. Bisognerebbe prestare particolare attenzione per trasferire il campione in modo da preservare Stage2, poiché senza di esso molti reverse engineer e analisti di malware saranno molto confusi su cosa stia accadendo. Gli archivi RAR sono in grado di preservare gli ADS e strumenti come 7Z e Peazip possono estrarre file e i loro ADS.

Come accennato in precedenza, quando il malware che utilizza questo ciclo di vita arriva a un Blue Teamer, dovrebbe essere a Stage1; Stage0 è già passato e Stage2 è già crittografato con le informazioni ambientali raccolte da Stage0. Non sapere che Stage0 sia mai esistito aggiungerà una notevole incertezza alla comprensione del ciclo di vita e alla decrittografia di Stage2.

In teoria (poiché ancora non ho esperienza di reverse engineering), Stage1 dovrebbe poter essere sottoposto a reverse engineering (dopo che i Blue Teamer avranno esaminato alcune copie perché continua a eliminarsi) e le informazioni che Stage1 raccoglie dal sistema target dovrebbero poter essere identificate. A condizione di una risposta ben orchestrata, il Blue Team dovrebbe essere in grado di identificare la vittima da cui proveniva il malware e andare a raccogliere quelle informazioni da essa e inserirle nel programma in modo che possano essere trasformate appropriatamente nella chiave AES/IV che decrittografa Stage2. Ci sono tuttavia molti "se" legati alla competenza relativa del reverse engineer e alla disponibilità della macchina vittima per recuperare tali informazioni.

La whitelisting delle applicazioni frustrerebbe significativamente questo ciclo di vita. Stage0/Stage1 potrebbero essere sideloadati come DLL, tuttavia sospetto che Stage2 come ADS presenterebbe alcuni problemi. Non ho un ambiente per testare il malware contro AWL né mi sono preoccupato di portare tutto in formato DLL, quindi non posso dirlo. Sono sicuro che ci siano modi creativi per aggirare questi problemi.

Sono anche abbastanza fiducioso che ci siano modi più intelligenti per eseguire Stage2 che non siano rilasciarlo su disco e chiamare CreateProcess; mappare manualmente l'eseguibile o utilizzare uno strumento come Donut per trasformarlo in shellcode sembrano idee ragionevoli.

Codice e binario

Durante lo sviluppo ho creato un'applicazione Builder in cui possono essere inseriti Stage1 e Stage2 per produrre uno Stage0 funzionale; questo non verrà fornito, tuttavia fornirò la maggior parte del codice sorgente per stage1 poiché è il pezzo che sarebbe più visibile a un Blue Teamer. Stage0 sarà escluso come esercizio per il lettore, e stage2 è qualsiasi eseguibile autonomo tu voglia eseguire e proteggere. Questo POC può essere ulteriormente ricercato a discrezione e sforzo dei lettori capaci.Fornirò una copia compilata di questo malware come Dropper64.exe. Dropper64.exe è compilato per x64. Dropper64.exe è Stage0; contiene Stage1 e Stage2. All'esecuzione, Stage1 e Stage2 verranno scritti su disco ma NON verranno eseguiti automaticamente, dovrai eseguire di nuovo Dropper64.exe (ora Stage1). Stage2 è una versione x64 di calc.exe. Lo includo per chiunque dei Blue Teamers voglia dare un'occhiata, ma tieni presente che in uno scenario di risposta agli incidenti il 99& delle volte riceverai Stage1/Stage2, Stage0 sarà sparito.

Conclusione

Questo è stato un interessante progetto personale che mi ha impegnato un lungo fine settimana. Sono sicuro che sarebbe stato molto più avanzato/completo se avessi avuto esperienza con un debugger e un disassemblatore, ma si fa del proprio meglio con ciò che si ha. Non vedo l'ora di sentire cosa ne pensano i Blue Teamers e altri sviluppatori di malware. Sono certo di aver reinventato la ruota in modo eccessivamente complicato rispetto a ciò che fanno gli APT reali, ma lungo il percorso ho imparato alcune cose. Grazie per aver letto!

Scarica lo strumento