KeServiceDescriptorTableShadow的获取
2010-07-01 17:12
267 查看
如果没有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位是相同的,符合上面的规则。
最后就是自己的一些处理,略。
全篇完。
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位是相同的,符合上面的规则。
最后就是自己的一些处理,略。
全篇完。
相关文章推荐
- KeServiceDescriptorTable 结构及获取
- 关于windbg不能正确显示KeServiceDescriptorTableShadow的问题
- 在XP内核模式下如何获得KeServiceDescriptorTableShadow的地址
- [转载]恢复2k/xp win32k.sys的KeServiceDescriptorTableShadow
- Obtaining KeServiceDescriptorTableShadow address
- windebug查看KeServiceDescriptorTable
- 编译器报错: error LNK2001: unresolved external symbol "struct _ServiceDescriptorTable * KeServiceDescript
- #define SYSTEMSERVICE(_func) KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_func+1) 这
- #define SYSTEMSERVICE(_func) KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_func+1) 这
- 编译器报错: error LNK2001: unresolved external symbol "struct _ServiceDescriptorTable * KeServiceDescript
- X64系统下的KeServiceDescriptionTable
- 从数据库获取的表格里的内容用SortableTable进行排序
- 关于VSS(Volume Shadow Copy Service)一
- Lua中获取table长度问题探讨
- tableView 获取网络图片,并且设置为圆角(优化,fps)
- Jquery中获取table中某列值的具体思路
- jQuery实现获取table表格第一列值的方法
- Qt 获取tableview的选中行数据
- 使用BroadcasterRecevier拦截系统短信息_使用service后台获取位置信息
- ORA-12514, TNS:listener does not currently know of service requested in connect descriptor案例2