Rootkit之SSDT hook(通过CR0)

SSDT即System Service Dispath Table,它是一个表,这个表中有内核调用的函数地址。
KeServiceDescriptorTable:是由内核(Ntoskrnl.exe)导出的一个表,这个表是访问SSDT的关键,具体结构是
typedef struct ServiceDescriptorTable {
PVOID ServiceTableBase;
PVOID ServiceCounterTable(0);
unsigned int NumberOfServices;
PVOID ParamTableBase;
}

其中,
ServiceTableBase System Service Dispatch Table 的基地址。
NumberOfServices 由 ServiceTableBase 描述的服务的数目。
ServiceCounterTable 此域用于操作系统的 checked builds,包含着 SSDT 中每个服务被调用次数的计数器。这个计数器由 INT 2Eh 处理程序 (KiSystemService)更新。
ParamTableBase 包含每个系统服务参数字节数表的基地址。

CR0当中有一个写保护位,是保护内存不可写属性的,为了能够写入内核,只能把它的保护给咔嚓掉了,不过……如果做完了手脚但不还原写保护属性的话,极有可能会BOSD.

代码实例如下:

#include <NTDDK.h>

#pragma pack(1)
typedef struct ServiceDescriptorEntry {
unsigned int *ServiceTableBase;
unsigned int *ServiceCounterTableBase; //Used only in checked build
unsigned int NumberOfServices;
unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry, *PServiceDescriptorTableEntry;
#pragma pack()

_declspec(dllimport) ServiceDescriptorTableEntry 

KeServiceDescriptorTable;

NTSYSAPI NTSTATUS ZwOpenProcess(OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId);

typedef NTSTATUS (*ZWOPENPROCESS)(OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId);

#define SYSTEMSERVICE(_function) 

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

ZWOPENPROCESS OldZwOpenProcess;

NTSTATUS MyZwOpenProcess(PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PCLIENT_ID ClientId)
{
NTSTATUS ntStatus = STATUS_SUCCESS;

KdPrint(("MyZwOpenProcess\r\n"));

//调用原来的NtOpenProcess;
ntStatus = OldZwOpenProcess(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);

return ntStatus;
}

VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
__asm{//去掉内存保护
cli
mov  eax,cr0
and  eax,not 10000h
mov  cr0,eax
}

(ZWOPENPROCESS)SYSTEMSERVICE(ZwOpenProcess) = OldZwOpenProcess;//恢复HOOK SSDT

__asm{//恢复内存保护 
mov  eax,cr0
or   eax,10000h
mov  cr0,eax
sti
}

KdPrint(("驱动卸载完毕!\r\n"));
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING pRegistryPath)
{
NTSTATUS status = STATUS_SUCCESS;
KdPrint(("The driver begin loading.\r\n"));
DriverObject->DriverUnload = DriverUnload;
OldZwOpenProcess = (ZWOPENPROCESS)SYSTEMSERVICE(ZwOpenProcess);

__asm{//去掉内存保护
cli
mov  eax,cr0
and  eax,not 10000h
mov  cr0,eax
}

(ZWOPENPROCESS)SYSTEMSERVICE(ZwOpenProcess) = MyZwOpenProcess;    

//HOOK SSDT

__asm{//恢复内存保护 
mov  eax,cr0
or   eax,10000h
mov  cr0,eax
sti
}
KdPrint(("The driver ends loading\r\n"));
return status;
}
posted @ 2013-08-17 15:00  vcerror  阅读(242)  评论(0编辑  收藏  举报