Riepilogo
- SharpRhino si basa sul progetto open source ThunderShell
- Viene distribuito alle vittime come programma di installazione NSIS che rilascia script di PowerShell
- Gli script di PowerShell contengono assembly .NET codificati
- Il payload .NET viene utilizzato per comunicare con il server C2
- Può eseguire comandi da remoto
- Il traffico di rete è crittografato con RC4 e codificato in formato Base64
Introduzione
Hunters International, un gruppo noto per le attività di erogazione di ransomware-as-a-service, sta utilizzando un nuovo malware RAT. Il primo incidente in cui è stata individuata questa minaccia risale all'inizio di agosto 2024 ed è stato denominato SharpRhino, perché utilizza il linguaggio C#. Il trojan viene distribuito alle vittime come software legittimo e permette l'accesso da remoto al sistema colpito. Tramite il software, gli attaccanti possono eseguire diversi comandi e propagare altro malware.
Dettagli tecnici
Panoramica
L'esemplare analizzato viene distribuito alle vittime come un programma di installazione realizzato con Nullsoft Scriptable Install System (NSIS). Il file distribuito contiene 'Angryip.org' nella descrizione e un certificato digitale valido, ma il nome dell'azienda è falso e non esiste.

L'installer contiene un programma di installazione aggiuntivo, un archivio protetto da password e altri file che vengono utilizzati durante l'esecuzione del malware.

Installazione
Al momento dell'esecuzione, l'esemplare scarica tutti i file incorporati nella cartella 'C:\ProgramData\Microsoft\WindowsUpdate24' ed esegue il file 'ipscan-3.9.1-setup.exe', un programma di installazione del software legittimo Angry IP Scanner.

Mentre l'utente è distratto da questo programma di installazione, il malware estrae i file dall'archivio UpdateFull.zip protetto da password. Quindi utilizza un programma 7za.exe incorporato per decomprimere l'archivio. Nella riga di comando possiamo vedere la password per l'archivio:
C:\ProgramData\Microsoft\WindowsUpdate24\7za.exe x C:\ProgramData\Microsoft\WindowsUpdate24\UpdateFull.7z -pTG98HJerxsdqWE45 -oC:\ProgramData\Microsoft\WindowsUpdate24
Il contenuto dell'archivio è il seguente:

Dopo l'estrazione, l'esemplare crea una nuova cartella 'C:\ProgramData\Microsoft\LogUpdateWindows' in cui vengono copiati i file estratti dall'archivio. L'utilizzo di due cartelle di installazione diverse può aiutare gli attaccanti a ottenere la persistenza e a rimanere nel sistema nel caso in cui una delle due cartelle venga rimossa, perché i file nelle cartelle hanno procedure di esecuzione simili. A questo punto, viene aggiunta una nuova chiave del Registro di sistema al percorso 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run' che punta al file 'Microsoft.AnyKey.lnk', un file di collegamento che contiene la destinazione successiva:
C:\ProgramData\Microsoft\LogUpdateWindows\Microsoft.AnyKey.exe abnormal c:\programdata\%username%0 cmd /c C:\ProgramData\Microsoft\LogUpdateWindows\LogUpdate.bat
L'eseguibile 'Microsoft.AnyKey.exe', anch'esso estratto dall'archivio, è un programma legittimo che fa parte degli strumenti Node.js per Visual Studio ed è denominato 'Microsoft.NodejsTools.PressAnyKey.exe'.
Esecuzione
I file 'LogUpdate.bat' e 'WindowsUpdate.bat' hanno la stessa funzionalità, ma caricano file diversi.

Entrambi i file 'Wiaphoh7um.t' e 'kautix2aeX.t' contengono dati offuscati. Per questi file, i dati grezzi e la chiave sono diversi, ma i dati risultanti saranno gli stessi. Dopo il processo di decodifica, l'esemplare definisce questi dati come assembly .NET ed esegue la chiamata a un metodo con alcuni parametri.

Una volta eseguito il dump di tutti i dati dallo script, possiamo osservare le variabili seguenti:
Le variabili $var1, $var2, $var3 determinano gli assembly di riferimento e, concatenate, formano la stringa seguente:
System.Drawing.dllSystem.Web.Extensions.dllSystem.Windows.Forms.dll
La variabile $var4 è diversa per ogni file e contiene l'indirizzo di un server C2. Di seguito è riportata una tabella che rappresenta gli argomenti utilizzati nella chiamata dell'assembly .NET per ogni file:
Después de realizar el volcado de todos los datos del script, podemos observar las siguientes variables:

'$fjwZrHB1k2RF' rappresenta l'assembly .NET caricato in memoria. Dopo aver eseguito il dump dei dati, possiamo osservare il codice C#. Lo script di PowerShell esegue la chiamata a una funzione dallo spazio dei nomi 'Bzxmlpi' e dalla classe 'OyrWkb'. All'inizio di questa classe, sono visibili alcuni carichi di import aggiuntivi e nomi di variabili illeggibili.

In effetti, questo file è una versione modificata del progetto open source 'ThunderShell'. Al progetto originario sono state apportate numerose modifiche:
- Sono stati rimossi keylogger, screenshot e funzioni di caricamento di .NET Assembly, nonché i comandi del server che rappresentavano tali funzioni.
- Tutte le classi, le funzioni e le variabili sono state rinominate.
- Sono stati aggiunti dei valori predefiniti che vengono utilizzati se il payload viene eseguito senza argomenti.

Questa funzione genera per prima cosa una stringa casuale di 16 byte. Durante l'inizializzazione della classe Random, l'esemplare utilizza la data, l'ora e l'ID del processo. Quindi, acquisisce alcune variabili d'ambiente, come COMPUTERNAME, USERDOMAIN e USERNAME. Tutti questi dati vengono formattati:

In questo modo viene generata la stringa successiva:

Quindi, l'esemplare passa questa stringa a una funzione che la invia al server. Nel server, i dati vengono crittografati con un cifrario RC4 e una chiave passata come secondo argomento.

Dopo il processo di crittografia, alcuni dati vengono aggiunti alla richiesta; la stringa crittografata viene inoltre codificata nel formato Base64. Tutti questi dati vengono quindi inviati al server.

Alla prima connessione, la risposta del server viene ignorata. Quando l'esemplare entra in un loop, si connette nuovamente al server, ma entrambi gli argomenti restituiscono un valore 'null'. Successivamente, la risposta viene salvata e confrontata con i valori salvati. Se riceve il comando 'delay', l'esemplare prende un argomento aggiuntivo e modifica il valore che viene passato alla funzione di sospensione. Se riceve il comando 'exit', interrompe il loop e termina l'esecuzione. Se ottiene dati diversi da 'delay' o 'exit', crea un nuovo thread con una funzione che utilizza i dati ottenuti come argomento. Tutte queste azioni vengono ripetute con un intervallo di 95 secondi tra un'iterazione e l'altra del loop.

La risposta ricevuta dal server viene passata alla funzione di deserializzazione nella classe 'zWxFlnVASjHYb', che acquisisce e archivia i dati successivi: 'UUID', 'ID' e 'Data'.

Server C2
Anche se il collegamento presente nell'esemplare è già offline, possiamo utilizzare il server del progetto sorgente per capire come funziona la comunicazione. Innanzitutto, è necessario modificare la configurazione del server. Contiene alcuni campi, tra cui l'indirizzo IP del server, la chiave di crittografia, le impostazioni della GUI e le impostazioni HTTP e HTTPS. Quindi dobbiamo modificare i parametri 'callback-url', 'gui-host' e 'encryption-key'. Prenderemo i parametri della chiave di crittografia da un esemplare di SharpRhino.

Il server è un'applicazione Python e richiede l'esecuzione di un server Redis. Dopo l'avvio, fornisce alcune informazioni sul server.

Tra queste informazioni c'è un indirizzo Web GUI. Quando viene aperto, l'utente deve prima effettuare l'accesso. Non importa quale sia il nome utente inserito, ma la password deve essere presa dal file di configurazione. Una volta effettuato l'accesso, viene visualizzata la sezione della dashboard che contiene informazioni sulle sessioni e sui registri.

È possibile creare il payload nell'interfaccia web. È necessario fornire l'indirizzo IP del server e il tipo di payload.

Dopo aver selezionato una sessione, l'attaccante può interagire con essa. Digitando 'help' vengono visualizzati tutti i comandi supportati utilizzabili all'interno della sessione.

Comunicazioni C2
Questi comandi dispongono di stringhe predefinite che vengono aggiunte ai dati che l'attaccante inserisce come argomenti. Utilizzando 'shell [command]', ad esempio, 'cmd.exe /c' viene aggiunto all'inizio della stringa da inviare. Un altro esempio è il comando 'ps', che invia lo script di PowerShell al client:

Il comando arriva al client crittografato con RC4 e codificato nel formato Base64. Contiene i parametri ID e UUID, dove ID è l'ID del client e UUID è l'ID del comando.

Tutti questi dati vengono passati al nuovo thread. La funzione in questo thread utilizza i moduli di PowerShell per eseguire i comandi specificati.

Utilizzando la pipeline, l'esemplare ottiene il risultato del comando eseguito. I dati vengono quindi crittografati e inviati al server.

Conclusioni
ThunderShell, un vecchio progetto open source che non è stato aggiornato per quasi quattro anni, è stato utilizzato da Hunters International per distribuire malware alle vittime. Arriva come programma di installazione dell'utility Angry IP Scanner, che rilascia ed esegue script di PowerShell dannosi. Sfruttando le funzionalità di PowerShell, questi script eseguono assembly .NET codificati, quindi non è necessario inserire alcun eseguibile compilato aggiuntivo: il codice dannoso viene richiamato ed eseguito in memoria.
Anche se il codice originale è stato modificato, ha mantenuto la sua funzionalità principale: eseguire comandi da remoto sui sistemi di destinazione. Questo è il pericolo intrinseco dei progetti open source di questo tipo. In genere, vengono sviluppati per scopi didattici o di test di penetrazione, ma possono poi essere utilizzati per sferrare attacchi reali.
Rilevato da Acronis

