关于windows内核SSDT HOOK的一点思考
----------------TTL
关于windows内核,一直是众多OS黑客所喜欢又不敢触及的地方,确实,内核的知识实在是隐晦,又生涩难懂。我觉得OS hacker和WEB hacker确实存在差别。一般来讲,OS hacker的难度要很大。因为二进制的漏洞相比于web漏洞难度大,主要是无源。web有源码,挖掘漏洞自然相对就很简单(但也需要扎实的基本功和良好的知识基础)。
那么关于什么是SSDT呢?我有一点自己的思考。
首先百度百科也说了SSDT的含义。SSDT就是windows内核的一个十分庞大的地址索引表,在这个地址索引表上,有内核服务的地址。这些地址组成了一个线性的地址序列,也就是数组,每个数组元素就是一个指针。这个指针就是内核中的系统服务的地址。
在不同的操作系统上,SSDT也是不一样的。所以SSDT HOOK 的代码要做到兼容难度也是不小。其实用户层的程序在执行的过程中,首先调用win32平台上的API,然后进入内核,在SSDT的庞大地址索引表中寻找对应的内核服务的地址。这样就将上层的API和内核的服务对应了起来。
接下来,看一下代码,代码是我学习梦老大的。在这里,感谢梦老大。
#pragma pack(1)
typedef struct ServiceDescriptorEntry {
unsigned int *ServiceTableBase;
unsigned int *ServiceCounterTableBase; //仅适用于checked build版本
unsigned int NumberOfServices;
unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
#pragma pack()
__declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable;
首先我声明一个ServiceDescriptorTableEntry_t结构体。这个结构体来管理SSDT,也就是SSDT都在这个表中指向。
void PageProtectOn()
{
__asm{//恢复内存保护
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
}
void PageProtectOff()
{
__asm{//去掉内存保护
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
}
首先谢了两个内存保护开启和关闭的函数,论坛上很多大神都采用这种风格,我也就延续大大们的风格。
首先,在Windbg中,查看了eProcess这个数据结构。后面的代码中我会用到。
可看到,在我的系统中,偏移0x174是ImageFileName。
然后利用XueTr查看了SSDT。
从表中可以看出,NtOpenProcess被腾讯的程序在内核被HOOK了,不仅仅是腾讯,像360,百度的一些安全软件,在底层也是疯狂的HOOK。这也是病毒对抗越来越趋向于底层化的原因。从图看到,NtOpenProcess在SSDT中是122号。
主要代码:
NTSTATUS NewNtOpenProcess (
__out PHANDLE ProcessHandle,
__in ACCESS_MASK DesiredAccess,
__in POBJECT_ATTRIBUTES ObjectAttributes,
__in_opt PCLIENT_ID ClientId
)
{
KdPrint(("NewNtOpenProcess"));
KdPrint(("%s",(char*)PsGetCurrentProcess()+0x174));
return ((NTOPENPROCESS)g_ntopenprocess)(ProcessHandle,DesiredAccess,ObjectAttributes,ClientId);
}
NTSTATUS HookNtOpenProcess()
{
NTSTATUS status;
status = STATUS_SUCCESS;
PageProtectOff();
g_ntopenprocess = KeServiceDescriptorTable.ServiceTableBase[122];
KeServiceDescriptorTable.ServiceTableBase[122] = (unsigned int)NewNtOpenProcess;
PageProtectOn();
return status;
}
VOID UnHookNtOpenProcess()
{
PageProtectOff();
KeServiceDescriptorTable.ServiceTableBase[122] = (unsigned int)g_ntopenprocess;
PageProtectOn();
}
VOID MyUnload(PDRIVER_OBJECT pDriverObject)
{
UnHookNtOpenProcess();
}
NTSTATUS DriverEntry(PDRIVER_OBJECTpDriverObject,PUNICODE_STRING Reg_Path)
{
HookNtOpenProcess();
pDriverObject->DriverUnload = MyUnload;
return STATUS_SUCCESS;
}
在新的NtOpenProcess我们什么也不做,只打印一条消息,和一条被哪个程序调用的名称。
效果如图:
从图中看到,NtOpenProcess已经被我们的sys所HOOK住,并不是之前的腾讯的程序了。
HOOK成功