HOOK技术:SSDT HOOK(x86)
在进行SSDT Hook之前我们要先了解SSDT的概念和作用。
SSDT:
System Services Descriptor Table(系统服务描述符表),在内核中是KeServiceDescriptorTable。这个表就是一个把ring3的Win32 API和ring0的内核API联系起来。SSDT并不仅仅只包含一个庞大的地址索引表,它还包含着一些其它有用的信息,诸如地址索引的基地址、服务函数个数等。
(Ring3层的函数API在进入内核层后,而每个调用号对应一个内核函数,为此Windows设计了一张表通过调用号作为序号,就能找到函数的地址。Windows内核把这张函数地址表称为 : 系统服务描述表(System Service Descriptor Table ) 简称SSDT)
SSDT表结构如下:
typedef struct ServiceDescriptorEntry {
unsigned int *ServiceTableBase;
unsigned int *ServiceCounterTableBase;
unsigned int NumberOfServices;
unsigned char *ParamTableBase;
} ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
0x00 实现原理
上面我们知道了SSDT表的作用,所以说要进行SSDT HOOK,只要根据索引找到函数实现的真实地址,然后将这个函数地址,更换成我们自己函数的地址,就可以完成HOOK。例如我们知道了ZwOpenProcess的索引号为0xbe,就可以通过0xbe找到函数地址,然后进行修改hook。
kd> u ZwOpenProcess
nt!ZwOpenProcess:
84857cd8 b8be000000 mov eax,0BEh //索引号
84857cdd 8d542404 lea edx,[esp+4]
84857ce1 9c pushfd
84857ce2 6a08 push 8
84857ce4 e8d5190000 call nt!KiSystemService (848596be)
84857ce9 c21000 ret 10h
nt!ZwOpenProcessToken:
84857cec b8bf000000 mov eax,0BFh
84857cf1 8d542404 lea edx,[esp+4]
用一个西游记里的小故事来说明SSDT HOOK的功能:
“当年唐僧的父亲是朝廷钦派的一名官员,而再唐僧父亲赶去赴任的时候,一个强盗把唐僧的父亲杀了,并且取走了官员证明,自己去当官享受荣华富贵了。”
在这个故事中呢,唐僧的父亲就是本来的函数,官员证明就是SSDT表中函数的地址,强盗呢就是我们自己写的函数。
0x01 实现流程
1.根据索引找到函数地址
2.保存原函数地址(因为再卸载驱动的时候,我们要再恢复回去 )
3.替换地址为自己的函数地址
还有最重要的是在HOOK之前不能忘记修改内存保护。
首先我们使用找到ZwOpenProcess函数的索引0BEh。
#define SSDT_INDEX(ZwFunctionAddress)*(PULONG)((PUCHAR)ZwFunctionAddress+1)//+1是为了跳过b8
kd> u ZwOpenProcess
nt!ZwOpenProcess:
84857cd8 b8be000000 mov eax,0BEh
然后再SSDT表中找到相应的函数地址
&__ServiceTableBase[SSDT_INDEX(ZwFunctionAddress)
然后将地址替换成自己实现的函数地址:
#define SSDT_HOOK(ZwFunctionAddress,FakeFunctionAddress,OriginalFunctionAddress)\
OriginalFunctionAddress=(PVOID)InterlockedExchange((PLONG)&__ServiceTableBase[SSDT_INDEX(ZwFunctionAddress)],(LONG)FakeFunctionAddress)
修改内存写保护属性方法如下:
_asm
{
cli; //禁止任何中断发生
push eax;
mov eax, cr0;
mov Attribute, eax;
and eax, 0xFFFEFFFF; // CR0 16 BIT = 0
mov cr0, eax;
pop eax;
};