内核驱动开发HOOK SSDT
HOOK SSDT思路:
驱动加载时通过KeServiceDescriptorTable得到函数指针地址 -> 替换其地址为自定义函数地址
驱动卸载时恢复SSDT原来地址
代码部分:
对于KeServiceDescriptorTable的类型定义如下:
typedef struct _SERVICE_DESCRIPTOR_TABLE
{
PULONG ServiceTableBase; //指向系统服务函数地址表
PULONG ServiceCounterTableBase;
ULONG NumberOfService; //服务函数的个数,NumberOfService*4 就是整个地址表的大小
ULONG ParamTableBase;
}SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TABLE;
//KeServiceDescriptorTable为导出函数
extern "C" PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;
驱动入口函数:
extern "C" NTSTATUS DriverEntry ( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath )
{
NTSTATUS status; //定义驱动卸载函数 pDriverObject->DriverUnload = OnUnload; //调用HOOK Hook();
return STATUS_SUCCESS;
}
驱动卸载函数:
VOID OnUnload(IN PDRIVER_OBJECT pDriverObject)
{
//调用恢复HOOK
Unhook();
}
HOOK函数:
VOID Hook()
{
//得到内核函数在SSDT表中索引的地址,其中0x3E是服务ID号
ULONG NtDeleteFileAddress = (ULONG)(KeServiceDescriptorTable->ServiceTableBase+0x3E);
//在SSDT表中取到内核函数的地址,并保存以便卸载驱动的时候恢复
OldNtDeleteFile = *(ULONG*)NtDeleteFileAddress ;
__asm
{
//去掉内存保护
cli mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
//把我们自己函数写进SSDT表中索引位置
*(ULONG*)NtDeleteFileAddress = (ULONG)MyNtDeleteFile;
__asm
{
//恢复内存保护 mov eax,cr0 or eax,10000h mov cr0,eax sti
}
}
UNHOOK函数:
VOID Unhook()
{
//得到内核函数在SSDT表中索引的地址
ULONG NtDeleteFileAddress = (ULONG)(KeServiceDescriptorTable->ServiceTableBase+0x3E);
__asm
{
cli mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
//在SSDT表中索引的地址恢复系统内核函数
*(ULONG*)NtDeleteFileAddress = (ULONG)OldNtDeleteFile;
__asm{ mov eax,cr0 or eax,10000h mov cr0,eax sti }
}
//自定义函数
NTSTATUS MyNtDeleteFile( IN POBJECT_ATTRIBUTES ObjectAttributes)
{
//函数内可做过滤,如放行则可调用原来函数
return STATUS_SUCCESS;
}