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