Windows X86下系统中一共有2个系统服务描述符表,保存在如下的结构体中:
typedef struct _KSYSTEM_SERVICE_TABLE
{
PULONG ServiceTableBase; //服务表的基址
PULONG ServiceCounterTableBase;
ULONG NumberService; //服务表函数的数量
ULONG ParamTableBase; //服务表函数参数表
}KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;
而每个系统描述符表中有四个服务表:
typedef struct _KSERVICE_DESCRIPTOR_TABLE
{
KSYSTEM_SERVICE_TABLE ntoskrnl; //ntoskrnl.exe的服务表,在KeServiceDesriptorTable和KeServiceDescriptorTableShadow均有值
KSYSTEM_SERVICE_TABLE win32k; //win32k.sys的服务表,仅在KeServiceDescriptorTableShadow中有值
KSYSTEM_SERVICE_TABLE notUsed1;
KSYSTEM_SERVICE_TABLE notUsed2;
}KSERVICE_DESCRIPTOR_TABLE, *PKSERVICE_DESCRIPTOR_TABLE;
内核中有两个系统服务描述符表,一个是KeServiceDescriptorTable(由ntoskrnl.exe导出),一个是KeServieDescriptorTableShadow(没有导出)。两者的区别是,KeServiceDescriptorTable仅有ntoskrnel一项有值,而KeServieDescriptorTableShadow包含了ntoskrnel以及win32k。一般的Native API的服务地址由KeServiceDescriptorTable分派,gdi.dll/user.dll的内核API调用服务地址由KeServieDescriptorTableShadow分派。
而win32k.sys只有在GUI进程中才加载,非GUI进程中无法查看,所以我们在hook的时候可以使用KeStackAttachProcess来挂靠到一个GUI进程。
下面我来说一下具体的步骤吧,这次hook的函数是GetDC,在Win32k模块的服