Skoči na vsebino

SI-CERT TZ017 / Analiza nalagalnika HijackLoader

Na SI-CERT-u smo v prvi polovici leta 2025 obravnavali številne primere okužb spletnih mest z zlonamerno kodo, ki je pod krinko CAPTCHA preverjanja poskušala na sisteme obiskovalcev spletnih mest prenesti in zagnati zlonamerni tovor za množično krajo kriptosredstev. Opis zlonamernega CAPTCHA preverjanja z ročnim zagonom PowerShell ukaza kot začetnega vektorja okužbe smo objavili v februarju (https://www.cert.si/si-cert-2025-02/), ta tehnični zapis pa opisuje analizo in delovanje najpogosteje prenešenega nalagalnika v kombinaciji s tem tipom okužbe – HijackLoader (tudi IDAT Loader in Ghostpulse).

Spodnja slika prikazuje potek tristopenjske okužbe, pri čemer prvo stopnjo označujemo z začetno izvršljivo (.exe) datoteko, prvotno zagnani PowerShell ukaz na kompromitirani spletni strani pa v tehničnem zapisu označujemo z ničto stopnjo. 

Spodnja slika prikazuje potek tristopenjske okužbe, pri čemer prvo stopnjo označujemo z začetno izvršljivo (.exe) datoteko, prvotno zagnani PowerShell ukaz na kompromitirani spletni strani pa v tehničnem zapisu označujemo z ničto stopnjo. 
Potek tristopenjske okužbe z zlonamerno kodo
Ničto stopnjo okužbe predstavlja vpis PowerShell ukaza po lažnih CAPTCHA navodilih
Ničto stopnjo okužbe predstavlja vpis PowerShell ukaza po lažnih CAPTCHA navodilih

Zlonamerni PowerShell ukaz v pametni pogodbi na verigi Binance Smart Chain (BSC)

Bistven element zlorabe je kopiranje teksta zlonamernega PowerShell ukaza v sistemsko odložišče (clipboard). Spletna stran lahko tekst skopira na različne načine z javascript kodo. V prvotnih primerih se je ta koda nahajala v berljivi obliki, in jo je bilo enostavno identificirati in ugotoviti, kakšen točen tekst spletna stran skopira v odložišče. V kasnejših primerih so napadalci uporabljali različne tehnike zakrivanja (obfuskacije), katerih namen je bil otežitev tako analize s strani varnostnih strokovnjakov, kot detekcije s strani avtomatiziranih sistemov za prepoznavo napadov. 

V enem izmed obravnavanih incidentov je bila na spletno mesto vstavljena zlonamerna JavaScript koda, ki je škodljivi PowerShell ukaz za prenos začetnega nalagalnika pridobila iz vsebine pametne pogodbe na verigi Binance Smart Chain (BSC). Za klic metode v pametni pogodbi je uporabila naslednji aplikacijski binarni vmesnik (Application Binary Interface, ABI), ki omogoča branje njenih podatkov:
{
    “inputs”: [],
    “name”: “jadeCode”,
    “outputs”: [{“internalType”: “string”, “name”: “”, “type”: “string”}],
    “stateMutability”: “view”,
    “type”: “function”
}

Pametna pogodba za pridobivanje zlonamernega PowerShell ukaza skripta definira metodo jadeCode. Ker je v binarnem vmesniku ABI označena s tipom view, njen klic ne spreminja pogodbene vsebine ali sproži kakršnekoli transakcije, temveč služi zgolj njenemu branju (read only). Podtaknjena JavaScript koda, ki je vstavljena na kompromitirani spletni strani, se ob obisku spletne strani poveže na verigo Binance Smart Chain in z definiranim vmesnikom pokliče omenjeno pogodbeno metodo, s katero prenese tekst zlonamernega PowerShell ukaza. Za namene analize smo alternativno skripto za prenos ukaza izvedli z Node.js.

Slika prikazuje pridobivanje zlonamernega PowerShell ukaza iz pametne pogodbe.
Podtaknjena JavaScript koda, ki je vstavljena na kompromitirani spletni strani

Ker pogodba v času pisanja ni potrjena, je na spletnih vmesnikih za njihovo pregledovanje (npr. BscScan) vidna samo njena EVM strojna koda (Ethereum Virtual Machine bytecode), zato je vsebina pogodbe neberljiva. Ethereum Bytecode je nizkonivojska koda, ki se izvaja na Ethereum navideznem stroju (Ethereum VM) in pametnim pogodbam omogoča delovanje na Ethereum podprtih blokovnih verigah, v konkretnem primeru Binance Smart Chain (BSC). 

Pametna pogodba Binance Smart Chain (BSC)
Pametna pogodba Binance Smart Chain (BSC)
Zlonamerno vsebino pametne pogodbe napadalci redno spreminjajo. Slika prikazuje primer ukaza, namenjenega Linux/Unix/macOS sistemom
Zlonamerno vsebino pametne pogodbe napadalci redno spreminjajo

Prenos nalagalnika prve stopnje

Pregled entropije posameznih sekcij izvršljive datoteke razkrije prisotnost šifrirane vsebine v njenih virih. Z orodjem DetectItEasy ugotovimo, da datoteka vključuje resource sekcijo z entropijo, ki se približuje maksimalni vrednosti (8). Z orodjem Malcat Professional razkrijemo, da sekcija vsebuje PNG sliko, katere visoka entropija izhaja iz izrazite nenaključnosti podatkov. Za legitimne slike je namreč značilna prostorska redundanca (medsebojna podobnost sosednjih pikslov), zato je visoka entropija v sklopu analize zlonamerne kode pogosto prvi znak prikrite vsebine ali šifrirane kode. Nadaljnja analiza razkrije, da prenašalnik HijackLoader v tej sliki nosi konfiguracijo in šifrirano lupinsko kodo druge stopnje nalagalnika. 

Visoka entropija v sklopu analize zlonamerne kode je pogosto prvi znak prikrite vsebine ali šifrirane kode
Visoka entropija v sklopu analize zlonamerne kode je pogosto prvi znak prikrite vsebine ali šifrirane kode

Šifrirana konfiguracija se nahaja v slikovnih točkah

V starejših različicah je HijackLoader znotraj slikovnih virov svoje lastne datoteke iskal niz ‘IDAT’, po katerem je tudi dobil enega od svojih imen – IDATLoader. V novejši, analizirani različici, tovor nosi v tabeli bajtnih vrednosti njenih slikovnih točk, ki se nahajajo tik za veljavnim blokom. Lupinska koda prve stopnje z uporabo predhodno razrešenih GDI+ API funkcij sliko naloži v pomnilnik, iz nje izlušči vrednosti slikovnih točk, poišče CRC32 veljavni blok in z njegovimi parametri odšifrira šifriran blok z enostavno XOR operacijo.

Barvna slika je v splošnem 3-slojna matrika, ki za vsakega od treh osnovnih barvnih kanalov (R,G,B) nosi svojo tabelo vrednosti. V analiziranem primeru takšna struktura nalagalniku predstavlja množico več tisoč 16-bajtnih blokov, med katerimi je veljaven zgolj eden. 

Barvna slika je v splošnem 3-slojna matrika, ki za vsakega od treh osnovnih barvnih kanalov (R,G,B) nosi svojo tabelo vrednosti. V analiziranem primeru takšna struktura nalagalniku predstavlja množico več tisoč 16-bajtnih blokov, med katerimi je veljaven zgolj eden.
Barvna slika je v splošnem 3-slojna matrika, ki za vsakega od treh osnovnih barvnih kanalov (R,G,B) nosi svojo tabelo vrednosti.

Nalagalnik poišče edini veljavni blok s primerjavo izračunane in v bloku vključene CRC32 kontrolne vsote. Iz veljavnega bloka v nadaljevanju pridobi XOR ključ in velikost tovora, s katerima odšifrira linearni tovor, ki se v sliki nahaja neposredno za veljavnim blokom. 

Slika prikazuje iskanje CRC32 konfiguracijskega bloka v sliki.
Iskanje CRC32 veljavnega bloka v sliki

Odšifrirano lupinsko kodo nalagalnik tekom celotnega izvajanja nosi v pomnilniški sekciji in je ne spreminja, prenese pa jo tudi v novoustvarjeni proces s tehniko votlenja procesa (Process Hollowing). Nalagalnik namreč v svoji drugi in tretji stopnji uporablja enako lupinsko kodo, ki pa zaradi drugačne konfiguracije v vsaki stopnji delujeta drugače. 

Slika prikazuje odšifriranje konfiguracije in lupinske kode iz slike.
XOR odšifriranje konfiguracije in lupinske kode druge in tretje stopnje

Lupinska koda druge stopnje je namenjena votlenju procesa

Glavna naloga odšifrirane lupinske kode druge stopnje je izvedba votlenja procesa, s katero v novoustvarjeni otroški proces vstavi zlonamerno kodo – sebi povsem enako lupinsko kodo, ki je bila odšifrirana iz slike. Pred votlenjem procesa svoje zlonamerno delovanje prikriva z nalaganjem sekundarne kopije Ntdll z diska, spreminjanjem naloženih knjižnic v pomnilniku in ponarejanjem klicnega sklada. 

Ntdll je najnižje ležeča knjižnica v uporabniški (ang. Userland) plasti operacijskega sistema. Služi kot ovojnica okoli sistemskih klicev, ki v operacijskem sistemu predstavljajo nizkonivojske Zw* API funkcije za komunikacijo z jedrom (kernel). Zaradi njene pomembnosti EDR/XDR orodja vanjo dodatno vstavijo preusmeritvene ukaze (hooks), s katerimi prestrezajo podane argumente funkcijam in si tako pomagajo pri svojem odločitvenem procesu identifikacije zlonamernosti posameznih aplikacij in procesov. Ker je ta varnostni mehanizem avtorjem zlonamerne kode dobro poznan, se ti pogosto odločijo za nalaganje sekundarne kopije knjižnice Ntdll neposredno z diska, v katero EDR/XDR orodja ne posegajo. Nalagalnik HijackLoader v tem ni izjema. 

Ker nalagalnik operacijskega sistema knjižnico Ntdll samodejno naloži v vsak zagnan proces, njeno ponovno dinamično nalaganje po običajnem postopku (LoadLibrary) ni možno. Nalagalnik zato datoteko knjižnice Ntdll odpre kot datoteko z diska s klicem API funkcije ZwCreateFile s podano potjo “C:\Windows\System32\ntdll.dll”. S pridobljenim ročajem (handle) kliče funkcijo ZwCreateSection, s katero ustvari datotečno spominsko sekcijo. Slednjo v pomnilnik mapira s klicem ZwMapViewOfSection. Na ta način sekundarno knjižnico mapira kot sliko (image) in s tem doseže enak učinek, kot če bi knjižnico naložil z običajnim klicem LoadLibrary.

Nalaganje sekundarne NTDLL z diska
Nalaganje sekundarne NTDLL z diska
Pogled v razhroščevalniku po nalaganju dodatne kopije knjižnice z diska.
Pogled v razhroščevalniku po nalaganju dodatne kopije knjižnice z diska

Nalagalnik dodatno naloženo knjižnico uporabi, da prepiše .text sekcijo prvotno naloženih knjižnic Ntdll in Wow64cpu. Prva prikazana funkcija poišče .text sekcijo knjižnice, ki je bila naložena neposredno z diska, druga pa v tej sekciji išče ukaze CALL (opcode 0xE8) in JMP (opcode 0xE9). Te inštrukcije primerja z avtomatsko naloženo knjižnico Ntdll in ob zaznavi odstopanj popravi njene relativne naslove ali zamenja celotno inštrukcijo. Popravki se v pomnilniški prostor procesa zapišejo s kombinacijo klicev ZwProtectVirtualMemory, ZwWriteVirtualMemory in ponovnega ZwProtectVirtualMemory, ki omogočijo začasno spremembo pravic pomnilniške sekcije. Celoten postopek manipulacije sistemskih knjižnic se izvede dvakrat: najprej za Ntdll, nato pa še za wow64cpu.dll.

Primerjava .text sekcij Ntdll in Wow64cpu s kopijama z diska
Primerjava .text sekcij Ntdll in Wow64cpu s kopijama z diska

Razreševanje indeksov sistemskih klicev Zw* funkcij

Nalagalnik izvaja sistemske klice z lastno implementacijo tranzicijske plasti nebeških vrat (Heaven’s gate). Pred izvedbo direktnih sistemskih klicev mora najprej pridobiti njegovo šestnajstiško vrednost – SSN (System Service Number), ki v operacijskem sistemu Windows predstavlja identifikator nizkonivojskega Zw API klica. Lupinska koda s pridobljenim indeksom sistemske klice izvaja neposredno, s čimer se izogne uporabi knijžnice Ntdll, naložene v pomnilniku.

Slika prikazuje lastno implementacijo nebeških vrat (Heaven's Gate) za izvedbo direktnih sistemskih klicev.
Lastna implementacija nebeških vrat (Heaven’s Gate) za izvedbo direktnih sistemskih klicev

Spodaj prikazana funkcija pridobi ročaj (handle) do datoteke ntdll.dll z diska, v datoteki poišče njeno NT zaglavje (NT Headers) in na odmiku 0x78 dostopa do njene izvozne tabele (export directory). V tej se nahajajo trije ključni seznami: AddressOfNames, AddressOfNameOrdinals in AddressOfFunctions. Za pridobivanje relativnega odmika (offset) naslova posamezne Zw API funkcije mora lupinska koda uporabiti vse 3 sezname. 
Za vsako izvoženo funkcijo primerja začetek njenega imena z “Zw” (v Little Endian v kodi “wZ”) in v primerih ujemanj pridobi relativni odmik pripadajočih API funkcij. Ker je knjižnica Ntdll samo ovojnica okoli sistemskih klicev, funkcija preveri ujemanje z inštrukcijo 0xB8, ki v x86 zbirniku predstavlja inštrukcijo MOV EAX, IMM32, oziroma kopiranje 4-bajtne SSN vrednosti v register EAX, ki ga Ntdll izvede tik pred sistemskim klicem. Tako pridobljene SSN indekse funkcija shrani v strukturo na skladu.

Pridobivanje SSN z NTDLL z diska
Pridobivanje SSN z NTDLL z diska

Tako pridobljene SSN indekse nalagalnik uporabi pri izvedbi direktnih sistemskih klicev, ki jih v drugi stopnji svojega izvajanja uporabi za votlenje procesa (Process Hollowing) in v tretji stopnji za izvedbo NTFS trasakcij. Pri tem popolnoma zaobide uporabo katerekoli izmed naloženih knjižnic NTDLL v pomnilniku, s čemere se izogne običajnemu preverjanju EDR/XDR orodij. 

Ustvarjanje procesa iz ločene lupinske kode in njeno čiščenje

Nalagalnik nov proces more.com ustvari s klicem API funkcije CreateProcessW, ki jo izvede iz ločene lupinske kode in brez uporabe direktnih sistemskih klicev. Lupinsko kodo za ustvarjanje procesa vstavi v sistemsko knjižnico Shdocvw.dll, prepisano originalno kodo te knjižnice pa si začasno shrani v medpomnilnik (2. točka na sliki). Za dodatno prikrivanje zlonamerno kodo izvede šele po odstranitvi pravic za pisanje, ko so pravice pomnilniške sekcije nastavljene na PAGE_EXECUTE_READ (0x20) (točka 3). Ko dodatna lupinska koda uspešno ustvari nov proces (4), jo nalagalnik po zaključku njenega izvajanja z namenom prikrivanja sledi pobriše. S funkcijo VirtualProtect (5) v ta namen pomnilniški sekciji začasno dodeli pravice za pisanje PAGE_EXECUTE_READWRITE (0x40), prepiše vstavljeno lupinsko kodo z originalno, predhodno shranjeno vsebino (6) in nato zaščito povrne na PAGE_EXECUTE_READ (0x20), s čimer za seboj prikrije sledi injeciranja zlonamerne kode v knjižnico (DLL injection). 

Ko dodatna lupinska koda uspešno ustvari nov proces, jo nalagalnik po zaključku njenega izvajanja z namenom prikrivanja sledi pobriše.
Ko dodatna lupinska koda uspešno ustvari nov proces, jo nalagalnik po zaključku njenega izvajanja z namenom prikrivanja sledi pobriše.

Ustvarjanje novega procesa s cevjo

Za tehniko votlenja procesa (Process Hollowing) je običajno, da nalagalnik nov otroški proces zažene v suspendiranem stanju, dealocira pomnilniško sekcijo in jo nadomesti z zlonamerno kodo. Analiziran vzorec nalagalnika HijackLoader na tem koraku odstopa, saj otroškega procesa ne zažene v suspendiranem stanju, temveč pri klicu CreateProcessW specificira argument _STARTUPINFOW z nastavljeno cevjo (pipe). Ko v nov proces vstavi zlonamerno sekcijo, proces zažene s pisanjem /r/n v cev in klicem ZwResumeThread.

Struktura _STARTUPINFOW ob ustvarjanju novega procesa nosi ročaj do cevi.
Struktura _STARTUPINFOW ob ustvarjanju novega procesa nosi ročaj do cevi.

Podajanje konfiguracije med stopnjami

S postopkom votlenja procesa se v novi proces vstavi zgolj lupinska koda nalagalnika, ne pa tudi njena konfiguracija, ki nalagalniku omogoča pravilno delovanje (različne vrednosti, zastavice, konstante, imena procesov, ki sodelujejo pri odpakiranju, ipd.)
V drugi stopnji nalagalnik konfiguracijo in lupinsko kodo v šifrirani obliki zapiše na disk v datoteko z naključnim imenom znotraj mape %TEMP%. Pred zapisom vsebino XOR šifrira s ključem, izračunanim iz CRC32 kontrolne vsote imena računalnika (preko API funkcije GetCompNameW) in konstante 0xA1B2D3B4. Na ta način v prvi stopnji enostavno prikrije svojo konfiguracijo, jo zapiše v datoteko na disku in nanjo usmeri novo okoljsko spremenljivko (Environment variable). 
V tretji stopnji – v novem procesu (za analiziran vzorec je to proces more.com) do te šifrirane konfiguracijske datoteke dostopa v obratnem vrstnem redu – preko okoljske spremenljivke najprej identificira njeno mesto na disku, ponovno izračuna CRC32 kontrolno vsoto XOR vrednosti imena računalnika in navedene konstante in rezultat uporabi kot XOR ključ pri njenem končnem odšifriranju. 

XOR šifriranje konfiguracije z imenom računalnika pred zapisom na disk
XOR šifriranje konfiguracije z imenom računalnika pred njenim zapisom na disk

Ponarejanje klicnega sklada

Po ugotovitvah raziskovalcev Zscaler nalagalnik pred izvedbo direktnih sistemskih klicev opravi ponarejanje klicnega sklada (call stack spoofing), s čimer prikrije njegov seznam naslovov za vračanje (return addresses).

Varnostna orodja EDR/XDR namreč poleg preverjanja klicev nizkonivojskih klicev in nastavljenih parametrov pogosto pregledujejo tudi klicni sklad in tako identificirajo klice API funkcij, ki ne izvirajo iz sistemskih knjižnic, temveč zlonamernih procesov. Nalagalnik Hijackloader opisano preverjanje klicnega sklada zaobide z nastavitvijo lažnih naslovov za vračanje, pri čemer njihove vrednosti prepiše z naslovi legitimne sistemske knjižnice. 

Funkcija za preverjanje naslova za vračanje v prvem argumentu sprejme strukturo, ki vključuje štiri ključne celoštevilske člane: začetni in končni naslov .text sekcije knjižnice Ntdll ter začetni in končni naslov .text sekcije knjižnice Kernelbase.  S temi mejami funkcija preverja, ali naslov za vračanje trenutne funkcije s klicnega sklada leži znotraj območij omenjenih sistemskih knjižnic. Ker se klic funkcije nahaja v zanki, ta izvede preverjanje naslovov za vračanje po celotnem skladu oklepajoče funkcije. Svoje zunajležeče naslove za vračanje popravi tako, da kažejo na legitimno sistemsko knjižnico, ki je navedena v konfiguraciji, odšifrirani iz slike v prvi stopnji nalagalnika (v tem primeru shdocvw.dll). 

Nalagalnik Hijackloader opisano preverjanje klicnega sklada zaobide z nastavitvijo lažnih naslovov za vračanje, pri čemer njihove vrednosti prepiše z naslovi legitimne sistemske knjižnice.
Nalagalnik Hijackloader preverjanje klicnega sklada zaobide z nastavitvijo lažnih naslovov za vračanje, pri čemer njihove vrednosti prepiše z naslovi legitimne sistemske knjižnice.

Funkcija izbere naključni naslov v naslovnem prostoru naložene knjižnice, ki je definirana v konfiguraciji nalagalnika (v analiziranem primeru uporabi naslovni prostor knjižnice shdocvw.dll) in njene naključne naslove uporabi pri ponarejanju klicnega sklada pri klicih API funkcij. Spodaj prikazana funkcija prepiše kazalce v strukturi, kamor so bili predhodno shranjeni originalni naslovi za vračanje, ki niso pripadali dovoljeni sistemski knjižnici (ntdll.dll ali kernelbase.dll) v predhodnem preverjanju. 

Spodaj prikazana funkcija prepiše kazalce v strukturi, kamor so bili predhodno shranjeni originalni naslovi za vračanje, ki niso pripadali dovoljeni sistemski knjižnici (ntdll.dll ali kernelbase.dll) v predhodnem preverjanju.
Prikazana funkcija prepiše kazalce za vračanja na naslov, ki kaže v legitimno sistemsko knjižnico

Rezultat ponarejanja klicnega sklada je sprememba naslovov za vračanje ob klicu tranzicijske plasti nebeških vrat (Heaven’s gate) ob izvedbi nizkonivojskih API funkcij za votlenje procesa v drugi stopnji nalagalnika. Ponarejanje klicnega sklada lahko zmede orodja EDR/XDR, ki poleg sistemskih klicev in nastavljenih parametrov pregledujejo tudi klicni sklad, nalagalnik pa svojo lupinsko kodo v otroški proces vstavi z manjšo verjetnostjo zaznave varnostnih orodij.

Slika prikazuje rezultat ponarejanja klicnega sklada
Ponarejanja klicnega sklada

Uporaba NTFS transakcij za vstavljanje končnega tovora

Uporaba transakcij je v splošnem značilna za podatkovne baze, njihova glavna prednost pa je atomarnost (nedeljivost), kar pomeni, da se izbrana množica operacij izvede v celoti ali pa sploh ne. Podoben koncept transakcij so v jedro operacijskega sistema vpeljali tudi razvijalci podjetja Microsoft. 

Uporaba NTFS transakcij je bila javnosti prvič predstavljena v operacijskem sistemu Windows Vista, funkcionalnosti pa so se ohranile v vseh njegovih novejših različicah, vključno z Windows 11. Glavna ideja razvijalcev NTFS transakcij je bila poenostavitev dela razvijalcem, ki so v svoje aplikacije na enostaven način želeli dodati zanesljiv in varen mehanizem zapisovanja datotek na disk, in to funkcionalnost integrirati v jedro operacijskega sistema (kernel).

Sistem transakcij ob zapisovanju datoteke na disk sproti zapisuje dnevnik, postopek zapisovanja datoteke pa je uspešno zaključen šele s potrditvijo transakcije (commit). V primeru kritične napake pri zapisovanju, kot je npr. izguba električnega napajanja ali napaka na disku med postopkom zapisovanja, pa operacijski sistem glede na vsebino dnevnika povrne sistem na stanje pred začetkom transakcije, s čimer prepreči delno zapisovanje ene ali večih datotek. Nameščanje dodatnih programov ali aplikacijskih komponent je pogosto obširen postopek, ki na sistemu spremni številne datoteke in vrednosti v registru, zato lahko spreminjanje samo dela datotek in registrskih vrednosti ob neuspešni namestitvi onesposobi tudi operacijski sistem. Gre torej za mehanizem zagotavljanja integritete podatkov (in posledično tudi razpoložljivosti sistema), ki kljub vsem dodatnim zanesljivostim mehanizmom, glede na Microsoftove meritve, vnaša samo nekaj (približno 6%) dodatne časovne zakasnitve v primerjavi z običajnim zapisovanjem na disk. 

NTFS transakcije je za posodabljanje operacijskega sistema uporabljal Vista Client System update, nekaj časa pa so ga nameravali integrirati tudi razvijalci nameščevalnika NSIS. Zaradi kompleksnosti uporaba mehanizma med razvijalci nikoli ni zaživela, vse do leta 2017, ko so raziskovalci podjetja enSilo na konferenci BlackHat predstavili uporabo transakcij za vstavljanje zlonamernega tovora v t.i. tehniki podvajanja procesa (Process Doppelgänging, https://www.youtube.com/watch?v=Cch8dvp836w). 

Nalagalnik HijackLoader iz naše analize v svoji tretji stopnji izvajanja uporablja hibridni pristop s kombinacijo predstavljene tehnike podvajanja procesa (Process Doppelganging) in votlenja procesa (Process Hollowing), ki ga prikazuje spodnja shema. 

Nalagalnik HijackLoader iz naše analize v svoji tretji stopnji izvajanja uporablja hibridni pristop s kombinacijo predstavljene tehnike podvajanja procesa (Process Doppelganging) in votlenja procesa (Process Hollowing), ki ga prikazuje spodnja shema.
Hibridni pristop za vstavljanje končnega tovora

Lupinska koda tretje stopnje – ustvarjanje dvojnika procesa

Avtorji nalagalnika HijackLoader NTFS transakcije ne uporabljajo zaradi zagotavljanja zanesljivosti zapisa, temveč zaradi dodatnega nivoja izolacije zlonamernega tovora. Datoteka, ki je predmet transakcije, je namreč nedostopna in na disku nevidna vsem ostalim procesom, vključno z AV/EDR/XDR orodji.

S klicem ZwCreateTransaction preko tranzicijske plasti najprej ustvari transakcijski objekt in za tem s klicem RtlSetCurrentTransaction ustvarjeni objekt priredi trenutni niti procesa. Nato v mapi %TEMP% s klicem funkcije ZwCreateFile ustvari naključno poimenovano transakcijsko datoteko in vanjo s periodičnimi klici ZwWriteVirtualMemory iz pomnilniške sekcije po 1024 bajtnih izsekih zapiše celotno vsebino zlonamernega tovora. Nalagalnik na ta način na disk zapiše datoteko končnega tovora (v analiziranem primeru SectopRAT) in pri tem izkoristi prednosti zapisa na disk, ne da bi bila datoteka pri tem vidna kateremukoli drugemu procesu, kot to prikazuje spodnja slika. V razhroščevalniku x64dbg je viden ročaj (Handle) na transakcijsko datoteko s končnim tovorom, a je ta vsem ostalim procesom nedostopna, kot to ponazarja spodnja slika.

V razhroščevalniku x64dbg je viden ročaj (Handle) na transakcijsko datoteko s končnim tovorom, a je ta vsem ostalim procesom nedostopna, kot to ponazarja slika.
V razhroščevalniku x64dbg je viden ročaj (Handle) na transakcijsko datoteko s končnim tovorom, a je ta vsem ostalim procesom nedostopna.

S pridobljenim ročajem do začasne datoteke (v katerem se nahaja zlonamerni tovor) nalagalnik kliče API funkcijo ZwCreateSection, s katerim ustvari objekt pomnilniške sekcije, ki temelji na transakcijski datoteki zapisanega tovora. Ta korak je ključen, saj z datoteko tovora z diska lahko ustvari sekcijo, ki jo kasneje mapira v pomnilnik kot sliko izvršljive datoteke (image). 

Ustvarjanje nove sekcije z zlonamernim tovorom
Ustvarjanje nove sekcije z zlonamernim tovorom

Po ustvarjanju nove sekcije nalagalnik datoteke končnega tovora ne potrebuje več, zato z uporabo API klica ZwRollbackTransaction prekliče transakcijo in tako navkljub vstavljanju vsebine datoteke v pomnilniško sekcijo te datoteke nikoli dejansko ne zapiše na disk. Vsebina te datoteke je vidna le znotraj NTFS transakcije, zato je nedostopna drugim procesom, to pa pomeni, da nalagalnik za sabo prekrije vse sledi zapisa končnega tovora na disk. Preklic transakcije dokončno zaključi s klicem ZwClose, s katerim zapre TmTx transakcijski objekt.

Nalagalnik za sabo prekrije vse sledi zapisa končnega tovora na disk.
Nalagalnik za sabo prekrije vse sledi zapisa končnega tovora na disk.

Preklicu transakcije sledi ustvarjanje novega, tokrat zadnjega procesa, kamor nalagalnik ponovno s tehniko votlenja procesa (Process Hollowing) vstavi pridobljeno kodo končnega tovora. Izbira končnega procesa je odvisna od odšifrirane konfiguracije, v analiziranem primeru pa gre za legitimni proces MSBuild.exe z diska. Novi suspendirani proces ustvari s klicem API funkcije CreateProcessW (v tem primeru MSBuild.exe), pri čemer je to edini klic API funkcije brez uporabe tranzicijske plasti nebeških vrat v postopku votlenja procesa. Za ustvarjanjem otroškega procesa pokliče funkcijo ZwReadVirtualMemory, s katero prebere bazni naslov slike novoustvarjenega procesa iz njegove PEB strukture. 

Z enako triado API klicev, s katero je nalagalnik v drugi stopnji naložil dodatno knjižnico Ntdll (CreateFileW, ZwCreateSection in ZwMapViewOfSection), v tretji stopnji v novoustvarjeni otroški proces mapira knjižnico colorui.dll, kamor v nadaljevanju vstavi lupinsko kodo. S klicem ZwGetContextThread pridobi kontekst (vrednosti registrov) in nastavi nov inštrukcijski register (EIP) s klicem ZwSetContextThread. Omenjeno lupinsko kodo vstavi z zaporednima klicema ZwProtectVirtualMemory, s katero spremeni pravice destinacijski sekciji, in ZwWriteVirtualMemory, s katerim vanjo zapiše lupinsko kodo. 

Med postopkom zapisa lupinske kode v otroški proces nalagalnik večkrat pokliče ZwDelayExecution. Po uspešnem zapisu pokliče funkcijo ZwResumeThread, s katero nadaljuje nastavljeno nit otroškega procesa in za tem zaključi svoje izvajanje.

Persistenca

Nalagalnik v tretji stopnji izvajanja vzpostavi persistenco z nastavitvijo bližnjice (.lnk) in uporabo mehanizma Component Object Mode (COM), ki je sicer namenjen interprocesni komunikaciji. 
S klicem funkcije CopyFileW najprej kopira prvotno datoteko prve stopnje nalagalnika v kopijo na poti %APPDATA%\WCA\JRWorker.bin — gre za povsem enako datoteko, ki jo je prenesel zlonamerni PowerShell ukaz na strani lažnega CAPTCHA preverjanja. 

Nalagalnik nato v mapi %TEMP% ustvari novo naključno poimenovano datoteko, pri čemer naključno ime ustvari s pomočjo funkcij RtlRandom in QueryPerformanceCounter. Ustvarjeno .lnk bližnjico usmeri na omenjeno kopijo prve stopnje – novoustvarjeno datoteko JRWorker.bin. Za ustvarjanjem bližnjice nalagalnik to datoteko registrira kot ukaz za izvedbo COM objekta, kar mu omogoča, da datoteko prve stopnje ponovno zažene ob vsakem vnovičnem klicu funkcije CoCreateInstance s pripadajočim identifikatorjem razreda CLSID. Na koncu s klicem funkcije ExpandEnvironmentStringsW sestavi niz poti do zagonske mape %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup in ji pripne ime bližnice JRWorker.lnk, ki kaže na omenjeno kopijo datoteke prve stopnje, zapisane v prejšnjem koraku. Z zapisom bližnjice v Startup mapo dokončno vzpostavi persistenco in si omogoči izvajanje ob vsakem zagonu okuženega sistema. 

Nalagalnik v tretji stopnji izvajanja vzpostavi persistenco z nastavitvijo bližnjice (.lnk) in uporabo mehanizma Component Object Mode (COM), ki je sicer namenjen interprocesni komunikaciji.
Nalagalnik v tretji stopnji izvajanja vzpostavi persistenco z nastavitvijo bližnjice (.lnk) in uporabo mehanizma Component Object Mode (COM), ki je sicer namenjen interprocesni komunikaciji.

Končni tovor

Končni tovor je sicer neodvisen od delovanja nalagalnika, vseeno pa za celovitost analize vzorca dodajamo kratko analizo pripadajočega tovora in njegove indikatorje zlorabe. V vseh obravnavanih primerih na odzivnem centru SI-CERT so vzorci nalagalnika odšifrirali in naložili zlonamerni tovor ene izmed družin, namenjene kraji uporabniških podatkov in kriptodenarnic, najpogosteje LummaStealer in SectopRAT. V analiziranem primeru nalagalnik izvede končni tovor družine SectopRAT, ki tekom celotnega izvajanja ostane v pomnilniku, z edino izjemo zapisa pri NTFS transakciji, ko je vsem preostalim procesom popolnoma nedostopen. S kontrolnim strežnikom komunicira preko TCP povezave z navedenim IP naslovom, v primeru neuspele povezave pa lahko pridobi nadomestni IP iz javne .txt datoteke na spletni strani pastebin.com. V tem primeru sta ta naslova enaka. 

V vseh primerih, ki smo jih obravnavali na SI-CERT so vzorci nalagalnika odšifrirali in naložili zlonamerni tovor ene izmed družin, namenjene kraji uporabniških podatkov in kriptodenarnic
V vseh primerih, ki smo jih obravnavali na SI-CERT so vzorci nalagalnika odšifrirali in naložili zlonamerni tovor ene izmed družin, namenjene kraji uporabniških podatkov in kriptodenarnic

Indikatorji zlorabe (IoC)

  • SHA256 zgoščena vrednost datoteke nalagalnika Hijackloader: 488b4f0ab9ae82910cb1812ccf655c420cc7aea1eb03a4728265bcd1fe7f1cb6
  • SHA1 datoteke nalagalnika: ab9350c8ea0d395de2fe223040f95c923f36598a
  • Naslov zlonamerne pametne pogodbe na blokovni verigi Binance Smart Chain: 0x53fd54f55C93f9BCCA471cD0CcbaBC3Acbd3E4AA
  • C2 IP naslov končnega tovora SectopRAT: 185.147.124[.]181 

Preberite tudi

Spletni seminar o naprednih napadih na podjetja

Spletni seminar o sodobnih naprednih in ciljanih napadih družbenega inženiringa na organizacije.
Več

SI-CERT na vaji Locked Shields 2025 – pogled skozi oči tekmovalca

Slovenija je skupaj z ekipo Italije in Nacionalne garde ameriške zvezne države Kolorado sodelovala na največji in najzahtevnejši vaji kibernetske varnosti na svetu Locked Shields 2025. Skupna ekipa je osvojila odlično …
Več

Posvet o izobraževanju zaposlenih o kibernetski varnosti

V sredo, 4. junija 2025, je v Ljubljani potekal posvet o izobraževanju zaposlenih o kibernetski varnosti, organiziran pod okriljem Nacionalnega odzivnega centra za kibernetsko varnost SI-CERT. Dogodek je pod naslovom …
Več