注    册
密 码 忘记密码
保存密码         取消
注    册
密 码 忘记密码
保存密码         取消

我的日志

KeServiceDescriptorTableShadow的获取

分类:安全文摘
2008.2.19 17:35 作者:朋友般的恋人 | 评论:0 | 阅读:0

如果没有KeServiceDescriptorTable,那么很多事情就会变得简单许多,我们只需要定义一个全局变量:

extern PSERVICE_Descriptor_TABLE    KeServiceDescriptorTable;

这样就能够引用KeServiceDescriptorTable了,就能够访问ntoskrnel下面所导出的所有函数。但是因为还有一些函数是通过win32k表导出的,这些函数都是win32k.sys的服务函数,所以要访问类似这些函数就得从shadow标结构中读取win32k表的EntryPoint。

因为KeServiceDescriptorTableShadow并不公开,所以需要从其他途径获取该结构表。现在用的比较多的一种方法是通过KeAddSystemServiceTable,遍历该函数的起始地址,查找有效内存地址(MmIsAddressValid)。因为shadow是涵盖了KeServiceDescriptorTable表的结构,在查找的过程中,就是采用和KeServiceDescriptorTable表进行匹配的方法,其中前16位需要匹配,而且两个表的起始地址不能相同(否则为同一张表),就是按照这种方法,查找获得shadow表。其实现函数如下:

 

#include <ntddk.h>

 

//KeServiceDescriptorTable的表结构

typedef struct _SERVICE_Descriptor_TABLE
{
  PVOID   ServiceTableBase;
  PULONG  ServiceCounterTableBase;
  ULONG   NumberOfService;
  ULONG   ParamTableBase;
}SERVICE_Descriptor_TABLE,*PSERVICE_Descriptor_TABLE;

 

//下面这句话非常重要,用来申明KeServiceDescriptorTable,方才能在以后的程序中使用

extern PSERVICE_Descriptor_TABLE    KeServiceDescriptorTable;

 

//下面同样是用来申明的,KeAddSystemService,这样才能使用,以此得到函数的入口地址

NTSYSAPI BOOLEAN NTAPI KeAddSystemServiceTable (
          PVOID* ServiceTable,
          ULONG Reserved,
          ULONG Limit,
          BYTE* Arguments,
          ULONG NumOfDesc);

 

//下面就是具体的实现函数

DWORD  GetAddrssofShadowTable()
{
 int i;
 unsigned char *p;
 unsigned int dwordatbyte;

 p=(unsigned char *)KeAddSystemServiceTable;   //由KeAddSystemServiceTable起始地址遍历

 for (i=0; i<4096; i , p ) {

 __try {
 dwordatbyte = *(unsigned int *)p;
 }
 __except (EXCEPTION_EXECUTE_HANDLER)
 {
  return 0;
 }

 if (MmIsAddressValid((PVOID)dwordatbyte))       //检测地址是否有效,能否读写
 {

  if ((PVOID)dwordatbyte == *(PVOID *)&KeServiceDescriptorTable)    //如果起始地址相同,则为同一张表,

                                                                                                             //继续循环
  {
   continue;
  }
   
  if (memcmp((PVOID)dwordatbyte, *(PVOID *)&KeServiceDescriptorTable, 16) == 0)   

  //比较前16位,相同则为shadow表
  {

   DbgPrint("Shadow @%x\n", dwordatbyte);

   return dwordatbyte;
  }
 }
}

return 0;
}

 

分析具体实例如下:

分析工具:windbg

lkd>dd KeServiceDescriptorTable

8055c6e0  80504940 00000000 0000011c 80504db4
8055c6f0  00000000 00000000 00000000 00000000
8055c700  00000000 00000000 00000000 00000000
8055c710  00000000 00000000 00000000 00000000

可以看到只有ntskrnel表,下面三项都为0,采用上面方法获取到shadow地址为0x8055C6A0,察看其对应内容如下:

lkd> dd 8055c6a0

8055c6a0  80504940 00000000 0000011c 80504db4
8055c6b0  bf999280 00000000 0000029b bf999f90
8055c6c0  00000000 00000000 00000000 00000000
8055c6d0  00000000 00000000 00000000 00000000

看到前16位是相同的,符合上面的规则。

 

最后就是自己的一些处理,略。

全篇完。

你可以通过这个链接引用该篇文章:http://caojq9902.bokee.com/viewdiary.24498152.html

            PE文件获取导出函... 上一篇 | 下一篇 内存读写

我的搜索

文章评论

添加评论

马上抢占沙发,进行评论
昵  称:  主  页: (选填)
验证码: