Ŀ¼
SSDTHOOK
x32下,直接获取系统描述符表.以及调用号.就可以进行HOOK了.
x64下可以设置回调来进行过滤我们想要的功能.当然如果你简单的过一下PatchGuard也可以设置SSDT HOOK.
首先SSDT 我们是可以在windbg下看到的

SSDT表的结构如下:
typedef struct _KSERVICE_TABLE_DESCRIPTOR { PULONG_PTR Base; PULONG Count; ULONG Limit; PUCHAR Number; } KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR; 在WRK中的 ke.h中可以看到.

查看定义

在wrk中也可以看到定义的地方. 所以我们只需要在我们的函数中引用这个全局变量即可.
其中这个结构第一项是表的首地址 第二项是表的个数. *表 + n = 第某个函数的地址
也就是 base[10]就是第十项的地址.
KeServiceDescriptorTable

对应PCHunter查看.

所以我们想要HOOK就很简单了.
- 导入全局变量. 则获得SSDT表的地址
- 获取你想HOOK函数的位置
- 进行HOOK
- HOOK之前关闭一下CR0得写保护
代码如下:
#include "Driver.h" NTKERNELAPI UCHAR* PsGetProcessImageFileName(IN PEPROCESS Process); void UnHook(); void DriverUnLoad(PDRIVER_OBJECT pDriverObj) { UnHook(); KdPrint(("驱动卸载成功")); } typedef struct _KSERVICE_TABLE_DESCRIPTOR { PULONG_PTR Base; PULONG Count; ULONG Limit; PUCHAR Number; } KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR; __declspec(dllimport) KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable; //导入全局变量 // sizeof(base) + 370 * 4 = NtTerMinateProcess //extern KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable typedef NTSTATUS(*PfnZwTerminateProcess)( IN HANDLE ProcessHandle OPTIONAL, IN NTSTATUS ExitStatus); PfnZwTerminateProcess OldZwTerminateProcess; NTSTATUS Hook_ZwTerminateProcess( IN HANDLE ProcessHandle OPTIONAL, IN NTSTATUS ExitStatus) { NTSTATUS rc; PEPROCESS pRocess; UCHAR *pszProcessName; //UCHAR *pszProcessName = PsGetProcessImageFileName(); rc = ObReferenceObjectByHandle(ProcessHandle, GENERIC_ALL, *PsProcessType, KernelMode, &pRocess, NULL); if (!NT_SUCCESS(rc)) { return OldZwTerminateProcess(ProcessHandle, ExitStatus); } pszProcessName = PsGetProcessImageFileName(pRocess); if (strstr(pszProcessName, "calc")) { return STATUS_ACCESS_DENIED; ObDereferenceObject(pRocess); } ObDereferenceObject(pRocess); rc = OldZwTerminateProcess(ProcessHandle, ExitStatus); return rc; } //关闭写保护 1111 1111 1111 1110 1111 1111 1111 1111 VOID _CloseWriteProtected() { __asm { push eax mov eax, cr0 and eax, 0xFFFEFFFF mov cr0,eax pop eax } return; } VOID _OpenTheWriteProtected() { __asm { push eax mov eax, cr0 or eax, NOT 0xFFFEFFFF mov cr0, eax pop eax } return; } void HOOK() { //370是ntTerminateProcess 也可以写成 base + sizeof(type) *n = *(KeServiceDescriptorTable.Base) + 4 * 370 = NtTinminateProcess的地址 /* OldZwTerminateProcess = (PfnZwTerminateProcess)(*(KeServiceDescriptorTable.Base) + 370 * 4); */ OldZwTerminateProcess = (PfnZwTerminateProcess)KeServiceDescriptorTable.Base[370]; _CloseWriteProtected(); // KeServiceDescriptorTable.Base[370] = (int)Hook_ZwTerminateProcess; _OpenTheWriteProtected(); } void UnHook() { _CloseWriteProtected(); // KeServiceDescriptorTable.Base[370] = (int)OldZwTerminateProcess; _OpenTheWriteProtected(); } NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath) { pDriverObj->DriverUnload = DriverUnLoad; HOOK(); return STATUS_SUCCESS; } 
总的来说如果按照服务号来HOOK是很简单的.如果没有服务号你怎么HOOK?
其实在32位下.你调用的函数.里面就有调用号.内核也跟应用层的调用号是息息相关的.我们可以取得函数调用号进行HOOK也可以.
如:
未测试. KeServiceDescriptorTable.Base[*(PULONG)((PUCHAR)_FUNCTION +1)];
其中_FUNCTION用名字修改即可.