65.9K
CodeProject 正在变化。 阅读更多。
Home

如何获取 KeServiceDescriptorTableShadow 的地址

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.67/5 (4投票s)

2008年5月26日

CPOL
viewsIcon

34236

downloadIcon

216

解释如何获取 KeServiceDescriptorTableShadow 的地址

引言

本文档展示了如何获取内核变量 KeServiceDescriptorTableShadow 的地址。该变量用于向内核添加新的系统服务,或挂钩现有的系统服务。不幸的是,它没有被 ntoskrnl.exe 导出,因此我们必须手动获取其地址。

背景

通过使用 ntoskrnl.exe 导出的变量 KeServiceDescriptorTable,我们可以获取 KeServiceDescriptorTableShadow 变量的地址。KeServiceDescriptorTableShadowKeServiceDescriptorTable 变量的扩展。请参阅以下部分。

Using the Code

这两个变量的类型都是 SERVICE_DESCRIPTOR_TABLE 结构体。该结构体定义如下

typedef struct _SERVICE_DESCRIPTOR_TABLE
{
 PULONG  ServiceTable;  	// array of entry-points
 PULONG  puCounterTable;  	// array of counters
 ULONG  uTableSize;   	// number of table entries
 PUCHAR  pbArgumentTable; 	// array of byte counts
} SERVICE_DESCRIPTOR_TABLE, *PSERVICE_DESCRIPTOR_TABLE;

KeServiceDescriptorTableShadow 的第一部分与 KeServiceDescriptorTable 相同。因此,我们可以通过比较 KeServiceDescriptorTable 周围的内存来获取 KeServiceDescriptorTableShadow 的地址。在不同版本的 Windows 中,此地址是不同的。

此函数在不同版本的 Windows 中检索其地址。

PSERVICE_DESCRIPTOR_TABLE QuerySDTShadow()
{
 ULONG Index;
 PUCHAR SDTShadow;
 UONG MajorVersion, MinorVersion, BuildNumber;
 UNICODE_STRING &CSDVersion;
 PsGetVersion(&MajorVersion, &MinorVersion, &BuildNumber, &CSDVersion);
 __try
 {
  if(MajorVersion == 5 && MinorVersion == 1) // Windows XP
   SDTShadow = (PUCHAR)((ULONG)&KeServiceDescriptorTable - 0x40);
  else // Windows 2000, or Windows Vista
   SDTShadow = (PUCHAR)((ULONG)&KeServiceDescriptorTable + 0x40);
  for(Index = 0; Index < 0x1000; Index ++, SDTShadow ++)
  {
   KeServiceDescriptorTableShadow = (PSERVICE_DESCRIPTOR_TABLE)SDTShadow;
   if(KeServiceDescriptorTableShadow == &KeServiceDescriptorTable)
    continue;
   if(memcmp(KeServiceDescriptorTableShadow, &KeServiceDescriptorTable, 0x10) == 0 
    && ((UCHAR)KeServiceDescriptorTableShadow->ServiceTable & 3) == 0)
   {
    return (PSERVICE_DESCRIPTOR_TABLE)SDTShadow;
   }
  }
  return NULL;
 }
 __except(1)
 {
  return NULL;
 }
} 

这段代码已经在各种环境下进行了测试,但您必须谨慎使用它。

历史

  • 2008 年 5 月 26 日:初始发布
© . All rights reserved.