
roba cattiva di persone cattive
Il campione di Hive analizzato e citato in questo documento è stato scelto casualmente da questo elenco creato da @rivitna a cui vanno i miei più sentiti ringraziamenti. Gli artefatti sono disponibili sulla piattaforma VirusTotal.
In questo documento, il file a0h2uih3d2.exe è stato preso come riferimento
MD5: 15CF5E0DA094ACDD751A513402A8C941
SHA-1: 72E15AC4473903C814E65E3C06F54EB0399580AA
SHA-256: 335D2E4A743D059955760ECF2EC25EE86D36AA60B096C9180E860C64EF78EE55
Per avere un'idea della complessità di questo ransomware, dai un'occhiata a questa analisi pubblicata da Microsoft Threat Intelligence Center (MSTIC).
Leggi attentamente l'intero documento prima di iniziare a giocare con il codice!
Negli ultimi mesi, ho concentrato gran parte delle mie energie nello studio e nel reverse engineering dell'algoritmo di crittografia di Hive v5. Ho avuto il piacere di collaborare con un grande analista di malware e reverse engineer @rivitna che in passato ha analizzato le versioni precedenti di Hive e ha pubblicato codice e PoC relativi ai loro meccanismi di crittografia. Ha contribuito (non poco) a identificare i componenti coinvolti nelle operazioni di crittografia di Hive v5, che essendo scritto in RUST è diventato più difficile da analizzare. Ho trovato qualcosa in comune con Babuk, un altro ransomware molto importante le cui fonti sono state divulgate nel giugno 2021:
Il ransomware Hive v5 in esecuzione su un sistema vittima genera due chiavi in chiaro, usando l'algoritmo nella prova qui sotto, basato sulle API Windows QueryPerformanceCounter e QueryPerformanceFrequency.
Dai un'occhiata a questa pagina Microsoft per maggiori informazioni sulle API QueryPerformanceCounter, qui per QueryPerformanceFrequency.
QueryPerformanceCounter è un contatore di tempo molto accurato. Quando viene chiamato, restituisce il tempo trascorso dall'ultima accensione del PC.
QueryPerformanceFrequency restituisce il valore (frequenza) del contatore delle prestazioni. Ha un valore fisso di 0x989680. Ciò significa che il valore di QueryPerformanceCounter viene aggiornato 0x989680 volte al secondo, ovvero 10,000,000 volte.
Le due chiavi in chiaro hanno una dimensione di 0xCFFF00 byte e vengono generate una alla volta, byte per byte. Di seguito è riportato lo snippet che consente la creazione di un array di 0xA00000 byte, che è la parte più grande della cosiddetta chiave in chiaro con cui Hive crittografa i file sul PC della vittima.

Ogni byte della chiave viene ottenuto prendendo il valore del registro AL. Il registro EAX contiene il risultato della funzione 0044ADE0 rinominata con l'etichetta createByte che implementa la differenza tra l'istante di tempo corrente e il valore seed iniziale, calcolato alla prima chiamata della funzione 0044A850 rinominata con l'etichetta call_to_QueryPerformanceCounter.
Di seguito è riportato il codice scritto in C++ per generare una chiave in chiaro:

L'algoritmo è molto semplice, anche se all'interno della funzione 0044ADE0 sono state inserite istruzioni che eseguono operazioni ridondanti e vari salti condizionali per cercare di ritardare il tempo di esecuzione del codice durante la generazione della chiave in chiaro:

Nella cartella HiveRansomwareV5_custom_keygen_PoC troverai il codice raw ricavato dal reverse engineering del campione Hive v5 analizzato. Non è codice ottimizzato come quello trovato nel malware, perché non volevo perdere nemmeno una riga di codice della versione compilata.
Nella cartella HiveRansomwareV5_custom_keygen_PoC-optimized troverai il codice ottimizzato derivato dal codice raw sopracitato. In questa versione il codice è molto più facile da leggere rispetto a quello raw, per comprenderne la funzionalità implementata.
Entrambe le versioni devono essere personalizzate con il tuo utente prima di eseguirle, per salvare la chiave in chiaro generata sul tuo Desktop.
Entrambe le chiavi in chiaro vengono generate utilizzando lo stesso algoritmo.
Una chiave in chiaro è composta da 0xA00000 byte generati casualmente in modo sicuro byte. Quindi i primi 0x2FFF00 byte vengono copiati alla fine, creando una chiave in chiaro finale di 0xCFFF00 byte.

Poi Hive usa le due chiavi generate per crittografare i file, ma prima di tutto Hive ransomware v5 crittografa le chiavi generate in una struttura personalizzata (d'ora in poi chiamata keystream) e le posiziona nella radice di ogni unità che crittografa usando l'estensione .key. Ad esempio, se hai sia l'unità C che D installate sul tuo sistema, i keystream crittografati saranno presenti nella radice di ogni unità.

Hive ransomware v5 usa le chiavi in chiaro generate per crittografare i file usando l'istruzione XOR, quindi ci troviamo di fronte a una crittografia simmetrica molto veloce sulle moderne CPU x86/x64.
Hive ransomware v5 deve proteggere la chiave in chiaro generata, crittografandola due volte; d'ora in poi chiameremo questi passaggi round. Sono necessari due round di crittografia per ottenere il keystream finale.
Per fare ciò, a ogni round vengono eseguiti i seguenti passaggi:
Il passaggio 3 garantisce la creazione di un keystream che può essere aperto da una doppia coppia di chiavi private: quelle generate da Hive durante la crittografia e quelle che l'affiliato Hive ha generato quando ha compilato il ransomware per noi.

Al termine di questa descrizione, un punto particolare è evidente: la chiave in chiaro, la chiave privata e il nonce usati in entrambi i round di crittografia sono generati dalla stessa funzione sopra (0044ADE0 aka createByte). La funzione 0044ADE0 è condizionata dal tempo che la CPU impiega per eseguire il codice chiamato all'interno del ciclo for.
Guardando la figura sopra che evidenzia la struttura del keystream dopo i due round di crittografia, è evidente che abbiamo libero accesso solo al nonce (altrimenti gli affiliati Hive non saprebbero come decrittare i file).
Quindi concentriamoci sul NONCE, che è lungo 24 byte:
NONCE: 40 A4 08 6C D0 D0 34 98 FC 60 C4 28 8C F0 F0 54 B8 1C 80 E4 48 AC AC 10
La differenza tra un byte del nonce e il successivo (in valore assoluto) rappresenta il tempo trascorso tra un'iterazione e la successiva. Introduciamo il concetto di impronta con questa definizione.
NONCE FINGERPRINT: 64 9c 64 64 00 9c 64 64 9c 64 9c 64 64 00 9c 64 9c 64 64 9c 64 00 9c
Se analizziamo i valori ottenuti, scopriamo che il tempo di esecuzione del codice è quasi identico, con lievi variazioni dovute in particolare alla tecnologia utilizzata dal processore in uso (per i miei test ho usato un processore i7 di decima generazione e un i5 di quinta generazione; su altri sistemi questa impronta può differire).
Questa scoperta è molto importante se pensiamo che il nonce sia generato dalla stessa funzione che genera la chiave in chiaro e soprattutto la chiave privata. Poiché questi valori menzionati seguiranno anche questo principio, cioè la differenza tra i singoli byte del nonce è prevedibile, allora anche i valori della chiave privata e della chiave in chiaro saranno prevedibili.
Tuttavia, le analisi hanno mostrato che generare un array di 0xA00000 caratteri sperando di ottenere gli stessi byte originali della chiave in chiaro calcolata da Hive è molto difficile: le variazioni nei carichi di CPU e memoria influiscono sulla velocità di esecuzione del codice e spesso la chiave in chiaro originale calcolata dal PE di Hive è diversa (anche solo per pochi byte) dalla chiave calcolata da noi.
Usiamo questa impronta del nonce per confrontarla con l'impronta ottenuta dalla generazione di un possibile dizionario di 0xA00000 byte di lunghezza (questo numero è stato fissato empiricamente; dopo una serie di test, si è visto che statisticamente in questo numero di byte sono presenti le due chiavi private di 32 byte ciascuna, necessarie nei due round di crittografia). Se l'impronta del nonce è contenuta nell'impronta del dizionario, abbiamo trovato il dizionario giusto per iniziare la forza bruta su entrambe le chiavi private.
Non finisce qui, perché dalle analisi dinamiche condotte sulla generazione del nonce, della chiave in chiaro e anche della chiave privata, è stato verificato che il primo byte ha una distanza media diversa dal secondo byte, rispetto a tutti gli altri byte che hanno valori quasi omogenei. Vediamo in dettaglio:

Come puoi vedere, i valori dell'impronta successivi al primo subiscono variazioni minime, cioè la distanza in valore assoluto tra il primo e il secondo byte della chiave privata, nella maggior parte dei casi, ha valori al di fuori dei valori presenti nel resto dell'impronta.
Probabilmente ciò è dovuto ad alcuni algoritmi di ottimizzazione presenti nella CPU che accelerano l'esecuzione del codice dopo la prima iterazione del ciclo for.
Il codice proposto legge il nonce di ogni round di crittografia del keystream, determina la sua impronta e genera un elenco di possibili dizionari di chiavi che contengono la possibile chiave privata.
Per risolvere il problema relativo al primo byte dell'impronta, che è sempre diverso dal resto della chiave, ho pensato di fare questo:
Quando le due chiavi pubbliche coincidono, avremmo trovato la chiave privata con cui è stato crittografato il secondo (ultimo) round di crittografia. Iterando nuovamente le operazioni descritte finora, avremo la chiave privata per decrittare il primo round di keystream crittografato e infine estrarre la chiave in chiaro originale.
Nella cartella HiveRansomwareV5-keystream_decryptor troverai la soluzione VS 2017 e una libreria monocypher personalizzata. Il programma ti permette di scegliere quale operazione eseguire.

L'opzione "1" è la prima da scegliere perché ti permette di creare un dizionario di byte "su misura" per il processore del tuo PC; pertanto dovrebbe essere eseguita sulla macchina crittografata, perché è molto più probabile che tu ottenga valori uguali a quelli presenti nel suo keystream.

In alternativa, se la prima opzione non funziona, genera il tuo dizionario eseguendo il malware nel debugger (sullo stesso PC già infetto) fino al termine della generazione della chiave in chiaro (appena fuori dal ciclo for) e salva il contenuto della memoria che contiene la chiave in chiaro. In questo caso puoi convalidare il tuo dizionario usando l'opzione "3":

Una volta ottenuto il dizionario giusto per il tuo keystream, l'opzione "2" può essere eseguita anche su computer più potenti, poiché ridurrebbe il tempo necessario per forzare le combinazioni di byte, senza influire in alcun modo sui valori dei byte delle chiavi private.

Per eseguire correttamente la funzionalità presente nell'opzione 2, è necessario estrarre la chiave pubblica. Poiché non tutti i campioni di Hive sono uguali, non è molto facile creare un estrattore di chiave pubblica universale. Tuttavia, un modo che è noto funzionare è impostare un punto di interruzione in questa porzione del disassemblato dopo la creazione del nonce. Nella prova di seguito, la chiave pubblica viene passata alla funzione 44E3D8 per derivare la chiave condivisa usando curve25519. È l'unico punto in cui la chiave pubblica viene rivelata durante l'esecuzione del malware.

Presta attenzione quando hai a che fare con le opzioni di Visual Studio. L'output del programma, come i byte del dizionario generato, può essere alterato se si passa da debug a release e viceversa.
Se vuoi accelerare la procedura di forza bruta, puoi modificare il valore dictionary_dimension nel codice, ma tieni presente che ridurre la dimensione del dizionario può anche diminuire le probabilità di trovare le chiavi private.
Inoltre, se decidi di usare un array di byte in chiaro generato eseguendo Hive e facendone il dump dalla memoria, ricordati di impostare la dimensione del dump nella variabile dictionary_dimension.
Per testare il tool di decrittazione ho reso disponibili alcuni file da usare nella cartella dummy_data_PoC:
Buona fortuna!
https://github.com/rivitna/Malware/blob/main/Hive/Hive_samples.txt
https://www.virustotal.com/gui/file/335d2e4a743d059955760ecf2ec25ee86d36aa60b096c9180e860c64ef78ee55
https://www.microsoft.com/security/blog/2022/07/05/hive-ransomware-gets-upgrades-in-rust/
https://docs.microsoft.com/en-us/windows/win32/sysinfo/acquiring-high-resolution-time-stamps
https://monocypher.org/manual/x25519
https://monocypher.org/manual/advanced/poly1305