r0下进程保护

简介

SSDT 的全称是 System Services Descriptor Table,系统服务描述符表。这个表就是一个把 Ring3 的 Win32 API 和 Ring0 的内核 API 联系起来。SSDT 并不仅仅只包含一个庞大的地址索引表,它还包含着一些其它有用的信息,诸如地址索引的基地址、服务函数个数等。通过修改此表的函数地址可以对常用 Windows 函数及 API 进行 Hook,从而实现对一些关心的系统动作进行过滤、监控的目的。一些 HIPS、防毒软件、系统监控、注册表监控软件往往会采用此接口来实现自己的监控模块。

结构

ssdt是一张表,即系统服务描述符表

kd> dd  KeServiceDescriptorTable

 

第一个参数指向的地址存储的是全部的内核函数

这个参数代表ssdt表里面有多少个内核函数

这个参数是一个指针指向一个地址,这里表示的是与上面的内核函数相对应的参数个数,例如第一个为18,参数个数就为18/4 = 6

这里找一下OpenProcess在SSDT表的索引,首先bp OpenProcess

断在了kerner32.OpenProcess,这里OpenProcess会调用ntdll里面的ZwOpenProcess进入ring0,在ring0ZwOpenProcess又会调用NtOpenProcess

跟进去可以发现mov eax,0x7A,那么这里ZwOpenProcess的索引就为0x7A

然后通过KeServiceDescriptorTable 找到所有的内核函数,通过内核函数+偏移找到OpenProcess函数

在 NT 4.0 以上的 Windows 操作系统中,默认就存在两个系统服务描述表,这两个调度表对应了两类不同的系统服务,这两个调度表为:KeServiceDescriptorTable 和 KeServiceDescriptorTableShadow,其中 KeServiceDescriptorTable 主要是处理来自 Ring3 层 Kernel32.dll 中的系统调用,而 KeServiceDescriptorTableShadow 则主要处理来自 User32.dll 和 GDI32.dll 中的系统调用,并且KeServiceDescriptorTable 在ntoskrnl.exe(Windows 操作系统内核文件,包括内核和执行体层)是导出的,而 KeServiceDescriptorTableShadow 则是没有被 Windows 操作系统所导出。

关于 SSDT 的全部内容则都是通过KeServiceDescriptorTable 来完成的。

SSDT表的结构通过结构体表示为如下:

typedef struct _KSERVICE_TABLE_DESCRIPTOR
{
  KSYSTEM_SERVICE_TABLE  ntoskrnl;  // ntoskrnl.exe 的服务函数
  KSYSTEM_SERVICE_TABLE  win32k;   // win32k.sys 的服务函数
(GDI32.dll/User32.dll 的内核支持)
  KSYSTEM_SERVICE_TABLE  notUsed1;
  KSYSTEM_SERVICE_TABLE  notUsed2;
} KSERVICE_TABLE_DESCRIPTOR, * PKSERVICE_TABLE_DESCRIPTOR;

其中每一项又是一个结构体:KSYSTEM_SERVICE_TABLE 。通过结构体表示为如下:

typedef struct _KSYSTEM_SERVICE_TABLE
{
  PULONG  ServiceTableBase;      // SSDT (System Service Dispatch Table)的基地址
  PULONG  ServiceCounterTableBase;  // 用于 checked builds, 包含 SSDT 中每个服务被调用的次数
  ULONG  NumberOfService;      // 服务函数的个数, NumberOfService * 4 就是整个地址表的大小
  ULONG  ParamTableBase;       // SSPT(System Service Parameter Table)的基地址
} KSYSTEM_SERVICE_TABLE, * PKSYSTEM_SERVICE_TABLE;

调用号

进入0环时调用号是eax传递的,但这个调用号并不只是一个普通的数字作为索引序号,系统会把他用32位数据表示,拆分成19:1:12的格式,如下:

图片

 

分析一下0-11这低12位组成一个真正的索引号,第12位表示服务表号,13-31位没有使用。而进入内核后调用哪一张表,就由调用号中的第12位决定,为0则调用SSDT表,为1则调用ShadowSSDT表。

 

相关推荐

  1. 什么情况需要进行网络安全等级保护

    2024-02-04 15:34:04       32 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-04 15:34:04       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-04 15:34:04       106 阅读
  3. 在Django里面运行非项目文件

    2024-02-04 15:34:04       87 阅读
  4. Python语言-面向对象

    2024-02-04 15:34:04       96 阅读

热门阅读

  1. 音频处理库和工具,以及相关开源

    2024-02-04 15:34:04       46 阅读
  2. 什么是ISO21434网络安全中的汽车网络?-亚远景

    2024-02-04 15:34:04       61 阅读
  3. nginx:配置内网转发阿里云oss

    2024-02-04 15:34:04       51 阅读
  4. js的深拷贝与浅拷贝

    2024-02-04 15:34:04       50 阅读
  5. python实现的LDA算法

    2024-02-04 15:34:04       47 阅读
  6. 【力扣刷题练习】876. 链表的中间结点

    2024-02-04 15:34:04       44 阅读
  7. leetcode-2的幂

    2024-02-04 15:34:04       52 阅读
  8. 滴滴面经相关知识整理(基于newbing)

    2024-02-04 15:34:04       61 阅读
  9. 开源软件的发展

    2024-02-04 15:34:04       52 阅读
  10. Kubernetes - DAEMONSET 与 DEPLOYMENT 区别

    2024-02-04 15:34:04       47 阅读