Windows内核开发-10-监听对象

Windows内核除了可以监听进程,线程、dll还可以监听特定的对象和注册表。这里先讲一下监听对象。

监听对象

内核提供了一种可以监听对特定的对象类型的句柄进行打开或复制的机制。正式支持的对象类型有进程和线程,Windows10还支持一个桌面对象(桌面对象这个先不考虑)。

这个和前面的监听进程线程以及模块加载是有区别的。这个是相对于对象的句柄的,比如说一个进程的句柄,线程的句柄,别的进程通过关闭这个进程的句柄来关闭这个进程这种。是这个意思。

这里也有很多和前面相似的地方。

比如说,首先得注册通知。

注册对象通知

注册对象通知的主要API:

NTSTATUS ObRegisterCallbacks(
 POB_CALLBACK_REGISTRATION CallbackRegistration,
 PVOID                     *RegistrationHandle
);

如果采用这个API,必须在链接是开启/integritycheck

void ObUnRegisterCallbacks(
 PVOID RegistrationHandle
);//关闭注册的API

整体说明下这两个API如何使用:

首先有一个公用的参数 RegistrationHandle,这个参数在注册的API里面是一个输出参数,然后在取消注册里面是一个输入参数,相当于这个参数会和注册的对象进行一个绑定,通过注册API会给它赋一个值,然后取消注册API会通过它的值,来唯一标识一个对象进行取消注册这样子。

比较重要的是注册API的第一个参数:CallbackRegistration。

typedef struct _OB_CALLBACK_REGISTRATION {
 USHORT                    Version;
 USHORT                    OperationRegistrationCount;
 UNICODE_STRING            Altitude;
 PVOID                     RegistrationContext;
 OB_OPERATION_REGISTRATION *OperationRegistration;
} OB_CALLBACK_REGISTRATION, *POB_CALLBACK_REGISTRATION;

这个结构体是必须在注册前先初始化的。

_OB_CALLBACK_REGISTRATION

这个结构体比较重要,需要展开讲讲。

字段 含义
Version 必须为设置为OB_FLT_REGISTRATION_VERSION
OperationRegistrationCount 被注册的数量,指定了OperationRegistration指向的结构体数量。
Altitude 这个高度值,用来标榜被调用的顺序,值越高在调用链中就越早。但是不能和之前的值有重复值,这个其实没啥用,最主要的是防止重复了。这个值是一个无限精度的十进制数字,所以小数或者随机数都可以,最主要的别重复了。一般会多写点,比如说 123145,111111这种,就很大程度上可以规避重复。
RegistrationContext 这个值由系统和驱动自动赋值,传个NULL就行
OperationRegistration 这个值比较重要且复杂,单独解释。

OperationRegistration

这个结构体用来具体标榜要通知的内容的信息:

typedef struct _OB_OPERATION_REGISTRATION {
 POBJECT_TYPE                *ObjectType;
 OB_OPERATION                Operations;
 POB_PRE_OPERATION_CALLBACK  PreOperation;
 POB_POST_OPERATION_CALLBACK PostOperation;
} OB_OPERATION_REGISTRATION, *POB_OPERATION_REGISTRATION;
字段 内容
ObjectType 标记要通知的对象的类型:进程、线程、桌面。PsProcessType PsThreadType ExDesktopObjectType。
Operations 标记要做的操作,打开创建还是复制。OB_OPERATION_HANDLE_CREATE OB_OPERATION_HANDLE_DUPLICATE
PreOperation 一个函数指针PobPreOperationCallback,在系统调用涉及到对象的时候之前就采用这个回调函数。
PostOperation 一个函数指针PobPreOperationCallback,在系统调用涉及到对象的时候之后就采用这个回调函数。
POB_PRE_OPERATION_CALLBACK PobPreOperationCallback;

OB_PREOP_CALLBACK_STATUS PobPreOperationCallback(
 PVOID RegistrationContext,
 POB_PRE_OPERATION_INFORMATION OperationInformation
)
{...}

POB_POST_OPERATION_CALLBACK PobPostOperationCallback;

void PobPostOperationCallback(
 PVOID RegistrationContext,
 POB_POST_OPERATION_INFORMATION OperationInformation
)
{...}

这里面的RegistrationContext是上下文寄存器环境OperationInformation是记录着一些相关的对象信息。

这个OperationInformation大同小异,比如说调用前的OperationInformation就是这个结构体:

typedef struct _OB_PRE_OPERATION_INFORMATION {
OB_OPERATION                 Operation;
union {
  ULONG Flags;
  struct {
    ULONG KernelHandle : 1;
    ULONG Reserved : 31;
  };
};
PVOID                       Object;
POBJECT_TYPE                 ObjectType;
PVOID                       CallContext;
POB_PRE_OPERATION_PARAMETERS Parameters;
} OB_PRE_OPERATION_INFORMATION, *POB_PRE_OPERATION_INFORMATION;
字段 意义
Operation 操作类型
KernelHandle 是否是内核对象
Object 进程就是EPROCESS,线程就是PETHREAD
ObjectType 对象的类型,和前面一样
CallContext 驱动自动赋值,不是很重要,这里用不到
Parameters 基于操作的附加信息

针对parameter又有扩展内容:

typedef union _OB_PRE_OPERATION_PARAMETERS {
 OB_PRE_CREATE_HANDLE_INFORMATION    CreateHandleInformation;
 OB_PRE_DUPLICATE_HANDLE_INFORMATION DuplicateHandleInformation;
} OB_PRE_OPERATION_PARAMETERS, *POB_PRE_OPERATION_PARAMETERS;

然后这里的CreateHandleInformation我们用得上:

typedef struct _OB_PRE_CREATE_HANDLE_INFORMATION {
 ACCESS_MASK DesiredAccess;
 ACCESS_MASK OriginalDesiredAccess;
} OB_PRE_CREATE_HANDLE_INFORMATION, *POB_PRE_CREATE_HANDLE_INFORMATION;

DesiredAccess表示的是访问掩码,也就是获得对进程操作的权限,我们只要在这里把关闭进程的权限给删除了就好了。

实例代码:

由于各种API啊,各种结构体啊,调用起来层次复杂,光这样讲肯定是少了很多东西,用一个实际场景来讲会更好。

这里提供一个保护进程的思想,就是通过进程的PID来进行保护,删除除掉别的进程打开保护进程的句柄时的关闭权限。就行了。

思路的话就是通过调用前,判断是不是我们保护的进程,如果是就不让关闭了,删除掉PROCESS_TERMINATE权限。,其实比较简单。

整个驱动的代码我写好打包上github了:

https://github.com/skrandy/ProtectYourProcess

最终结果:

添加了保护后,再用任务管理器就无法关闭了。

小结

监听对象,通过对其它进程对别的进程、线程以及桌面对象的处理而进行一个处理。说起来有的绕口了,就是说比如说正常的用r3的API来打开一个进程,肯定是会有权限,然后可以再内核中添加保护代码,当打开你的进程句柄时,关闭掉一些权限,比如说这里的关闭权限,那么正常的API关闭流程,比如说OpenProcess,然后CloseProcess这种就无法关闭了。

Windows内核开发-10-监听对象的更多相关文章

  1. Windows内核开发-4-内核编程基础

    Windows内核开发-4-内核编程基础 这里会构建一个简单但是完整的驱动程序和一个客户端,部署内核执行一些平时user下无法执行的操作. 将通过以下内容进行讲解: 1 介绍 2 驱动初始化 3 Cr ...

  2. Windows内核开发-6-内核机制 Kernel Mechanisms

    Windows内核开发-6-内核机制 Kernel Mechanisms 一部分Windows的内核机制对于驱动开发很有帮助,还有一部分对于内核理解和调试也很有帮助. Interrupt Reques ...

  3. Windows内核基础知识-8-监听进程、线程和模块

    Windows内核基础知识-8-监听进程.线程和模块 Windows内核有一种强大的机制,可以在重大事件发送时得到通知,比如这里的进程.线程和模块加载通知. 本次采用链表+自动快速互斥体来实现内核的主 ...

  4. AngularJS - Watch 监听对象

    <body> <div ng-app="myApp"> <div ng-controller="firstController"& ...

  5. vue 监听对象里的特定数据

    vue  监听对象里的特定数据变化 通常是这样写的,只能监听某一个特定数据 watch: { params: function(val) { console.log(val) this.$ajax.g ...

  6. Windows内核开发-3-内核编程基础

    Windows内核开发-3-内核编程基础 这里会深入讲解kernel内核的API.结构体.和一些定义.考察代码在内核驱动中运行的机制.最后把所有知识合在一起写一个有用的驱动. 本章学习要点: 1:通用 ...

  7. 在vue中使用watch监听对象或数组

    最近发现在vue中使用watch监听对象或者数组时,当数组或者对象只是单一的值改变时,并不会出发watch中的事件. 在找问题过程中,发现当数组使用push一类的方法时,会触发watch,如果只是单一 ...

  8. Object.defineProperty 监听对象属性变化

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...

  9. Windows平台下Oracle监听服务启动过程中日志输出

    Windows平台下Oracle监听服务启动过程中日志输出记录. 日志目录:D:\app\Administrator\diag\tnslsnr\WIN-RU03CB21QGA\listener\tra ...

随机推荐

  1. adb shell 查看当前与用户交互的 activity

    adb shell dumpsys activity activities | grep mActivityComponent

  2. Git - Mac 电脑使用 brew 更新 Git

    安装 Homebrew Homebrew 是一个软件包管理器.它的作用就是将软件包安装到自己的目录中,然后将其文件符号链接到 /usr/local.更多信息,请自行进入官网查看 https://bre ...

  3. djangoProject default codes

    1 === 2 settings.py 3 === 4 """ 5 Django settings for djangoProject project. 6 7 Gene ...

  4. JAVA安全基础之反射

    JAVA安全基础之反射 在JAVA安全中,反射是一个经常使用的技术,所以熟悉使用反射是非常必要的.下面就简单的讲下JAVA的反射的用法 什么是反射 每个类都有对应的Class类对象,该Class类对象 ...

  5. [第八篇]——Docker 容器使用之Spring Cloud直播商城 b2b2c电子商务技术总结

    Docker 客户端 docker 客户端非常简单 ,我们可以直接输入 docker 命令来查看到 Docker 客户端的所有命令选项. xxx@xxx:~# docker 可以通过命令  docke ...

  6. 洛谷P1803——凌乱的yyy(贪心)

    题目描述 现在各大oj上有n个比赛,每个比赛的开始.结束的时间点是知道的. yyy认为,参加越多的比赛,noip就能考的越好(假的) 所以,他想知道他最多能参加几个比赛. 由于yyy是蒟蒻,如果要参加 ...

  7. 使用Java MVC模式设计一个学生管理系统

    最近在做web实验,要求是用jsp+servlet+mysql实现一个学生管理系统,完成对数据库的增删改查. 效果图:   代码: package dao; import java.util.List ...

  8. Django学习day03随堂笔记

    每日测验 """ 今日考题 1.什么是静态文件,django静态文件配置如何配置,如何解决接口前缀不断变化,html页面上路径的引用需要反复修改的问题 2.request ...

  9. PHP的那些魔术方法(二)

    上文中介绍了非常常用并且也是面试时的热门魔术方法,而这篇文章中的所介绍的或许并不是那么常用,但绝对是加分项.当你能准确地说出这些方法及作用的时候,相信对方更能对你刮目相看. __sleep()与__w ...

  10. java中避免集合死链调用

    目录 1. 前言 2. 场景 3. 环境 3.1 开发环境准备 3.2 数据准备 3.2.1 Mysql数据库表及数据 3.2.2 redis库数据 4. 解决方式 5.完整代码 5.1Model 5 ...