SSDT的全称是 System Services Descriptor Table,系统服务描述符表
导出变量KeServiceDescriptorTable,通过这个我们能查看相关的系统服务描述表SSDT
(资料图)
知识点:因为KeServiceDescriptorTable是一个导出变量,如果我们在驱动中要使用,那么声明一下就可以使用了
dd KeServiceDescriptorTable
比如未导出变量KeServiceDescriptorTableShadow需要用其他的方式来查找,但是windbg中能够载入相关的pdb文件,所以windbg可以直接使用这个变量
知识点:通过KeServiceDescriptorTableShadow变量来进行查看,能够观察到多个系统服务表
dd KeServiceDescriptorTableShadow
系统服务表和SSDT表的结构体关系如下所示
typedef struct _SYSTEM_SERVICE_TABLE{PVOID ServiceTableBase;//System Service Dispatch Table 的基地址 PVOID ServiceCounterTable;//包含着 SSDT 中每个服务被调用次数的计数器。这个计数器一般由sysenter 更新。 unsigned int NumberOfServices;//由 ServiceTableBase 描述的服务的数目。 PVOID ParamTableBase;//包含每个系统服务参数字节数表的基地址-系统服务参数表 }SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;typedef struct _SSDT{SYSTEM_SERVICE_TABLE a; // ntoskrnlSYSTEM_SERVICE_TABLE b; // win32kSYSTEM_SERVICE_TABLE c; // no useSYSTEM_SERVICE_TABLE d; // no use}SSDT, *PSSDT;
这里拿NtReadVirtualMemory来进行分析学习
1、NtReadVirtualMemory函数的函数服务号为0xBA
2、NtReadVirtualMemory函数三环的ReadVirtualMemory对应的0环调用函数
3、NtReadVirtualMemory相关的地址函数存储在系统服务表的函数地址表中
首先根据0xBA服务号,找到系统服务表中的函数地址表的位置
dd KeServiceDescriptorTable ,拿到系统服务表的函数地址表的地址0x80505570
通过偏移 dd 0x80505570+0xBA*4 ,拿到对应NtReadVirtualMemory在0环的函数调用地址0x805b52f6
u 805b52f6
dd KeServiceDescriptorTable ,先找到系统服务表中的参数大小的表的地址0x805059e4
接着找到对应0xBA服务号的参数大小的表 db 0x805059e4+0xba
可以看到十六进制为0x16,那么十进制就是20,4个字节一个参数,那么NtReadVirtualMemory的参数也就是5个参数
在SSDT表中追加一个函数地址(NtReadVirtualMemory),自己编写API的3环部分调用这个新增的函数(注意:使用2-9-9-12分页)。
首先要追加一个函数地址的话,那么要改变的有系统服务表中的哪写字段?
1、系统服务表中的函数地址表中需要添加四个字节,该四个字节代表的是新的函数地址的位置
2、系统服务表中描述的函数的数目需要加一
3、系统服务表中描述的参数表需要添加新的函数地址的一个对应的参数字节大小的位置