U Windows okruženjima, DLL-ovi i tehnike ubrizgavanja procesa postale su jedno od najosjetljivijih područja moderne kibernetičke sigurnosti. Oni nisu samo osnova za to koliko aplikacija radi, već i vrlo praktičan način za napadača da se infiltrira u sistem bez previše buke.
Kada čujete za DLL injection, DLL Hijacking ili DLL hijacking , oni zapravo opisuju različite načine iskorištavanja načina na koji Windows učitava i upravlja svojim dinamičkim bibliotekama linkova. Dobro razumijevanje ovih koncepata je ključno bez obzira da li ste softverski programer, član plavog tima, forenzički analitičar ili tester penetracije.
Šta je DLL datoteka i zašto je toliko važna u Windowsu?
DLL (Dynamic-Link Library) je, jednostavno rečeno, biblioteka prethodno kompajliranog koda koju nekoliko aplikacija može dijeliti . Umjesto da se sav kod stavi unutar izvršne datoteke (.exe), Windows dozvoljava da se mnoge uobičajene funkcije (grafika, umrežavanje, šifriranje, Windows itd.) nalaze u odvojenim .dll datotekama.
Ovo ima nekoliko prednosti: štedi memoriju i prostor na disku jer mnogi programi dijele istu biblioteku u RAM-u; specifične komponente se mogu ažurirati bez ponovnog kompajliranja cijele aplikacije; i potiče ponovnu upotrebu testiranog i optimiziranog koda, umjesto da se svaki put "izmišlja točak".
Ako ste programirali u C ili C++, znate da linker može raditi na dva načina: sa statičkim povezivanjem ili sa dinamičkim povezivanjem . Kod statičkog povezivanja, kod biblioteke se kopira u izvršnu datoteku tokom kompajliranja. Kod dinamičkog povezivanja, aplikacija pohranjuje samo reference, a stvarna biblioteka se učitava u memoriju tokom izvođenja.
Za korisnike Windowsa, ove dinamičke biblioteke su dobro poznati DLL-ovi. U praksi, DLL-ovi se učitavaju u memorijski prostor kojem proces može pristupiti, ali su izolirani na nivou adresnog prostora od drugih procesa. Uprkos tome, postoje Windows API-ji koji omogućavaju jednom procesu čitanje i pisanje u memoriju drugog procesa, i upravo tu počinju sigurnosni problemi.

Kako Windows učitava DLL-ove: implicitno, eksplicitno i povezivanje pretrage
Windows može povezati DLL-ove na dva glavna načina: implicitno povezivanje i eksplicitno povezivanje . Razumijevanje ove razlike je ključno za razumijevanje i DLL injekcije i DLL otmice.
Kod implicitnog povezivanja, DLL se deklariše u tabeli uvoza izvršne datoteke. Kada se program pokrene, Windows loader automatski traži i učitava potrebne DLL-ove prije nego što glavni kod počne s izvršavanjem. Ako jedan nedostaje, aplikacija se možda neće ni pokrenuti.
Kod eksplicitnog povezivanja, sam program poziva LoadLibrary / LoadLibraryEx tokom izvođenja programa kako bi učitao određenu DLL datoteku. Ključni parametar je lpLibFileName , koji može biti apsolutna putanja (na primjer, C:\Windows\System32\mylib.dll) ili samo naziv datoteke (mylib.dll).
Kada se proslijedi samo ime, Windows primjenjuje unaprijed definirani redoslijed pretrage DLL-ova . Prvo, provjerava da li je DLL već učitan u memoriju ili pripada listi poznatih DLL-ova (sistemske biblioteke koje se smatraju pouzdanim). Ako ne, pretražuje niz direktorija vrlo specifičnim redoslijedom.
Taj redoslijed se neznatno razlikuje ovisno o tome je li omogućen Sigurni način pretraživanja DLL-ova , ali u suštini Windows obično provjerava direktorij aplikacije, sistemske direktorije, Windows mapu, trenutni radni direktorij i na kraju direktorije definirane u varijabli okruženja PATH.
Problem nastaje kada aplikacija ne navede punu putanju , a napadač može pisati u jedan od tih direktorija. U toj situaciji, jednostavno postavljanje zlonamjernog DLL-a s istim imenom kao i legitimni u jedan od tih "prioritetnih" direktorija dovoljno je da Windows prvi učita njega.
Razlike između programiranja EXE i DLL datoteke
Iz perspektive razvoja, pisanje izvršne datoteke nije isto što i pisanje DLL-a. EXE datoteka obično ima ulaznu tačku u glavnoj funkciji (ili WinMain u Windows aplikacijama), koju direktno poziva učitavač operativnog sistema kada se proces kreira.
S druge strane, DLL koristi funkciju DllMain kao svoju internu ulaznu tačku biblioteke. Ova funkcija se izvršava kada se DLL učita ili istovari u proces, ili kada se niti kreiraju ili uništavaju unutar tog procesa. Kod unutar DllMain mora biti pažljivo izrađen jer se izvršava u osjetljivim kontekstima.
Dok "legitimni" DLL obično izvozi funkcije (na primjer, putem tabele za izvoz) koje druge aplikacije pozivaju, mnogi zlonamjerni DLL-ovi ne izvoze ništa i koncentrišu svu svoju logiku u DllMain, tako da samo njihovo učitavanje pokreće zlonamjerno ponašanje.
Nadalje, kada se DLL ubrizga u proces, on nasljeđuje njegove privilegije i kontekst . Ako se proces pokreće s administratorskim privilegijama ili kao sistemska usluga, DLL će imati isti nivo pristupa, što olakšava eskalaciju i trajnost privilegija.

Šta je procesna injekcija i zašto je toliko opasna?
Ubrizgavanje procesa je tehnika koja omogućava ubrizgavanje i izvršavanje koda unutar memorijskog prostora drugog pokrenutog procesa. Nije ograničena samo na ubrizgavanje DLL-a: obuhvata ubrizgavanje proizvoljnog koda, otimanje niti, ubrizgavanje APC-a, izdubljivanje procesa i još mnogo toga.
U suštini, napadač dobija identifikator ciljnog procesa, alocira memoriju u njegovom adresnom prostoru, tamo zapisuje svoj kod ili putanju do DLL-a , a zatim prisiljava proces da izvrši taj kod, obično kreiranjem udaljene niti ili modifikovanjem konteksta postojeće.
Ovaj pristup je smrtonosan sa stanovišta sigurnosti jer ubrizgani kod radi s istim dozvolama i sigurnosnim tokenom kao i ciljni proces. Nadalje, budući da se primarno nalazi u memoriji, može izbjeći neke sigurnosne kontrole zasnovane na datotekama (tradicionalni antivirusni softver, statička binarna analiza itd.).
Nije slučajnost da mnoge napredne tehnologije prijetnji (APT), bankarski trojanci i ciljana zloupotreba zlonamjernog softvera koriste injekcije kako bi špijunirali, krali podatke, onesposobili sigurnosna rješenja ili održavali stalan pristup kompromitovanim sistemima.
Osnove procesne memorije u Windowsu
Da bismo zaista razumjeli ubrizgavanje procesa, korisno je pregledati kako Windows upravlja memorijom. Svaki proces ima svoj vlastiti virtualni adresni prostor , logički izoliran od ostalih, iako smješten u istoj fizičkoj memoriji.
U 32-bitnim procesima, raspon virtualnih adresa se obično proteže od 0 do 0x7FFFFFFFF, dok u 64-bitnim procesima doseže mnogo više (na primjer, do 0x7FFFFFFFFFF). Upravitelj memorije u sustavu Windows odgovoran je za prevođenje ovih virtualnih adresa u fizičke stranice putem straničenja.
Unutar ovog virtuelnog prostora postoje različite regije: izvršni kod procesa , učitane DLL datoteke, heap-ovi, stekovi niti, područja rezervirana za dijeljenu memoriju itd. Svaka regija ima specifične dozvole pristupa i određenu svrhu.
Tipične dozvole za memoriju uključuju kombinacije kao što su PAGE_READ , PAGE_WRITE , PAGE_EXECUTE ili mješovite varijante kao što je PAGE_EXECUTE_READWRITE . Ako proces pokuša učiniti nešto što nije dozvoljeno u regiji (na primjer, pisanje tamo gdje je dozvoljeno samo izvršavanje), sistem pokreće prekršaj pristupa.
Windows nudi API-je niskog nivoa za manipulisanje memorijom: VirtualAlloc / VirtualAllocEx za alokaciju i dodjeljivanje memorije; VirtualProtect / VirtualProtectEx za promjenu dozvola; ReadProcessMemory i WriteProcessMemory za čitanje i pisanje u druge procese; i VirtualFree / VirtualFreeEx za oslobađanje memorijskih regija.
Glavne tehnike ubrizgavanja u proces
Iako sve teže istom cilju - izvršavanju koda unutar drugog procesa - različite tehnike injektiranja koriste različite kombinacije API-ja i memorijskih obrazaca , što također generira različite otiske prstiju za detekciju.
Klasična DLL injekcija
Najpoznatija metoda je injekcija DLL-a iz udžbenika. Tipičan tok uključuje otvaranje ciljnog procesa pomoću OpenProcess , alokaciju memorije u njegovom prostoru pomoću VirtualAllocEx za pohranu DLL putanje, pisanje te putanje pomoću WriteProcessMemory i konačno kreiranje udaljene niti pomoću CreateRemoteThread koja poziva LoadLibraryA/W koristeći tu putanju.
Kada se LoadLibrary izvrši unutar udaljenog procesa, on učitava zlonamjerni DLL kao da je njegov vlastiti . Od tog trenutka nadalje, biblioteka ima pristup memorijskom prostoru procesa, njegovim učitanim modulima i njegovim resursima, omogućavajući sve, od keylogging-a i snimaka ekrana do krađe podataka i instaliranja dodatnog zlonamjernog softvera.
Direktno ubrizgavanje koda
Druga varijanta je "čisto" ubrizgavanje koda, bez posrednog DLL-a. Umjesto prosljeđivanja putanje biblioteke, napadač direktno upisuje shellcode ili mašinski kod u izvršnu memorijsku regiju ciljnog procesa i uzrokuje da udaljena nit skoči na tu adresu.
Procedura se ponovo vrti oko VirtualAllocEx, WriteProcessMemory i CreateRemoteThread (ili njihovih ntdll ekvivalenata). Rezultat je isti: proizvoljni kod koji se izvršava u kontekstu legitimnog procesa, ali u ovom slučaju, bez potrebe za DLL datotekom na disku.
Otimanje teme
Umjesto kreiranja novih niti, neki napadači preferiraju preuzimanje postojeće niti unutar procesa . Da bi to učinili, koriste API-je kao što su SuspendThread za pauziranje niti, GetThreadContext za čitanje njenog stanja (registri, pokazivači instrukcija itd.), SetThreadContext za preusmjeravanje na njihov zlonamjerni kod i konačno, ResumeThread za nastavak izvršavanja s nove destinacije.
Ponovnim korištenjem legitimne niti, ova tehnika može biti prikrivenija , jer se nova sumnjiva nit koju je kreirao CreateRemoteThread ne pojavljuje, već se ponovo koristi postojeća i autorizirana.
Injektiranje korištenjem APC-a (asinhronog poziva procedure)
APC-ovi vam omogućavaju da programirate funkcije koje će se izvršavati kada nit uđe u stanje upozorenja. Napadač može ovo iskoristiti da stavi poziv svog koda u red čekanja na ciljnoj niti koristeći QueueUserAPC. Kada ta nit obradi svoj APC red čekanja (na primjer, tokom operacije čekanja), izvršit će zlonamjernu rutinu.
Ova tehnika se često viđa u napadima koji pokušavaju oponašati normalnu aktivnost sistema , jer se oslanja na standardne Windows mehanizme.
Reflektivna DLL injekcija
Reflektivna DLL injekcija zaobilazi standardni Windows loader. DLL sadrži vlastiti interni loader koji je sposoban za mapiranje sebe u memoriju, rješavanje uvoza i primjenu relokacija bez korištenja LoadLibrary-ja.
Napadač ubacuje i DLL kod i prilagođeni kod za učitavanje u ciljni proces i izvršava učitavanje. Budući da ne zahtijeva datoteku na datotečnom sistemu, ova tehnika smanjuje zauzetost diska i komplicira detekciju na osnovu tradicionalnih artefakata.
Procesno udubljivanje
Izdubljivanje procesa uključuje kreiranje legitimnog procesa u suspendovanom stanju (CreateProcess sa CREATE_SUSPENDED), odmapiranje njegove originalne slike (NtUnmapViewOfSection/ZwUnmapViewOfSection), alokaciju memorije za novu sliku, pisanje zlonamjernog izvršnog fajla u nju sa WriteProcessMemory, popravak zaglavlja i relokacija, prilagođavanje konteksta glavnog niza (SetThreadContext) da ukazuje na novu ulaznu tačku i konačno nastavak sa ResumeThread.
Rezultat je da se u upravitelju zadataka čini da se izvršava legitimni proces , ali u stvarnosti je njegova memorija zamijenjena zlonamjernim kodom, koji sada radi s identitetom i dozvolama originalne binarne datoteke.
Šta je otmica DLL-a ili otimanje DLL-a?
Otmica DLL datoteka iskorištava način na koji Windows traži DLL datoteke kada nije navedena puna putanja . Ako napadač može pisati u jedan od direktorija koje sistem provjerava prije nego što dođe do originalne DLL datoteke, može ubaciti zlonamjernu verziju s istim imenom.
Zamislite aplikaciju koja pokušava učitati "mylib.dll" bez pune putanje. Windows će prvo provjeriti određene direktorije: vlastiti direktorij aplikacije, sistemski direktorij, Windows mapu, trenutni radni direktorij i one u PATH-u, određenim redoslijedom ovisno o načinu sigurne pretrage.
Ako napadač ima dozvole za pisanje, na primjer, u direktoriju aplikacije ili u direktoriju u PATH-u koji se provjerava prije legitimnog direktorija, samo treba tamo smjestiti svoj zlonamjerni DLL . Windows će ga prvi pronaći i učitati kao da je original.
Ovaj trik se koristi barem od ere Windowsa 2000 i još uvijek je u upotrebi, posebno kada se aplikacije pokreću pri pokretanju sistema ili sa povišenim privilegijama , pretvarajući bilo koju otetu DLL datoteku u put za eskalaciju ili perzistenciju privilegija.
Varijante otimanja DLL datoteka: Bočno učitavanje i fantomska DLL datoteka
U okviru pojmu otimanja DLL datoteka (DLL hijacking), nalazimo nekoliko varijacija. Jedna od najpoznatijih je bočno učitavanje DLL datoteka (sideloading) , gdje se zlonamjerni DLL smješta u direktorij koji je rangiran više u redoslijedu pretrage od direktorija u kojem se nalazi originalni DLL. Na taj način sistem daje prioritet lažnoj kopiji.
U slučaju Phantom DLL Hijacking-a , legitimni DLL ne postoji ni u jednom od pretraženih direktorija. Softver pokušava da ga učita jer mu njegov kod to nalaže, ali pošto ga ne može pronaći, biće učitana prva datoteka sa tim imenom koja se pojavi u važećem direktorijumu za pretragu. Ovo omogućava napadaču da od nule kreira nepostojeći DLL sa odgovarajućim imenom i lokacijom.
Poznate DLL-ove, WinSxS i druge specijalne vektore
Windows održava listu poznatih DLL datoteka u registru (na primjer, u HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs). Ako se naziv DLL datoteke podudara s nekim na ovoj listi, sistem će koristiti vlastitu pouzdanu kopiju, smanjujući rizik od otimanja tih specifičnih modula.
Međutim, postoje sofisticiranije metode, kao što je bočno učitavanje u WinSxS , direktorij C:\Windows\WinSxS gdje se pohranjuje više verzija DLL-ova. Aplikacije koriste manifeste kako bi naznačile koju verziju DLL-a treba učitati. Manipulacijom ovih manifesta ili metapodataka moguće je ubrizgati lažne DLL-ove koje će sistem tretirati kao validne.
Drugi, manje očigledan vektor je modifikacija liste poznatih DLL-ova (KnownDLLs) ili povezanih ključeva registra kako bi se promijenilo koje se DLL-ove smatraju sistemskim DLL-ovima ili kako se oni rješavaju. Napadač s dovoljnim privilegijama može pokušati manipulirati ovim unosima kako bi favorizirao učitavanje vlastitih biblioteka.
Ubrizgavanje procesa i detekcija otmice DLL-a
Otkrivanje ovih tehnika nije lako, jer se oslanjaju na legitimne sistemske mehanizme i jer se veliki dio zlonamjernih aktivnosti odvija u memoriji. Uprkos tome, postoji nekoliko efikasnih strategija.
Analiza pamćenja i ponašanja
Jedan pristup je praćenje područja memorije procesa za neobična izvršna područja ili područja koja nisu povezana s važećim modulima . Stranice označene kao PAGE_EXECUTE_READWRITE, iznenadne promjene u dozvolama memorije ili prisustvo shellcode-a u područjima koja ne odgovaraju binarnim datotekama diska su tipični indikatori.
Također se prate dinamičke modifikacije mape memorije , neobično kreiranje niti i veze između procesa koji normalno ne komuniciraju . Mnogi moderni EDR-ovi implementiraju mehanizme korelacije koji detektuju sumnjive nizove znakova kao što su: OpenProcess → VirtualAllocEx → WriteProcessMemory → CreateRemoteThread.
Praćenje poziva Windows API-ja
Drugi pristup je praćenje korištenja kritičnih API-ja. Tipičan obrazac ubrizgavanja procesa poziva OpenProcess kako bi dobio kontrolu nad procesom žrtve, koristi VirtualAllocEx i WriteProcessMemory za pisanje podataka i završava sa CreateRemoteThread , QueueUserAPC ili SetThreadContext za pokretanje izvršenja.
Slično tome, nizovi korištenja LoadLibrary / LoadLibraryEx sa sumnjivim putanjama, u kombinaciji sa SearchPath ili nepravilnom upotrebom trenutnog radnog direktorija, mogu odati pokušaje otmice DLL-a ili nesigurnog predučitavanja.
Alati kao što su Process Monitor / Process Explorer
Pomoću uslužnih programa poput Process Monitora (Procmon) i Process Explorera, moguće je u realnom vremenu pratiti koje .dll datoteke proces otvara, iz kojih putanja i s kojim rezultatom. Primjenom filtera za prikaz samo DLL-ova i rezultata poput "NAME NOT FOUND " možete otkriti neuspješne pokušaje učitavanja ili pokušaje iz neočekivanih direktorija.
Ako aplikacija učitava DLL-ove iz korisničkog direktorija, iz privremenih putanja ili s nestandardnih lokacija, preporučljivo je provjeriti da li neprivilegovani korisnici ili servisni računi mogu pisati u te direktorije.
Modeli umjetne inteligencije i strojnog učenja
Neka moderna rješenja, kao što su određene SIEM i EDR platforme, počela su koristiti modele mašinskog učenja za identifikaciju obrazaca otmice DLL datoteka. Ovi modeli uzimaju kao ulaz metapodatke iz procesa i biblioteke: putanje, veličinu, internu strukturu, digitalni potpis, promjene imena, lokaciju (standardnu ili nestandardnu) itd.
Kombiniranjem tih informacija s anonimnom telemetrijom i reputacijom u oblaku , model može označiti kao sumnjiv pokušaj učitavanja neobične DLL datoteke s neuobičajene putanje, čak i ako se datoteka ne nalazi ni u jednoj poznatoj bazi podataka zlonamjernog softvera.
Kako ublažiti ubrizgavanje procesa i otmicu DLL-a
Ne postoji jedna kontrola koja rješava sve; odbrana uključuje kombinaciju dobrih praksi razvoja, jačanja sistema i kontinuiranog praćenja . Uprkos tome, postoje jasne mjere koje značajno smanjuju rizik.
Najbolje prakse za programere
Ako programirate na Windowsu, prvo pravilo je jasno: koristite pune putanje kad god je to moguće u LoadLibrary, CreateProcess i ShellExecute . Nemojte se oslanjati na zadani redoslijed pretrage za lociranje kritičnih DLL-ova.
Osim toga, toplo se preporučuje pozivanje funkcije SetDllDirectory("") na početku procesa kako bi se uklonio trenutni radni direktorij (CWD) iz redoslijeda pretrage DLL-a. Ovo sprječava napadača da iskoristi kompromitovani CWD za ubrizgavanje svojih biblioteka.
Također je preporučljivo izbjegavati obrasce poput korištenja SearchPath-a za lociranje DLL-ova koji se zatim učitavaju pomoću LoadLibrary-ja, budući da se redoslijed pretrage SearchPath-a razlikuje od redoslijeda pretrage LoadLibrary-ja i može dovesti do neočekivanih i nesigurnih rezultata.
Kad god je moguće, koristite potpisane DLL-ove i provjerite potpis prije njihovog učitavanja. Druga opcija je provjeriti hash biblioteke i osigurati da se podudara s očekivanom vrijednošću. Ovo smanjuje mogućnost učitavanja manipuliranog DLL-a, čak i ako se nalazi na ispravnoj putanji.
Postavke specifične za Windows
Windows nudi API-je poput SetSearchPathMode za omogućavanje trajnog sigurnog načina pretraživanja u procesu, pomičući CWD na kraj liste za pretraživanje. Nakon što se trajno omogući, sljedeći pozivi koji pokušavaju promijeniti ovaj način neće uspjeti, što će pojačati konzistentnost.
Još jedna osnovna preporuka je izbjegavanje instaliranja aplikacija u korijenski direktorij diska (npr. C:\) jer direktoriji kreirani tamo često nasljeđuju šira prava pisanja za autentificirane korisnike. Bolje je koristiti putanje unutar Program Files ili direktorije s dobro kontroliranim ACL-ovima.
Također je važno pravilno konfigurirati pravila kao što su UAC, AppLocker ili Windows Defender Application Control (WDAC) kako bi se ograničilo koje binarne datoteke i DLL-ove svaki proces može učitati i kako bi se osigurao integritet koda (važeći potpisi) kad god je to moguće.
Kontrole na sistemskom i organizacijskom nivou
Na sistemskom nivou, tehnologije kao što su DEP (Data Execution Prevention - Prevencija izvršavanja podataka) , ASLR (Address Space Layout Randomization - Randomizacija rasporeda adresnog prostora) , Control Flow Guard (CFG - Zaštita toka kontrolera) ili Protected Process Light (PPL - Zaštita zaštićenog procesa) postavljaju dodatne prepreke izvršavanju koda u memoriji i manipulaciji zaštićenim procesima.
Na nivou mreže i organizacije, ključno je ažurirati antivirusna i EDR rješenja , jer se mnoge varijante DLL injekcija i dalje mogu otkriti pomoću potpisa i heuristike. Specifični alati poput DLLSPY-ja mogu pomoći u lociranju ranjivosti eskalacije privilegija zasnovanih na DLL-u.
Konačno, važno je zapamtiti da mnogi zlonamjerni DLL-ovi ulaze u okruženje putem phishinga, socijalnog inženjeringa ili napada u lancu snabdijevanja . Obuka osoblja, implementacija višefaktorske autentifikacije, pregled sumnjivih e-poruka i usvajanje rješenja za upravljanje rizicima trećih strana (TPRM) pomažu u smanjenju ove površine napada.
Cijeli ovaj ekosistem tehnika - klasično ubrizgavanje DLL-a, otmica DLL-a, ubrizgavanje koda, izdubljivanje procesa i druge - pokazuje u kojoj mjeri su dinamičke biblioteke linkova mač s dvije oštrice: neophodne za efikasnost sistema, ali i glavni vektor za napredne napade . Razumijevanje kako one interno funkcionišu, kako se učitavaju i koji alati postoje za njihovo praćenje omogućava mnogo informiranije odluke pri dizajniranju aplikacija, zaštiti krajnjih tačaka i reagovanju na incidente u Windows okruženjima.