FTCODE: scopri come recuperare file corrotti dal virus

Share on FacebookTweet about this on TwitterPin on PinterestShare on Google+Share on LinkedIn

Come ho già affrontato in un articolo del blog di Aram in questi giorni le Pubbliche Amministrazioni e le aziende stanno subendo pesanti attacchi da parte di virus più spesso inviati attraverso la pec, che tutti ritengono sicura in quanto veicolo di documenti “ufficiali”.

La storia di Aram, la mia azienda è strettamente legata ad un virus e per questo accolgo sempre con un po’ di nostalgia le sfide che questi lanciano ai programmatori. Aram è stato il primo antivirus creato da noi circa 30 anni fa; l’antivirus ha dato anche il nome all’azienda.

In questi giorni, per riparare ai danni di questo nuovo virus, ho affrontato nuovamente la “sfida” imposta da questo virus, cercando di capire come funziona e di trovare una soluzione se un pc o un server è stato infettato.

Ho tentato di recuperare file corrotti dal virus …

recuperare file corrotti dal virus

Il virus ransomware FTCODE – chi è e come agisce

Il virus di cui parlo è una variante dell’FTCODE, un ransomware che ha iniziato a circolare già qualche anno fa. Il virus viene chiamato ransomware in quanto contiene un file nel quale viene richiesto un pagamento “riscatto” in bitcoin per ricevere la chiave di decriptazione. Non mi soffermerò su questo, in quanto è già stato affrontato in un altro articolo. Qui voglio mostrarti come sono arrivato alla soluzione. D’ora in poi l’articolo è tecnico e quindi dedicato a chi è del settore.

Se hai bisogno di recuperare file corrotti dal virus e non sei un tecnico contattaci.

recuperare file corrotti dal virus

Come funziona l’FTCODE

Ho cercato innanzitutto di capire come agisce questo virus. La pec (o email) ricevuta contiene un allegato in formato zip, con all’interno un documento Office che, se avviato esegue una macro. La macro genera una password di 50 caratteri; ogni carattere può essere un numero compreso tra 0 e 9 o un carattere maiuscolo o minuscolo.

La password non viene ovviamente salvata nel sistema per impedire che un tecnico possa utilizzarla per decriptare i file. Nel sistema viene generato un GUID univoco il quale poi viene inviato, insieme alla password appena creata, ad un sito dell’hacker. Questo sito si occupa di memorizzare la coppia GUID/Password.

Questo sistema di memorizzazione la password all’esterno ti permette di procedere ad un facile recupero dei file corrotti se il tuo proxy o gateway riesce a memorizzare tutte le chiamate di tipo POST.

Purtroppo non è sempre così poiché il più delle volte le chiamate vengono memorizzate semplicemente senza i campi inviati, dove appunto ci sarebbe la nostra password.  Mi riferisco ad esempio a Squid.

Il malware “lavora” utilizzando Powershell presente nel computer virato. Quindi certamente da Windows 7 in poi l’attacco è assicurato se viene aperto e lanciato l’allegato.

recuperare file corrotti dal virus

La nostra soluzione tecnica

Leggendo il codice del blocco Powershell noto l’istruzione per generare la password:

$Password = (get-random -count 50 -input (48..57 + 65..90 + 97..122) | foreach-object -begin { $pass = $null } -process {$pass += [char]$_} -end {$pass});

 

L’istruzione Get-random genera una password lunga 50 caratteri dai tre insiemi:

  • 48..57 (cifre 0-9)
  • 65..90 e 97..122 (lettere a-z maiuscole e minuscole)

L’approccio forzato obbligherebbe ad utilizzare le combinazioni di una password di 50 caratteri con 62 combinazioni per ogni carattere. Il recupero richiederebbe, con un normale calcolatore di casa, qualche millennio!

Le combinazioni sarebbero 62^50 ovvero

416.470.721.148.178.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000

Conoscendo come funziona la funzione “random” in qualsiasi computer l’idea mi si presenta quasi subito.

Mi spiego. La funzione Random richiede, sempre, un seed per essere inizializzata. In sostanza la funzione random produce una sequenza di numeri casuali diversa da un’altra a seconda del seed iniziale.

Questo perché il computer non conosce la casualità ma bensì la simula, appunto, attraverso la funzione random.

Ma come fa allora a generare una sequenza casuale?

Utilizza un seed “automatico”, ogni volta diverso dal precedente. Ovvero se chiedo al sistema di fornirmi due numeri casuali mi trovo sicuramente al 100% con due numeri differenti.

Se però inizializzo la funzione random in entrambe le richieste con lo stesso seed ottengo in entrambi i casi la stessa sequenza di numeri.

Ma quale numero potrebbe essere definito in automatico?

Fino alla versione 2.0 di PowerShell il numero viene preso dalla variabile di sistema TickCount che altro non è che il numero di millisecondi trascorsi dall’accensione del pc al momento in cui viene effettuata la richiesta.

Per le versioni successive questo numero viene generato in modo differente e il presente modello di recupero non è applicabile. Questo caso potrei analizzarlo in futuro, se necessario.

Facciamo un test?

Ok. Apriamo una console ISE di PowerShell 2 e digitiamo le seguenti istruzioni:

$Ticks=[Environment]::TickCount

$Password = (get-random -count 50 -input (48..57 + 65..90 + 97..122) | foreach-object -begin { $pass = $null } -process {$pass += [char]$_} -end {$pass});

Write-Output $Ticks

Write-Output $Password

Il risultato sarà (sul nostro pc):

23913892

Wa67YJXxidovOrE8stGTbpLzSwghB2MRum1FkZyIPKc40jUHV5

Vediamo cosa abbiamo ottenuto.

Attraverso la prima istruzione

$Ticks=[Environment]::TickCount

In questo modo ci siamo fatti estrarre dal sistema il numero di millisecondi dall’accensione: 23913892

Sucessivamente e, molto probabilmente, nella stessa frazione millesimale di secondo abbiamo calcolato la password chiamando la funzione Get-Random.

Il risultato Wa67YJXxidovOrE8stGTbpLzSwghB2MRum1FkZyIPKc40jUHV5 è appunto la nostra password.

Proviamo ora a rieseguire la richiesta della password “inseminando” la get-random con il valore di 23913892.

Il valore ritornato sarà Wa67YJXxidovOrE8stGTbpLzSwghB2MRum1FkZyIPKc40jUHV5

Provare, per credere.

Ricordo che la sequenza sarà sempre la stessa, non solo il primo numero.

Per esempio, trascriviamo le seguenti istruzioni in uno script PowerShell

$xx=get-random -minimum 100 -maximum 999999 -SetSeed 1950

Write-Output $xx

$xx=get-random -minimum 100 -maximum 999999

Write-Output $xx

La prima riga inizializza il seed con il valore 1950 e richiede un numero compreso tra 100 e 999999.

Scommetto che il tuo pc con PowerShell 2.0, ritornerà il valore di 455659!

Successivamente la terza riga chiede un secondo numero casuale senza inizializzare il seed.

Anche qui scommetto che il valore ritornato anche a te è 983630.

Quindi la sequenza, a parità di seed, è sempre la stessa.

Tornando al malware noto che la chiamata alla get-random per generare la password non è la prima ma la seconda. All’inizio lo script scarica dal web lo script vbs per infettare il computer. Lo script viene nominato temporaneamente con un numero random.

Quindi la chiamata per la password risulta essere la seconda. Bene.

Seguendo questa logica il problema principale è quello di definire quale valore (TickCount) utilizzare come seed iniziale.

L’hacker ha commesso un secondo sbaglio.

Nello script salva in un file locale dei pc infetti alcune informazioni. Le memorizza precisamente nella cartella C:\Users\Public\OracleKit.

Il file, sempre lo stesso, si chiama w00log03.tmp. Contiene, giusto per nota, il codice GUID utilizzato dall’hacker per legare la password generata al vostro pc. Ma questo ai fini del recupero dei file perduti non serve.

La data e l’ora della creazione di questo file è la nostra chiave di volta.

Partendo da questa e cercando o di ricordare l’orario di accensione del pc o di leggere dagli eventi del sistema l’effettivo orario di accensione possiamo definire, in modo approssimativo, quale potrebbe essere il valore del TickCount all’attivazione del malware.

Orientiamoci verso un range abbastanza valido, diciamo di circa mezz’ora.

Stiamo parlando di circa 1.800.000 millisecondi. Molto meno delle probabilità di forzare la password di 50 caratteri.

Abbiamo quindi scritto la procedura di decriptazione prendendo un file corrotto di cui eravamo in possesso di una copia non corrotta.

Se non dovessi avere questa possibilità dovresti avvalerti di un’altra tecnica, poco più articolata, ma che garantirebbe sicuramente il successo del recupero dei file infetti. Per esempio utilizzando un file zip dove i primi 4 caratteri sono sempre gli stessi.

Nei nostri test abbiamo distribuito il lavoro di decriptazione su quattro macchine, tutte più o meno con le stesse performance di CPU. Abbiamo evidenziato una tempistica di recupero di circa 20/30 secondi ogni 1000 test. Quindi il risultato è stato di 1.800 test per 30 secondi, diviso le quattro macchine.

Siamo sui 54.000 secondi, 900 minuti: 15 ore in tutto. Diviso per le 4 macchine siamo nell’ordine delle 3 ore e mezza.

Nel nostro caso la soluzione è arrivata dopo circa 2 ore. La password trovata, di 50 caratteri, è quindi stata verificata anche su altri file con il medesimo risultato positivo.

Da qui il resto è normale routine: abbiamo recuperato tutti i file su un computer, per il server avevamo fortunatamente il backup.

A titolo informativo questa è la quota parte di codice PowerShell, da far “girare” solo in ambiente 2.0, per effettuare la decriptazione del file:

function DecryptFile($bytebuffer, $password){

$salt=”BXCODE hack your system”
$init=”BXCODE INIT”
$RijndaelObject = New-Object System.Security.Cryptography.RijndaelManaged
$bytepassword = [Text.Encoding]::UTF8.GetBytes($password)
$salt = [Text.Encoding]::UTF8.GetBytes($salt)
$RijndaelObject.Key = (New-Object Security.Cryptography.PasswordDeriveBytes $bytepassword, $salt, “SHA1”, 5).GetBytes(32)
$RijndaelObject.IV = (New-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15]

$RijndaelObject.Padding=”Zeros”
$RijndaelObject.Mode=”CBC”
$dy = $RijndaelObject.CreateDecryptor()
$ms = New-Object IO.MemoryStream
$cs = New-Object Security.Cryptography.CryptoStream $ms,$dy,”Write”
$cs.Write($bytebuffer, 0,$bytebuffer.Length)
$cs.Close()
$ms.Close()
$RijndaelObject.Clear()
return $ms.ToArray()
}

$bytebuffer contiene o i 40960 caratteri iniziali del file o, nel caso di file di dimensione minore di 40960, tutti i caratteri del file. $password è la password di 50 caratteri.

Ora, se sei arrivato fino a questo punto, sei stato infettato dal malware e hai Windows 7, contattaci! Abbiamo una sorpresa per te!

Se hai trovato utile l’articolo su come recuperare file corrotti dal virus condividilo con i tuoi amici.
Se hai domande o suggerimenti inseriscili pure nei commenti.

Se vuoi leggere altri articoli tecnici ti suggerisco di leggere anche:

Come creare un plugin in WordPress

recuperare file corrotti dal virus