此方法只是遍历SSDT,判断是否在ntkrnlpa.exe模块里面。也就是寻找SSDT导出NT函数的原始地址。此方法不适合检测 inline Hook。
typedef struct _SYSTEM_MODULE_INFORMATION {
ULONG Reserved[2];
PVOID Base;
ULONG Size;
ULONG Flags;
USHORT Index;
USHORT Unknown;
USHORT LoadCount;
USHORT ModuleNameOffset;
CHAR ImageName[256];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
typedef struct _tagSysModuleList {
ULONG ulCount;
SYSTEM_MODULE_INFORMATION smi[1];
} SYSMODULELIST, *PSYSMODULELIST;
以上是SSDT模块信息的结构和链表。
NTSTATUS MyEnumSSDT()
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PULONG SSDT_Function_Address; //SSDT表函数地址
ULONG SSDT_Function_Number; //SSDT表函数个数
PSYSMODULELIST pSysModuleList;
SYSTEM_MODULE_INFORMATION SystemModuleInfo;//模块结构
PVOID pBuffer; //SSDT总大小缓冲区
ULONG uBufferSize;
ULONG i = 0;
ULONG j = 0;
ULONG uModuleBase;
ULONG uModuleMax;
CHAR strMdoulePath[255];
SSDT_Function_Address = (PULONG)KeServiceDescriptorTable->ServiceTableBase;
SSDT_Function_Number = KeServiceDescriptorTable->NumberOfService;
KdPrint(("SSDT_Function_Address:%x,SSDT_Function_Number:%d\n",SSDT_Function_Address,SSDT_Function_Number));
ZwQuerySystemInformation(SystemModuleInformation,NULL,0,&uBufferSize);//枚举SSDT表Path大小
if (!uBufferSize)
{
KdPrint(("ZwQuerySystemInformation1 error!\n"));
return status;
}
pBuffer = ExAllocatePoolWithTag(NonPagedPool,uBufferSize,MEM_TAG);//申请内存存放
if (!pBuffer)
{
KdPrint(("ExAllocatePoolWithTag error!\n"));
return status;
}
status = ZwQuerySystemInformation(SystemModuleInformation,pBuffer,uBufferSize,NULL);//第二次遍历,填充pBuffer缓冲区
if (!NT_SUCCESS(status))
{
KdPrint(("ZwQuerySystemInformation2 error!\n"));
return status;
}
pSysModuleList = (PSYSMODULELIST)pBuffer;//将所有SSDT函数缓冲区换成链表来访问
for (j = 0; j < pSysModuleList->ulCount; j++) //遍历获取ntkrnlpa.exe模块所在地址和大小
{
SystemModuleInfo = pSysModuleList->smi[j];
strcpy(strMdoulePath,(SystemModuleInfo.ImageName + SystemModuleInfo.ModuleNameOffset));
if (strncmp("ntkrnlpa.exe",strMdoulePath,12) == 0)
{
uModuleBase = (ULONG)SystemModuleInfo.Base;
uModuleMax = uModuleBase + SystemModuleInfo.Size;
}
}
//遍历SSDT表,对比地址检测是否被hook
for (i = 0; i < SSDT_Function_Number; i++)
{
if (uModuleBase < (ULONG)SSDT_Function_Address && (ULONG)SSDT_Function_Address < uModuleMax)
{
KdPrint(("UnHook:%03d Address:%X Path:%s\n",i,*(SSDT_Function_Address + i),strMdoulePath));
}
else
{
KdPrint(("Hook:%03d Address:%X Path:%s\n",i,*(SSDT_Function_Address + i),strMdoulePath));
}
}
if (pBuffer)
{
ExFreePool(pBuffer);
pBuffer = NULL;
}
return status;
}
总的来说还是比较简单的,还差了一个获取SSDT导出函数名字。下一篇补全。