r0下的进程保护


r0下的进程保护

文章插图
 
前言进程保护是众多AV或者病毒都要所具备的基础功能,本文就0环下通过SSDT来对进程进行保护进行探究,SSDT也不是什么新技术,但作为学习,老的技术我们同样需要掌握 。
什么是SSDTSSDT 的全称是System Services Descriptor Table,系统服务描述符表 。
首先要明确的是他是一张表,通过windbg查看这张表 。
ddKeServiceDescriptorTable
r0下的进程保护

文章插图
 
这个表就是一个把 Ring3 的 Win32 API 和 Ring0 的内核 API 联系起来 。
当我们在r 3调用一个API时,实际上调用的是一个接口,这里拿ReadProcessMemory举例 。
ReadProcessMemory函数在kernel32.dll中导出,通过断点可以找到对应的反汇编代码 。在汇编代码中,可以看到ReadProcessMemory调用了ntdll.dll中的ZwReadVirtualMemory函数 。
r0下的进程保护

文章插图
 
在ZwReadVirtualMemory函数开始的地方下断点 。
bp ZwReadVirtualMemory实际上功能代码也没有在ZwReadVirtualMemory函数中实现,只是拿着一个索引号并跳转到一个地址 。
r0下的进程保护

文章插图
 
这个索引号实际上就是SSDT表中的索引号,回到windbg,我们现在拿到索引号0xBA去SSDT表中找 。
kd> ddKeServiceDescriptorTable80553fa080502b8c 00000000 0000011c 8050300080553fb000000000 00000000 00000000 0000000080553fc000000000 00000000 00000000 0000000080553fd000000000 00000000 00000000 0000000080553fe000002710 bf80c0b6 00000000 0000000080553ff0f8b67a80 f82e7b60 821bfa90 806e2f408055400000000000 00000000 22bc349b 0000000180554010afa8a15b 01d7eb4f 00000000 00000000kd> dd 80502b8c + 0xba*480502e74805aa712 805c99e0 8060ea76 8060c43c80502e848056f0d2 8063ab56 8061aca8 8061d33280502e948059b804 8059c7cc 8059c1d4 8059baee80502ea4805bf456 80598d62 8059908e 805bf26480502eb4806064b6 8051ee82 8061cc3e 805cbd4080502ec4805cbc22 8061cd3a 8061ce20 8061cf4880502ed48059a07c 8060db50 8060db50 805c892a80502ee48063d80e 8060be28 80607fb8 8060882akd> u 805aa712
r0下的进程保护

文章插图
 
可以看到在0环调用的是NtReadVirtualMemory,这实际上才是真正实现功能的地方 。而SSDT将r 3和r 0联系到一起 。
r0下的进程保护

文章插图
 
SSDT结构在 NT 4.0 以上的 windows 操作系统中,默认就存在两个系统服务描述表,这两个调度表对应了两类不同的系统服务,
这两个调度表为:KeServiceDescriptorTable 和 KeServiceDescriptorTableShadow,
其中 KeServiceDescriptorTable 主要是处理来自 Ring3 层 Kernel32.dll 中的系统调用,
而 KeServiceDescriptorTableShadow 则主要处理来自 User32.dll 和 GDI32.dll 中的系统调用,
并且 KeServiceDescriptorTable 在 ntoskrnl.exe(Windows 操作系统内核文件,包括内核和执行体层)是导出的,
而 KeServiceDescriptorTableShadow 则是没有被 Windows 操作系统所导出,
而关于 SSDT 的全部内容则都是通过 KeServiceDescriptorTable 来完成的 。
r0下的进程保护

文章插图
 
SSDT表的结构通过结构体表示为如下:
typedef struct _KSERVICE_TABLE_DESCRIPTOR{KSYSTEM_SERVICE_TABLEntoskrnl;// ntoskrnl.exe 的服务函数KSYSTEM_SERVICE_TABLEwin32k;// win32k.sys 的服务函数(GDI32.dll/User32.dll 的内核支持)KSYSTEM_SERVICE_TABLEnotUsed1;KSYSTEM_SERVICE_TABLEnotUsed2;} KSERVICE_TABLE_DESCRIPTOR, * PKSERVICE_TABLE_DESCRIPTOR;其中每一项又是一个结构体:KSYSTEM_SERVICE_TABLE 。通过结构体表示为如下:
typedef struct _KSYSTEM_SERVICE_TABLE{PULONGServiceTableBase;// SSDT (System Service Dispatch Table)的基地址PULONGServiceCounterTableBase;// 用于 checked builds, 包含 SSDT 中每个服务被调用的次数ULONGNumberOfService;// 服务函数的个数, NumberOfService * 4 就是整个地址表的大小ULONGParamTableBase;// SSPT(System Service Parameter Table)的基地址} KSYSTEM_SERVICE_TABLE, * PKSYSTEM_SERVICE_TABLE;通过看图形化界面可以更加直观,下图是ntoskrnl.exe和win32k.sys的服务函数结构 。
r0下的进程保护

文章插图
 
HOOK SSDT有了上面的知识储备,理解SSDT HOOK就很容易了 。
当3环程序执行后,操作系统拿着索引去SSDT表中找对应的0环程序,这时我们就可以在SSDT表中做点手脚,将某一个api函数的指针改成我们自己函数的指针,这样执行的将会是我们自己的代码 。


推荐阅读