Red Hot Cyber

La cybersecurity è condivisione.
Riconosci il rischio, combattilo, condividi le tue esperienze ed 
incentiva gli altri a fare meglio di te.

Cerca

Analisi del codice sorgente di Conti ransomware.

Emanuele De Lucia : 2 Marzo 2022 22:52

Autore: Emanuele De Lucia (Cluster25)
Data Pubblicazione: 02/03/2022

Il 25.02.2022 la cyber-gang Conti ha pubblicato la seguente dichiarazione sul proprio data-leak.site (DLS):

Il post è stato redatto diverse ore dopo con un altro dai toni più neutri, che condanna la guerra e si dissocia dal governo, pur sottolineando i sentimenti contro l’Occidente. 

Il post ha mantenuto le sue minacce di ritorsioni contro le infrastrutture critiche appartenenti a qualsiasi aggressore russo.

Dopo di che, il 28.02.2022, probabilmente uno dei membri Conti (o solo un ricercatore di sicurezza ucraino) ha pubblicato un primo archivio con dati interni preziosi e informazioni appartenenti all’intero collettivo. 

L’azione è stata probabilmente una diretta conseguenza di una posizione così netta del gruppo sull’attuale situazione tra Russia e Ucraina. Tra questo materiale risulta esserci anche un archivio contenente il codice sorgente del loro ransomware di cui riportiamo un’analisi preliminare.

APPROFONDIMENTI

ContiLocker è un ransomware sviluppato dalla Conti Ransomware Gang , un collettivo criminale di lingua russa con sospetti legami con le agenzie di sicurezza russe. Il progetto è sviluppato in C++ su una versione di Visual Studio 2015 con Windows XP Nplatform toolset ( v140_xp ). 

La piattaforma di destinazione specificata è la 10.0 (Windows10). La struttura del progetto è organizzata in diverse sottocartelle, ognuna delle quali gestisce uno specifico modulo del ransomware (come la cartella “locker” per le operazioni di crittografia).

Per operazioni specifiche (come il meccanismo di crittografia) utilizza diversi thread simultanei gestiti dall’API di Windows CreateIoCompletitionPort e code diverse gestite da GetQueuedCompletitionStatusPostQueuedCompletitionStatus .

La funzione WinMain (main.cpp) inizia con la risoluzione dinamica dell’API LoadLibraryA tramite un’ispezione manuale del kernel32.dll importato (un’implementazione manuale dell’API GetProcAddress ).

Successivamente viene invocato il modulo “API” per eseguire una tecnica anti-DBI/anti-sandbox con lo scopo di disabilitare tutti i possibili hooking su DLL conosciute. In effetti, le seguenti DLL vengono caricate tramite l’ API LoadLibraryA appena risolta:

  • kernel32.dll
  • ws2_32.dll
  • advapi32.dll
  • ntdll.dll
  • rstrtmgr.dll
  • ole32.dll
  • oleaut32.dll
  • netapi32.dll
  • iphlpapi.dll
  • shlwapi.dll
  • shell32.dll

Per ogni DLL caricata, CreateFileMappingW e MapViewOfFile vengono richiamati per
accedere alla visualizzazione mappata nello spazio degli indirizzi del processo chiamante.

Questa vista viene utilizzata per accedere manualmente all’intestazione NT e alla directory di esportazione interna. Dalla directory di esportazione viene estratto ogni indirizzo delle funzioni esportate e vengono controllati i primi byte della funzione esportata per identificare una possibile istruzione JMP / NOP / RET che identifichi un hook esterno.

Se la funzione corrente è agganciata, VirtualProtect e l’API RtlCopyMemory vengono invocate per sovrascrivere i primi byte della funzione agganciata. Procedendo con l’ esecuzione di WinMain , viene creato un mutex denominato “kjsidugidf99439” per verificare eventuali esecuzioni simultanee dello stesso payload. Se un altro thread ha la proprietà del mutex, l’esecuzione termina qui.

Successivamente, gli argomenti delle righe di comando vengono controllati dall’API GetCommandLineW.

Questo ransomware accetta i seguenti argomenti della riga di comando:

  • -h: specifica un file che contiene l’IPv4 degli host da scansionare per la crittografia di rete/condivisioni (separato da \n\r);
  • -p: specifica un file che contiene il percorso di sistema per la scansione della crittografia dei file (separato da \n\r);
  • -m: specifica la modalità di crittografia
  • “all”: crittografa sia i file locali che quelli di rete
  • “local”: crittografa solo i file locali
  • “net”: crittografa solo i file di rete
  • “backup”: non implementato
  • -log: se contiene il valore “enabled”, registra le azioni/errori ransomware sul file locale C:\\ CONTI_LOG.txt

Successivamente, l’API GetNativeSystemInfo viene invocata per estrarre il numero di processori e il modulo “threadpool” viene utilizzato per istanziare number_of_processors * 2 thread (sia per la crittografia locale che/o di rete, in base ai flag specificati).

Ogni thread alloca il proprio buffer per la crittografia imminente e inizializza il proprio contesto di crittografia tramite l’ API CryptAcquireContextA e una chiave pubblica RSA.

Quindi, ogni thread attende in un ciclo infinito un’attività nella coda TaskList (condivisa da ciascun thread e accessibile dall’API EnterCriticalSection ). Nel caso in cui sia disponibile una nuova attività, il nome del file da crittografare viene estratto dall’attività e, se il nome del file corrisponde a “stopmarker“, l’esecuzione del thread è conclusa.

In ogni altro caso, viene invocato il modulo “locker” per crittografare il file corrente.

Il processo di crittografia

La routine di crittografia per un file specifico inizia con una generazione di chiavi casuali (utilizzando l’ API CryptGetRandom) di una chiave da 32 byte e un’altra generazione casuale di un IV da 8 byte .

Successivamente, la chiave casuale e la IV casuale vengono archiviate in una struttura FIleInfo personalizzata e la chiave casuale viene crittografata utilizzando la chiave RSA precedentemente decodificata.

Prima della fase di crittografia, se viene caricata la DLL di gestione del riavvio ( rstrtmgr.dll ), le API RmStartSession , RmGetList e RmShutdown vengono richiamate per terminare ogni applicazione che utilizza questa specifica risorsa o ha un handle aperto su tale risorsa.

Quindi, in base all’estensione del file, il contenuto del file è completamente crittografato o parzialmente crittografato (crittografia del 20% ). In particolare, viene invocato il metodo CheckForDataBases per verificare un’eventuale crittografia completa rispetto alle seguenti estensioni:

  • .4dd, .4dl, .accdb, .accdc, .accde, .accdr, .accdt, .accft, .adb, .ade, .adf, .adp, .arc, .ora, .alf, .ask, .btr , .bdf, .cat, .cdb, .ckp, .cma, .cpd, .dacpac, .dad, .dadiagrams, .daschema, .db, .db-shm, .db-wal, .db3, .dbc, .dbf, .dbs, .dbt, .dbv, .dbx, .dcb, .dct, .dcx, .ddl, .dlis, .dp1, .dqy, .dsk, .dsn, .dtsx, .dxl, .eco , .ecx, .edb, .epim, .exb, .fcd, .fdb, .fic, .fmp, .fmp12, .fmpsl, .fol, .fp3, .fp4, .fp5, .fp7, .fpt, . frm, .gdb, .grdb, .gwi, .hdb, .his, .ib, .idb, .ihx, .itdb, .itw, .jet, .jtx, .kdb, .kexi, .kexic, .kexis, .lgc, .lwx, .maf, .maq, .mar, .mas.mav, .mdb, .mdf, .mpd, .mrg, .mud, .mwb, .myd, .ndf, .nnt, .nrmlib, .ns2, .ns3, .ns4, .nsf, .nv, .nv2, .nwdb, .nyf, .odb, .ogy, .orx, .owc, .p96, .p97, .pan, .pdb, .p dm, .pnz, .qry, .qvd, .rbf, .rctd, .rod, .rodx, .rpd, .rsd, .sas7bdat, .sbf, .scx, .sdb, .sdc, .sdf, .sis, .spg, .sql, .sqlite, .sqlite3, .sqlitedb, .te, .temx, .tmd, .tps, .trc, .trm, .udb, .udl, .usr, .v12, .vis, .vpd, .vvv, .wdb, .wmdb, .wrk, .xdb, .xld, .xmlff, .abcddb, .abs, .abx, .accdw, .adn, .db2, .fm5, .hjt, .icg, .icr, .kdb, .lut , .maw, .mdn, .mdt

In caso contrario, viene invocato il metodo CheckForVirtualMachines per verificare una possibile crittografia parziale del 20% ((file_size / 100) * 7) rispetto alle seguenti estensioni:

  • vdi, .vhd, .vmdk, .pvm, .vmem, .vmsn, .vmsd, .nvram, .vmx, .raw, .qcow2, .subvol, .bin, .vsv, .avhd, .vmrs, .vhdx, .avdx, .vmcx, .iso

Negli altri casi si segue il seguente schema:

  • Se la dimensione del file è inferiore a 1,04 GB: esegue una crittografia completa.
  • Se la dimensione del file è compresa tra 1,04 GB e 5,24 GB: esegue una crittografia dell’intestazione (crittografa solo i primi 1048576 byte).
  • In caso contrario, eseguire una crittografia parziale del 50% ((file_size / 100) * 100).

Dopo aver scelto il metodo di crittografia, i primi byte del contenuto del file vengono sovrascritti (prima della crittografia) con le informazioni sulla modalità di crittografia e la chiave utilizzata per la crittografia. 

Quindi, il contenuto del file viene crittografato utilizzando la chiave casuale precedentemente crittografata con RSA e l’estensione del file viene modificata in .EXTEN .

Ora vediamo come questi thread vengono richiamati dai metodi di enumerazione che tornano all’esecuzione di WinMain.

Innanzitutto, viene utilizzato un bypass COM per eliminare le copie shadow da Strumentazione gestione Windows (WMI).

Nei dettagli:

  1. L’oggetto COM viene inizializzato tramite l’ API CoInitializeEx .
  2. I livelli di sicurezza COM vengono modificati tramite l’ API CoInitializeSecurity e il parametro cAuthSvc è uguale a -1 per disabilitare l’autenticazione.
  3. L’ API CoCreateInstance viene utilizzata per individuare la WMI tramite il CLSID “CLSID_WbemLocator“.
  4. È possibile accedere a WMI e WQL (WMI Query Language) tramite il metodo WbemLocator :: ConnectServer .
  5. I livelli di sicurezza del proxy WMI vengono modificati tramite l’ API CoSetProxyBlanket in modo da impostare il flag RPC_C_AUTHZ_NONE ed evitare l’autenticazione.
  6. La query ” SELECT * FROM Win32_ShadowCopy ” viene richiamata per identificare gli ID delle copie shadow e viene utilizzata un’esecuzione dalla riga di comando per eliminare ciascuna copia shadow ” cmd.exe /c C:\\Windows\\System32\\wbem\\WMIC. exe shadowcopy dove \”ID=’%s’\” elimina ”

Infine, inizia il processo di enumerazione. Innanzitutto, i percorsi del file system specificati tramite il flag -p vengono ripetuti e per ogni percorso la nota ransomware (R3ADM3.txt, non disponibile in questa versione trapelata) viene rilasciata nella directory specificata. 

Successivamente, le API FindFirstFileW e FindNextFileW vengono utilizzate per scorrere all’interno di ciascuna directory ignorando i file speciali (come “.” o “..”).

Il malware utilizza una whitelist sia per le directory che per i file per evitare la crittografia di dati non necessari. I seguenti nomi di directory e nomi di file vengono evitati durante il processo di enumerazione:

  • Directory: “tmp”, “winnt”, “temp”, “thumb”, “$Recycle.Bin”, “$RECYCLE.BIN”, “Informazioni sul volume di sistema”, “Boot”, “Windows”, “Trend Micro”
  • File: “.exe”, “.dll”, “.lnk”, “.sys”, “.msi”, “R3ADM3.txt”, “CONTI_LOG.txt”

Se il file da crittografare è una directory, il processo descritto viene ripetuto in modo ricorsivo per tutte le sottodirectory e i sottofile. 

Infine, il file da crittografare viene passato al primo thread disponibile per il processo di crittografia che popola la coda TaskList. L’enumerazione seguente esamina tutte le unità logiche del sistema infetto.

Infatti, oltre ai percorsi specificati dal flag -p, per ottenere l’elenco delle unità viene utilizzata l’API GetLogicalDriveStringsW . Quindi, per ogni unità logica, viene estratto il percorso radice e il processo precedente viene ripetuto per ogni sottodirectory e sottofile.

L’ultimo processo di enumerazione viene utilizzato per enumerare le condivisioni del sistema Windows infetto.

In effetti, l’API NetShareEnum viene utilizzata per recuperare informazioni su ciascuna risorsa condivisa. Per ogni risorsa, se la risorsa rappresenta un’unità disco, una condivisione speciale (ad esempio, $IPC communication, ADMIN$ amministrazioni remote, condivisioni amministrative) o una condivisione temporanea, viene estratto il percorso della condivisione (ad esempio, \\\\$IP\\ $SHARE_NAME ).

Quindi, ogni percorso di condivisione viene utilizzato come directory per il processo di crittografia delle directory e dei file descritto in precedenza.

I movimenti laterali

Oltre all’enumerazione delle condivisioni, questo ransomware presenta un componente multi-thread per cercare altri IP nelle reti raggiungibili per una crittografia distruttiva del movimento laterale. 

In particolare, le API WSAStartup e WSAIoctl vengono richiamate per ottenere un gestore a LPFN_CONNECTEX per collegamenti e connessioni di basso livello.

Quindi, l’ API GetIpNetTable viene richiamata per ripristinare la tabella ARP del sistema infetto. Per ogni voce della tabella ARP, gli indirizzi IPv4 specificati vengono confrontati con le seguenti maschere:

  • 172.*
  • 192.168.*
  • 10.*
  • 169.*

Se l’attuale ARP IPv4 rispetta una di queste maschere, la sottorete IP viene estratta e aggiunta alla coda di una sottorete. 

Da questa enumerazione vengono creati due thread simultanei. Il primo thread è responsabile della scansione della sottorete: per ogni possibile indirizzo (da .0 a .255) in ogni sottorete estratta il malware tenta una connessione su quell’IP sulla porta SMB (445) utilizzando il protocollo TCP. Per ogni connessione riuscita, questo primo thread salva gli IP validi in una coda e ripete la scansione ogni 30 secondi.

Il secondo thread attende un IP valido nella coda dell’IP e per ogni IP enumera le condivisioni utilizzando l’ API NetShareEnum ripetendo il processo descritto per l’enumerazione delle condivisioni. 

L’esadecimale 0xFFFFFFFF viene utilizzato come ultimo indirizzo IP nella coda per terminare entrambi i thread e concludere la seconda e l’ultima parte dell’enumerazione di rete.

Concludendo l’esecuzione del ransomware, l’API WaitForSingleObject viene richiamata su ciascun thread per attendere il completamento delle operazioni di crittografia ed enumerazione prima di chiudere il processo principale.

Conclusioni

La banda Conti è una delle organizzazioni criminali più conosciute e temute del mondo digitale. La quantità e il dettaglio dei dati interni che via via stanno venendo fuori sul collettivo possono certamente rappresentare un vero e proprio terremoto nel panorama delle minacce informatiche. 

Per quanto riguarda il codice, sembra essere molto ben modularizzato e gestito. 

Come ci si poteva aspettare la sua qualità è altissima.

Emanuele De Lucia
Laureato in Informatica (con master in Computer Security e un master alla Stanford University), ha lavorato come analista nel Security Operation Center (Se.OC o SOC) in una TELCO italiana e nel settore spaziale. Dirige un team internazionale di ricercatori focalizzato sulla Threat Intelligence, sul reverse engineering e la risposta agli incidenti.