Rootkit ( eng. rootkit , det vill säga " root set ") är en uppsättning programvaruverktyg (till exempel körbara filer, skript, konfigurationsfiler ) som tillhandahåller:
Termen Rootkit kom historiskt från UNIX -världen , och denna term syftar på en uppsättning verktyg eller en speciell kärnmodul som en angripare installerar på ett datorsystem som han har hackat omedelbart efter att ha fått superanvändarrättigheter. Denna uppsättning innehåller som regel en mängd olika verktyg för att täcka spåren av ett intrång i systemet, göra sniffers , skannrar, keyloggers , trojaner osynliga , och ersätta de viktigaste UNIX-verktygen (i fallet med ett icke-nukleärt rootkit). Rootkit låter en angripare få fotfäste i ett komprometterat system och dölja spår av deras aktiviteter genom att dölja filer, processer och själva närvaron av ett rootkit i systemet.
Ett rootkit kan installeras i ett system på olika sätt: genom att ladda ner via en exploit , efter att ha erhållit skalåtkomst (i det här fallet kan ett verktyg som wget eller den ursprungliga FTP-klienten användas för att ladda ner rootkit från en fjärrenhet), i källkoden eller resurserna för programvaruprodukten.
Det finns olika rootkit-teknologier, de vanligaste är call table capture (IAT, IDT, SSDT, GDT ), funktionsavlyssning (till exempel modifiering av initiala bytes), direkt modifiering av systemobjekt (DKOM), metoder för att använda drivrutiner.
Fånga samtalstabellerAnropstabellen är en array i vilken varje element lagrar adressen för motsvarande procedur. Sådana tabeller finns både i kärnläge (IDT, CPU MSR, GDT, SSDT, IRP-utskickningstabell) och i användarläge (IAT).
Import Address Table (IAT) är huvudanropstabellen för användarlägesmoduler. De flesta körbara filer har en eller flera inbyggda IAT:er som innehåller adresserna till biblioteksrutiner importerade från DLL:n [2] .
På en multiprocessormaskin finns det flera instanser av anropstabeller (t.ex. IDT, GDT , MSR ). Eftersom varje processor har sina egna systemregister (i synnerhet GDTR - det globala deskriptortabellregistret (GDT), innehåller IDTR - avbrottstabellbeskrivningsregistret (IDT) och IA32_SYSENTER_EIP - den virtuella adressen till kärnlägesingångspunkten (MSR)) , den har också egna systemstrukturer [3] .
När en post i anropstabellen ändras, styrs exekveringen av program och vid behov omdirigeras till de nödvändiga funktionerna. Den avlyssnade proceduren kan [4] :
Den allmänna idén med fångst är följande:
Om avlyssningsfunktionen innebär att den ursprungliga proceduren anropas, utförs blockering och övervakning före anropet, parameterfiltrering efter.
IAT är en anropstabell som finns i programmets filstruktur. IAT lagrar adressen till procedurer som exporteras av en viss DLL . Varje DLL som ett program länkar till vid uppstart har sin egen IAT. För att fånga IAT måste du göra följande:
För att manipulera IAT krävs åtkomst till adressutrymmet för applikationen som tabellen tillhör. Ett sätt är att injicera en DLL. Bland metoderna för att injicera en DLL i adressutrymmet för en process kan man specificera [5] :
Funktionsprincipen är baserad på det faktum att de första byten av uppfångade funktioner ersätts av interceptorkoden. Det bör betonas att när du installerar interceptorn analyseras inte koden för den avlyssnade funktionen: de första N byten ändras och inte de första N maskininstruktionerna. Konsekvensen av detta faktum är [6] :
Rootkit-algoritm:
Interceptor operationsalgoritm:
För att avlyssna räcker det med att modifiera de första fem byten av funktionen, i stället för vilken jmp-operationen skrivs, för att överföra kontrollen till rootkit-interceptorn.
Det bör noteras att de enklaste systemen för att skydda mot attacker av denna typ kontrollerar den första byten av de anropade funktionerna för närvaron av jmp-maskinens opkod i dem. Som en motåtgärd använder rootkit-utvecklare tekniker för att "maskera" koden som skrivits i början av interceptorfunktionen (med kommandon som PUSH / RET, placera flera NOP- operatorer eller skräpkod som PUSH AX / POP AX, såväl som element av polymorfism ).
Metoden för att modifiera de första byten av funktioner har ett antal nackdelar, huvudsakligen relaterade till behovet av att återställa maskinkoden för avlyssnade funktioner innan de anropas och återuppfångas efter anropet. Dessa operationer minskar systemets prestanda och kan få flertrådade applikationer att krascha.
DKOM (Direkt Kernel Object Manipulation)Operativsystem i Windows NT- familjen använder standardobjektmodeller. Olika komponenter i exekveringssystemet definierar en eller flera typer av objekt. Varje komponent exporterar i kärnläge en uppsättning funktioner och egenskaper som stöds, kallat COM-gränssnitt, för att manipulera den typen av objekt. Ingen komponent kan direkt komma åt ett annat komponentobjekt. Typiska kärnlägesobjekt är [7] :
Denna design ger flexibilitet och portabilitet, till exempel kan framtida versioner av operativsystemet innehålla kärnkomponenter som definierar liknande objekt, men har en helt annan intern struktur. Om sådana komponenter kommer att exportera funktioner med bevarade namn och parametrar kommer ändringen inte att ha någon effekt [3] .
Direkt manipulation av kärnobjekt är en ganska kraftfull teknik som är svår att upptäcka. Det finns dock ett antal nackdelar, såsom metodinstabilitet, versionsberoende, implementeringskomplexitet på grund av avsaknaden av en dokumenterad beskrivning av objektens strukturer och egenskaper. Trots dessa begränsningar låter den här metoden dig dölja processer, drivrutiner, portar och höja privilegierna för trådar (därav processer).
EPROCESS är en struktur som fungerar som en intern representation av en process (processobjekt). Windows använder en cirkulär dubbellänkad lista över EPROCESS-strukturer för att hålla reda på exekveringsförloppet. Länkar som länkar EPROCESS-objekt finns i fältet ActiveProcessLink, vars struktur är LIST_ENTRY [8] :
typedef struct _LIST_ENTRY { struct _LIST_ENTRY * Flink ; struct _LIST_ENTRY * Blink ; } LIST_ENTRY , * PLIST_ENTRY ;Den enklaste processdöljningsalgoritmen:
Att utesluta en process från processlistan påverkar inte dess utförande. I Windows är kod schemalagd för exekvering på trådnivå, processer definierar sammanhanget i vilket trådarna körs. Att dölja en process görs externt i verktyg som förlitar sig på EPROCESS processobjekt, såsom Task Manager. Kärnavsändaren använder ett annat redovisningsschema som förlitar sig på andra datastrukturer (främst ETHREAD-objektet). Denna metod låter dig dölja processer utan att förlora funktionalitet [9] .
DrivrutinerMicrosofts drivrutinsmodell stöder en skiktad arkitektur, så en I/O-begäran (I/O-begäran, datautbyte mellan applikationer och drivrutiner) kan betjänas av en serie anslutna drivrutiner , som var och en utför sin egen uppgift. En kedja av förare som betjänar en fysisk enhet kallas en stack. Detta modulära tillvägagångssätt gör att nya drivrutiner kan inkluderas i stacken för att öka funktionaliteten. I detta fall ändras eller läggs endast en separat del av kedjan till. Dessutom använder vissa kringutrustning samma styrenheter (och därför I/O-bussar). Modularitet gör att du kan optimera användningen av samma kodblock, istället för att skriva en separat drivrutin för varje enhet.
Tre typer av drivrutiner definieras i WDM-modellen: busdrivrutiner, funktionsdrivrutiner och filterdrivrutiner. Filterdrivrutiner är vanligtvis placerade mellan andra moduler och fångar in IRP:er som passerar genom dem . Innan IRP:n skickas till den intilliggande drivrutinen kan filtret undersöka innehållet eller modifiera det för att påverka ytterligare systembeteende. Till exempel, när du tar en diskbild från en kritisk driftstoppserver, kan en filterdrivrutin användas för att ändra dataströmmen för att dölja vissa filer.
IRP-paket (I/O-förfrågningspaket) är en Windows-kärndatastruktur som tillhandahåller datautbyte mellan applikationer och drivrutinen, såväl som mellan drivrutinen och drivrutinen. När en begäran tas emot från en applikation genererar I/O-hanteraren en lämplig IRP, som lokaliserar och vidarebefordrar till det översta objektet i drivrutinsstacken. Om toppföraren kunde bearbeta den inkommande IRP på egen hand, slutför den begäran och returnerar IRP till I/O-hanteraren. Annars utför föraren partiell bearbetning, lokaliserar det underliggande objektet på stacken och ber I/O-hanteraren att skicka IRP:n till nästa drivrutin.
När du skapar en IRP reserverar I/O-hanteraren minnesområdet efter rubriken. Det tilldelade minnet används för att skriva en array av IO_STACK_LOCATION-strukturer tilldelade för varje stackdrivrutin:
Minnesstorleken motsvarar antalet drivrutiner i stacken. Arrayen är numrerad från 1, motsvarande den nedre stackdrivrutinen. Strukturen innehåller information om förarkontrollfunktionen som anropas av I/O-hanteraren (fälten MajorFunction och MinorFunction), parametrarna som skickas till funktionen (fältet Parametrar, innehållet varierar beroende på funktion), en pekare till förarobjektet (DeviceObject), en pekare till kompletteringsfunktionen (fältet CompletionRoutine, denna funktion finns i drivrutinen på översta nivån).
Förarens kontrollfunktion återställer, när den först tar emot en IRP, parametrarna från lämplig I/O-stackposition genom att anropa IoGetCurrentIrpStackLocation(). Därefter utförs de föreskrivna åtgärderna, varefter, i fallet med vidarebefordran av IRP till den nedre stackdrivrutinen, inträffar följande:
Det finns två standardsätt att ställa in stackpositionen för följande förare [10] :
Funktionen minskar pekaren till matrisen IO_STACK_LOCATION med en. Sålunda, när IRP:n vidarebefordras, kommer pekaren att återställas (automatiskt ökas med en), som ett resultat kommer samma sektion av stacken att användas. När du använder den här metoden kommer det att finnas ett oanvänt område i slutet av stapeln.
Vidarebefordran av en IRP till nästa förare görs med funktionen:
NTSTATUS IoCallDriver ( IN PDEVICE_OBJECT DeviceObject , IN OUT PIRP Irp );Det första argumentet är en pekare till det underliggande drivrutinsobjektet. Metoden för att erhålla en sådan adress bestäms av den specifika kontrollfunktionen, det finns ingen standardmetod.
Varje begäran måste avslutas antingen av den sista föraren i stacken (ingen vidare vidarebefordran av IRP är möjlig) eller av en av uppströmsförarna.
I/O-hanteraren initierar kompletteringsprocessen för en given IRP när någon av IRP-bearbetningsdrivrutinerna anropar IoCompleteRoutine() kompletteringsfunktionen. När den anropas fyller I/O-hanteraren den aktuella förarens I/O-stack med nollor och anropar sedan drivrutinen på högre nivå med termineringsfunktionen inställd på denna IRP. Endast I/O-statusblocket i IRP:n är tillgängligt för att bestämma hur begäran hanteras av drivrutinen på lägre nivå av drivrutinens kompletteringsfunktion på högre nivå.
I själva verket låter filterdrivrutinen som är installerad på detta sätt inte bara bearbeta inkommande IRP-paket (till exempel blockläsning av en viss disksektor), utan också hantera resultaten av bearbetning av nedströmsdrivrutiner genom att initiera avslutningsfunktionen [11] .
En annan metod för att implementera rootkits är att modifiera MBR och starta upp till operativsystemets kärna - bootkits (till exempel BackDoor.MaosBoot).
Denna typ av skadlig kod i Windows-miljön har varit känd sedan början av 1990-talet under namnet stealth-virus .
Förutom sig själv kan ett rootkit, som regel, maskera närvaron i systemet av alla kataloger och filer som beskrivs i dess konfiguration på disken, nycklar i registret . Av denna anledning dök "monterade" rootkit-bibliotek naturligt upp. Många rootkits installerar sina egna drivrutiner och tjänster i systemet (så klart är de också "osynliga").
Rootkits är faktiskt de flesta kopieringsskyddsprogram (och sätt att kringgå dessa skydd - till exempel emulatorer av CD- och DVD-enheter ) .
2005 införlivade Sony BMG Corporation rootkit-baserat skydd i sina ljud-cd-skivor , som installerades utan användarens vetskap.
Dessa är verktyg eller inbyggda moduler som upptäcker närvaron av rootkits i systemet och (i varierande grad) tar bort dem. Det finns många konkurrerande verktyg för detta – både betalda och gratis, men de använder alla liknande principer.
Metoder för att upptäcka rootkitsDet finns en känd algoritm för att fånga MEP rootkits. Dess kärna ligger i det faktum att samma information registreras på flera sätt - med hjälp av API:et och "direkt", varefter den mottagna informationen jämförs på jakt efter avvikelser. Importtabellerna och Native API -anropstabellerna skannas oftast , såväl som strukturellt hela filsystemet.
Den grundläggande arsenalen av rootkit-fällningsverktyg är baserad på följande metoder.
![]() | |
---|---|
I bibliografiska kataloger |
Skadliga program | |
---|---|
Infektiös skadlig programvara | |
Dölja metoder | |
Skadlig programvara för vinst |
|
Genom operativsystem |
|
Skydd |
|
Motåtgärder |
|