欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

HOOK技术:SSDT HOOK(x86)

程序员文章站 2022-07-13 16:11:41
...

在进行SSDT Hook之前我们要先了解SSDT的概念和作用。
SSDT:
System Services Descriptor Table(系统服务描述符表),在内核中是KeServiceDescriptorTable。这个表就是一个把ring3的Win32 API和ring0的内核API联系起来。SSDT并不仅仅只包含一个庞大的地址索引表,它还包含着一些其它有用的信息,诸如地址索引的基地址、服务函数个数等。
(Ring3层的函数API在进入内核层后,而每个调用号对应一个内核函数,为此Windows设计了一张表通过调用号作为序号,就能找到函数的地址。Windows内核把这张函数地址表称为 : 系统服务描述表(System Service Descriptor Table ) 简称SSDT)

HOOK技术:SSDT HOOK(x86)
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;
	};
相关标签: HOOK