A Rootkit ( eng. rootkit , azaz " gyökérkészlet ") olyan szoftvereszközök (például futtatható fájlok, szkriptek, konfigurációs fájlok ) halmaza, amelyek a következőket biztosítják:
A Rootkit kifejezés történelmileg a UNIX világból származik , és ez a kifejezés egy sor segédprogramra vagy egy speciális kernelmodulra utal, amelyet a támadó a szuperfelhasználói jogok megszerzése után azonnal feltört számítógépre telepít. Ez a készlet általában számos segédprogramot tartalmaz a rendszerbe való behatolás nyomainak lefedésére, láthatatlanná téve a szippantókat , szkennereket, kulcsnaplókat , trójaiakat , leváltva a fő UNIX segédprogramokat (nem nukleáris rootkit esetén). A Rootkit lehetővé teszi a támadók számára, hogy megvegyék a lábukat egy feltört rendszerben, és elrejtsék tevékenységeik nyomait azáltal, hogy elrejtik a fájlokat, folyamatokat és a rootkit jelenlétét a rendszerben.
A rootkit többféleképpen telepíthető a rendszerbe: egy exploit segítségével , shell hozzáférés megszerzése után (ebben az esetben egy olyan eszközzel, mint a wget vagy az eredeti FTP kliens használható a rootkite letöltésére egy távoli eszközről), a szoftvertermék forráskódjában vagy erőforrásaiban.
Különféle rootkit technológiák léteznek, a legelterjedtebbek a hívástábla rögzítése (IAT, IDT, SSDT, GDT ), a funkcióelfogás (például a kezdeti bájtok módosítása), a rendszerobjektumok közvetlen módosítása (DKOM), az illesztőprogramok használatának módszerei.
Hívástáblázatok rögzítéseA hívástábla egy tömb, amelyben minden elem a megfelelő eljárás címét tárolja. Ilyen táblák mind kernel módban (IDT, CPU MSR-ek, GDT, SSDT, IRP diszpécsertábla), mind felhasználói módban (IAT) léteznek.
Az Import Address Table (IAT) a fő felhasználói módú modulhívási táblázat. A legtöbb végrehajtható fájl egy vagy több beépített IAT-tal rendelkezik, amelyek a DLL-ből importált könyvtári rutinok címeit tartalmazzák [2] .
Egy többprocesszoros gépen több hívási tábla is létezik (pl. IDT, GDT , MSR ). Mivel minden processzornak saját rendszerregisztere van (különösen a GDTR - a globális leíró tábla regisztere (GDT), az IDTR - a megszakítási tábla leíró regisztere (IDT) és az IA32_SYSENTER_EIP - tartalmazza a kernel módú belépési pont (MSR) virtuális címét). , saját rendszerstruktúrái is vannak [3] .
A hívási tábla egy bejegyzésének megváltoztatásakor a programok végrehajtása vezérlésre kerül, és szükség esetén átirányításra kerül a szükséges funkciókhoz. Az elfogott eljárás [4] :
A rögzítés általános ötlete a következő:
Ha az elfogási funkció az eredeti eljárás hívását jelenti, akkor a hívás előtt a blokkolás és a figyelés, utána a paraméterszűrés történik.
Az IAT egy hívástábla, amely az alkalmazás fájlstruktúrájában található. Az IAT tárolja az adott DLL által exportált eljárások címét . Minden DLL-nek, amelyhez az alkalmazás a rendszerindításkor hivatkozik, saját IAT-ja van. Az IAT rögzítéséhez a következőket kell tennie:
Az IAT manipulálásához hozzá kell férni annak az alkalmazásnak a címteréhez, amelyhez a tábla tartozik. Az egyik módja egy DLL beillesztése. A DLL-nek egy folyamat címterébe történő beillesztésének módszerei között megadható [5] :
A működési elv azon alapul, hogy az elfogott függvények első bájtjait felváltja az elfogó kód. Hangsúlyozni kell, hogy az elfogó telepítésekor az elfogott funkció kódja nem kerül elemzésre: az első N bájt módosul, és nem az első N gépi utasítás. Ennek a ténynek a következménye [6] :
Rootkit algoritmus:
Az elfogó működési algoritmusa:
Az elfogáshoz elegendő a függvény első öt bájtját módosítani, amelyek helyére a jmp műveletet írják, átadva a vezérlést a rootkit elfogónak.
Megjegyzendő, hogy az ilyen típusú támadások elleni védelem legegyszerűbb rendszerei ellenőrzik a hívott függvények első bájtját, hogy bennük van-e a jmp gépi műveletkód. Ellenintézkedésként a rootkit fejlesztők technikákat alkalmaznak az elfogó funkció elején írt kód „lefedésére” (például PUSH / RET parancsokkal, több NOP operátor elhelyezésével vagy szemétkóddal, például PUSH AX / POP AX, valamint polimorfizmus elemeivel ).
A függvények első bájtjainak módosításának módszere számos hátránnyal jár, amelyek főként azzal kapcsolatosak, hogy az elfogott függvények gépi kódját vissza kell állítani a hívás előtt, és a hívás után újra le kell fogni. Ezek a műveletek csökkentik a rendszer teljesítményét, és a többszálas alkalmazások összeomlását okozhatják .
DKOM (Direct Kernel Object Manipulation)A Windows NT család operációs rendszerei szabványos objektummodelleket használnak. A végrehajtási rendszer különféle összetevői egy vagy több típusú objektumot határoznak meg. Mindegyik összetevő kernel módban exportálja a támogatott függvényeket és tulajdonságokat, amelyeket COM-interfésznek neveznek, az ilyen típusú objektumok kezeléséhez. Egyetlen összetevő sem férhet hozzá közvetlenül egy másik összetevő objektumhoz. Tipikus kernel módú objektumok [7] :
Ez a kialakítás rugalmasságot és hordozhatóságot biztosít, például az operációs rendszer jövőbeli kiadásai tartalmazhatnak hasonló objektumokat definiáló, de teljesen eltérő belső szerkezetű kernelkomponenseket. Ha ezek a komponensek megőrzött nevekkel és paraméterekkel exportálnak függvényeket, a változtatásnak nincs hatása [3] .
A kernelobjektumok közvetlen manipulálása meglehetősen hatékony technológia, amelyet nehéz felfedezni. Ennek azonban számos hátránya van, mint például a metódusok instabilitása, a verziófüggőség, a megvalósítás bonyolultsága az objektumok szerkezetének és tulajdonságainak dokumentált leírásának hiánya miatt. E korlátozások ellenére ez a módszer lehetővé teszi a folyamatok, eszközillesztők, portok elrejtését és a szálak (tehát a folyamatok) jogosultságának növelését.
Az EPROCESS egy folyamat (folyamatobjektum) belső reprezentációjaként szolgáló struktúra. A Windows az EPROCESS struktúrák körkörös, kétszeresen összekapcsolt listáját használja a végrehajtás előrehaladásának nyomon követésére. Az EPROCESS objektumokat összekötő hivatkozásokat az ActiveProcessLink mező tartalmazza, melynek szerkezete LIST_ENTRY [8] :
typedef struct _LIST_ENTRY { struct _LIST_ENTRY * Flink ; struct _LIST_ENTRY * Villogás ; } LIST_ENTRY , * PLIST_ENTRY ;A legegyszerűbb folyamatrejtő algoritmus:
Egy folyamat kizárása a folyamatlistából nem befolyásolja a végrehajtását. A Windows rendszerben a kód végrehajtása szál szinten van ütemezve, a folyamatok határozzák meg a kontextust , amelyben a szálak futnak. A folyamatok elrejtése kívülről történik olyan eszközökben, amelyek EPROCESS folyamatobjektumokra támaszkodnak, például a Feladatkezelőben. A kernel diszpécser egy másik elszámolási sémát használ, amely más adatstruktúrákra (elsősorban az ETHREAD objektumra) támaszkodik. Ez a módszer lehetővé teszi a folyamatok elrejtését a funkcionalitás elvesztése nélkül [9] .
IllesztőprogramokA Microsoft illesztőprogram-modellje támogatja a réteges architektúrát, így az I/O kéréseket (I/O kérések, alkalmazások és illesztőprogramok közötti adatcsere) egy sor csatlakoztatott illesztőprogram szolgálja ki , amelyek mindegyike saját feladatot lát el. A fizikai eszközt kiszolgáló illesztőprogramok láncát veremnek nevezzük. Ez a moduláris megközelítés lehetővé teszi új illesztőprogramok beépítését a verembe a funkcionalitás növelése érdekében. Ebben az esetben a láncnak csak egy külön szakasza kerül módosításra vagy hozzáadásra. Ezenkívül egyes perifériák ugyanazokat a vezérlőket (és ezért I/O buszokat) használják. A modularitás lehetővé teszi, hogy optimalizálja ugyanazon kódblokkok használatát, ahelyett, hogy minden eszközhöz külön illesztőprogramot írna.
A WDM-modell három típusú illesztőprogramot határoz meg: busz-illesztőprogram, funkció-illesztőprogram és szűrő-illesztőprogram. A szűrő-illesztőprogramok általában más modulok között helyezkednek el, és rögzítik a rajtuk áthaladó IRP -ket . Mielőtt elküldi az IRP-t a szomszédos illesztőprogramnak, a szűrő megvizsgálhatja a tartalmat, vagy módosíthatja azt, hogy befolyásolja a rendszer további viselkedését. Ha például lemezképet vesz le egy kritikus állásidő-kiszolgálóról, egy szűrő-illesztőprogram használható az adatfolyam módosítására egyes fájlok elrejtése érdekében.
Az IRP csomag (I/O request packet) egy Windows kernel adatstruktúra, amely adatcserét biztosít az alkalmazások és az illesztőprogram, valamint az illesztőprogram és az illesztőprogram között. Amikor egy alkalmazástól kérés érkezik, az I/O menedzser létrehoz egy megfelelő IRP-t, amely lokalizálja és továbbítja az illesztőprogram-verem legfelső objektumát. Ha a felső illesztőprogram képes volt önállóan feldolgozni a bejövő IRP-t, akkor befejezi a kérést, és visszaküldi az IRP-t az I/O-kezelőnek. Ellenkező esetben az illesztőprogram részleges feldolgozást hajt végre, lokalizálja a mögöttes objektumot a veremben, és megkéri az I/O-kezelőt, hogy adja át az IRP-t a következő illesztőprogramnak.
IRP létrehozásakor az I/O menedzser lefoglalja a fejléc utáni memóriaterületet. A lefoglalt memória az egyes verem-illesztőprogramokhoz lefoglalt IO_STACK_LOCATION struktúrák tömbjének írására szolgál:
A memória mérete a veremben lévő illesztőprogramok számának felel meg. A tömb 1-től van számozva, ami megfelel az alsó verem-illesztőprogramnak. A struktúra információkat tartalmaz az I/O menedzser által meghívott illesztőprogram-vezérlő függvényről (MajorFunction és MinorFunction mezők), a függvénynek átadott paraméterekről (Parameters mező, a tartalom függvénytől függően változik), egy mutatót az illesztőprogram objektumra (DeviceObject), egy mutató a befejezési függvényre (a CompletionRoutine mező, ez a funkció a legfelső szintű illesztőprogramban található).
Az illesztőprogram vezérlőfunkciója, amikor először kap egy IRP-t, visszaállítja a paramétereket a megfelelő I/O verem pozícióból az IoGetCurrentIrpStackLocation() meghívásával. Ezután az előírt műveleteket hajtják végre, majd az IRP-nek az alsó verem-illesztőprogramba történő továbbítása esetén a következő történik:
Két szabványos mód van a verempozíció beállítására a következő illesztőprogramhoz [10] :
A függvény eggyel csökkenti az IO_STACK_LOCATION tömbre mutató mutatót. Így az IRP továbbításakor a mutató visszaáll (automatikusan eggyel megnövelve), ennek eredményeként a verem ugyanazt a része kerül felhasználásra. Ha ezt a módszert használja, a verem végén lesz egy kihasználatlan terület.
Az IRP továbbítása a következő illesztőprogramnak a következő funkcióval történik:
NTSTATUS IoCallDriver ( IN PDEVICE_OBJECT DeviceObject , IN OUT PIRP Irp );Az első argumentum egy mutató a mögöttes illesztőprogram objektumra. Az ilyen cím megszerzésének módját az adott vezérlőfüggvény határozza meg, szabványos módszer nincs.
Minden kérést vagy a verem utolsó meghajtójának kell leállítania (az IRP további továbbítása nem lehetséges), vagy az egyik upstream illesztőprogramnak.
Az I/O menedzser elindítja egy adott IRP befejezési folyamatát, amikor az IRP-feldolgozó illesztőprogramok bármelyike meghívja az IoCompleteRoutine() befejezési függvényt. Híváskor az I/O menedzser nullákkal tölti fel az aktuális illesztőprogram I/O veremét, majd meghívja a magasabb szintű illesztőprogramot, amelynek lezárási funkciója erre az IRP-re van beállítva. Az IRP-ben csak az I/O állapotblokk áll rendelkezésre annak meghatározásához, hogy a kérést hogyan kezelje a magasabb szintű illesztőprogram befejezési funkciójának alsó szintű illesztőprogramja.
Valójában az így telepített szűrő-illesztőprogram nem csak a bejövő IRP-csomagok feldolgozását teszi lehetővé (például egy bizonyos lemezszektor blokkolvasása), hanem a downstream illesztőprogramok feldolgozási eredményeinek kezelését is a lezáró funkció inicializálásával [11] .
A rootkitek megvalósításának másik módja az MBR módosítása és az operációs rendszer kernelére való rendszerindítás - bootkit (például BackDoor.MaosBoot).
Az ilyen típusú rosszindulatú kódok a Windows környezetben az 1990-es évek eleje óta ismertek lopakodó vírusok néven .
Önmaga mellett a rootkit általában elfedheti a rendszerben a konfigurációjában leírt könyvtárak és fájlok jelenlétét a lemezen, kulcsokat a rendszerleíró adatbázisban . Emiatt természetesen megjelentek a "csatolt" rootkit könyvtárak. Sok rootkit saját illesztőprogramokat és szolgáltatásokat telepít a rendszerbe (természetesen ezek is "láthatatlanok").
A rootkitek valójában a legtöbb másolásvédelmi szoftver (és olyan eszközök, amelyek megkerülhetik ezeket a védelmet – például a CD- és DVD-meghajtók emulátorai ) .
2005-ben a Sony BMG Corporation rootkit alapú védelmet épített be audio CD -ibe , amelyek a felhasználó tudta nélkül telepítettek.
Ezek olyan segédprogramok vagy rezidens modulok, amelyek észlelik a rootkitek jelenlétét a rendszerben, és (különböző mértékben) eltávolítják azokat. Ehhez számos versengő eszköz létezik – fizetős és ingyenes is, de mindegyik hasonló elveket használ.
Módszerek a rootkitek kimutatásáraIsmert algoritmus a MEP rootkitek elfogására. Lényege abban rejlik, hogy ugyanazt az információt többféle módon - az API segítségével és "közvetlenül" - regisztrálják, majd a kapott adatokat összehasonlítják az eltérések keresésére. A leggyakrabban az importálási táblákat és a natív API -hívástáblákat vizsgálják , valamint szerkezetileg a teljes fájlrendszert.
A rootkit csapdázási eszközök alapvető arzenálja a következő módszereken alapul.
![]() | |
---|---|
Bibliográfiai katalógusokban |
Rosszindulatú szoftver | |
---|---|
Fertőző rosszindulatú programok | |
Rejtős módszerek | |
Malware haszonszerzés céljából |
|
Operációs rendszerek szerint |
|
Védelem |
|
Ellenintézkedések |
|