初识SSDT、读取内核API地址

SSDT 表的初步学习

1 理论知识

大概思路和理论知识

首先明白应用层到 内核层 会通过一张SSDT 表、、我们要根据SSDT结构和索引号来获取函数的当前地址

如果检测一下这个函数有木有被HOOK我们要在获取这个函数的起源地址 对比一下即可知道、、

 

 

 

1 读取SSDT表函数当前地址

了解SSDT结构

系统服务描述符表 在ntoskrnl.exe导出KeServiceDescriptorTable这个表

typedef struct _ServiceDescriptorTable {

PVOID ServiceTableBase; //System Service Dispatch Table 的基地址

PVOID ServiceCounterTable;

//包含着SSDT 中每个服务被调用次数的计数器。这个计数器一般由sysenter 更新。

unsigned int NumberOfServices;//由ServiceTableBase 描述的服务的数目。

PVOID ParamTableBase; //包含每个系统服务参数字节数表的基地址-系统服务参数表

}*PServiceDescriptorTable;

//由SSDT索引号获取当前函数地址

extern PServiceDescriptorTable KeServiceDescriptorTable;

用KeServiceDescriptorTable这张表 可以获取SSDT的基地址 再使用索引号 即可得到函数的地址

这里是NTOpenProcess 索引号是7A(122) ,所以

NTOpenProcess 的地址是保存在KeServiceDescriptorTable+ 7A*4的位置

使用汇编得到这个地址 这么写

首先加一句

extern long KeServiceDescriptorTable;// 这里使用long不太准确

ULONGSSDT_NtOpenProcess_Cur_Addr; //定义一个全局变量 打印出这个值

__asm

{

int 3//为了调试方便 下一个int 3断点

push ebx

push eax

mov ebx,KeServiceDescriptorTable//直接使用这个表

mov ebx,[ebx]

mov eax,0x7A

shl eax,2 // imul eax,eax,4//左移两位

add ebx,eax// 地址[KeServiceDescriptorTable]+0x7A*4

mov ebx,[ebx]//取上边地址的内容

mov SSDT_NtOpenProcess_Cur_Addr,ebx//赋予全局变量

pop eax

pop ebx

} 使用指针这样写、

先定义一个

typedef struct _ServiceDescriptorTable {

PVOID ServiceTableBase; //System Service Dispatch Table 的基地址

PVOID ServiceCounterTable;

//包含着SSDT 中每个服务被调用次数的计数器。这个计数器一般由sysenter 更新。

unsigned int NumberOfServices;//由ServiceTableBase 描述的服务的数目。

PVOID ParamTableBase; //包含每个系统服务参数字节数表的基地址-系统服务参数表

}*PServiceDescriptorTable;

然后

extern PServiceDescriptorTable KeServiceDescriptorTable; //这个是准确的、

LONG *SSDT_Adr;

LONG SSDT_NtOpenProcess_Cur_Addr; //最终结果

LONG t_addr;//基地址

t_addr=(LONG)KeServiceDescriptorTable->ServiceTableBase;

SSDT_Adr=(PLONG)(t_addr+0x7A*4);//得到存放NTOpenProcess的地址的地址、、

SSDT_NtOpenProcess_Cur_Addr = *SSDT_Adr;//得到NTOpenProcess的地址

KdPrint(("SSDT_NtOpenProcess_Cur_Addr =%x\n",SSDT_NtOpenProcess_Cur_Addr));

 

可以双机调试一下、使用Kernel Detective 软件对照分析、、

 

2 读取SSDT函数表的真正地址、、即原始地址、

上边获取的是SSDT当前地址 不一定为函数的原始地址(该函数若有HOOK行为、)

这个有固定的函数、、

PVOID MmGetSystemRoutineAddress

(

__inPUNICODE_STRING SystemRoutineName

//参数是 保存要得到的函数名字的 缓冲区、、

);

 

实现

ULONG GetSSDT_Old_ADDR()

UNICODE_STRING Old_NtOpenProcess;

ULONG Old_Addr;

RtlInitUnicodeString(&Old_NtOpenProcess,L"NtOpenProcess");//初始化字符串

Old_Addr=(ULONG)MmGetSystemRoutineAddress(&Old_NtOpenProcess)NtOpenProcess地址

KdPrint(("取得原函数NtOpenProcess的值为%x",Old_Addr));

return Old_Addr;

 

posted @ 2014-01-21 13:37  晨曦语晴  阅读(694)  评论(0编辑  收藏  举报