SSDT HOOK中的几个宏

来源:互联网 发布:python findall函数 编辑:程序博客网 时间:2024/06/06 02:14

SSDT HOOK中的几个宏

 

#define GetSystemFunc(FuncName) KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PUCHAR)FuncName+1)]

#define GetIndex(_Function) *(PULONG)((PUCHAR)_Function+1)

#define HookOn(_Old, _New)  /
       (PVOID) InterlockedExchange( (PLONG) &MappedSCT[GetIndex(_Old)], (LONG) _New)

#define UnHook(_Old, _New)  /
       InterlockedExchange( (PLONG) &MappedSCT[GetIndex(_Old)], (LONG) _New)

     由于最近在看SSDT HOOK,对其中的几个宏定义不是很理解,主要是网上找了很多资料都只有对这几个宏的定义和使用,从来不说为什么这样定义,所以,一不爽就自己动手了。以上就是常用到的四个宏,主要是前两个比较重要,研究清楚了后面就没啥大问题了。

先来看个结构吧
typedef struct ServiceDescriptorEntry
{
        unsigned int *ServiceTableBase;
        unsigned int *ServiceCounterTableBase; //Used only in checked build
        unsigned int NumberOfServices;
        unsigned char *ParamTableBase;
} SSDTEntry;
用来获得SSDT表的一个很重要的结构,这个结构网上很多资料讲的很清楚。
    其中*ServiceTableBase是指向SSDT表表头的指针,用它可以获得每个SSDT表的表项,NumberOfServices表示SSDT表里有多少个表项,也就是SSDT表里有多少个系统调用。
一下以API:TerminateProcess()为例
    从ring3调用api首先会到ntdll.dll里去掉用一个相应的ntTerminateProcess()或者ZwTerminateProcess(),两者在ntdll.dll里是相同的,可以用IDA查看。调用ntTerminateProcess()以后,该函数内部会向ring0发送一个系统调用编号,这里发送的是101h,然后sysenter进入ring0,这里的细节没去研究过。
    然后下面就到了ring0,ZwTerminateProcess()在ntoskrnl.exe里有导出,注意这个函数和ntdll.dll里的不一样。
用IDA查看ZwTerminateProcess()如下:
text:00406AD0 ; NTSTATUS __stdcall ZwTerminateProcess(HANDLE ProcessHandle, NTSTATUS ExitStatus)
.text:00406AD0                 public ZwTerminateProcess
.text:00406AD0 ZwTerminateProcess proc near            ; CODE XREF: sub_42BC9F+1ABF8p
.text:00406AD0                                         ; sub_468278+E2p
.text:00406AD0
.text:00406AD0 ProcessHandle   = dword ptr  4
.text:00406AD0 ExitStatus      = dword ptr  8
.text:00406AD0
.text:00406AD0                 mov     eax, 101h     
.text:00406AD5                 lea     edx, [esp+ProcessHandle]
.text:00406AD9                 pushf
.text:00406ADA                 push    8
.text:00406ADC                 call    sub_407631
.text:00406AE1                 retn    8
.text:00406AE1 ZwTerminateProcess endp
   其实大家可以看到这个函数没做啥,关键在sub_407631里面做了很多东西,详细可以自己进去看看。
为什么要讲这个呢?因为本文一开始列出的4个宏中的第一个:#define GetSystemFunc(FuncName) KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PUCHAR)FuncName+1)]
FuncName为函数名,一般大家用都是用这个宏来获得相应函数在SSDT表里的地址。
这里传入的是ZwTerminateProcess()在ntoskrnl.exe里的地址,为什么能反过来得到SSDT表里的地址呢?关键看第一行代码:.text:00406AD0                 mov     eax, 101h
其中含有101h,这个系统调用号在SSDT表里很重要,有了他就可以结合ServiceTableBase找到SSDT表里的地址了。所以如何得到101h呢?来看看mov eax,101h的机器码吧。.text:00406AD0 B8 01 01 00 00,函数ZwTerminateProcess()正好指向00406AD0这个存储单元,所以其实只要把第一个byte去了,就可以取到101h了。没错,所以FetSystemFunc(FuncName)宏就是这么做的(*(PULONG)((PUCHAR)FuncName+1)这一句就得到了101h)。接下来就是去ServiceTableBase表里查101h的地址,这样得到这个地址以后想怎么改就怎么改,想怎么hook就怎么hook了。
其实这个宏是最关键的,个人认为,这个宏分析清楚了其他三个宏就迎刃而解了。
OK继续学习吧,学海无涯,还得多多钻研。

原创粉丝点击