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. MyBatis学习总结(一)——MyBatis入门学习

    一.MyBatis 简介 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可 ...

  2. API:获取当前用户的公网IP

    在vue项目根目录下" public " 文件夹中的index.html,也就是根节点所在的文件引入JS,vue项目中静态文件需要在这里引入,用 script 标签规避跨域 < ...

  3. 谈谈如何进阶Java高级工程师

    从入门到瓶颈(++文末附学习脑图++) 首先,先自我介绍一下,楼主94年的,四川人,普通大专毕业. 第一阶段 实习阶段 2015年,实习阶段去浙江温州(没错,就是皮革厂的那个地方)找了份软件实施的工作 ...

  4. 技术栈:springboot2.x,vue,activiti5.22,mysql,带工作流系统

    前言 activiti工作流,企业erp.oa.hr.crm等审批系统轻松落地,请假审批demo从流程绘制到审批结束实例. 一.项目形式 springboot+vue+activiti集成了activ ...

  5. python语言介绍及安装

    Python语言简介 Python是什么语言 Python是一种解释型的.可移植的.开源的脚本. 什么是计算机编程 计算机程序:为了让计算机执行某些操作或解决某个问题而编写的一系列有序指令的集合 如何 ...

  6. fontawesome图标不显示的原因

    1.查看css路径是否正确 2.查看font文件夹内的字体文件是否引入 3.查看font文件夹内的字体资源路径是否正确

  7. Sentry 监控 - Search 搜索查询实战

    系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...

  8. Java基础系列(25)- break、continue、goto

    break在任何循环语句的主体部分,均可用break控制循环的流程.break用于强行退出循环,不执行循环中剩余的语句.(break语句也在switch语句中使用) continue语句用于在循环语句 ...

  9. hadoop报错

    19/11/24 08:29:08 INFO qlh.MyMapreduce: ================this is job================= 19/11/24 08:29: ...

  10. Mybatis-Plus 全局Update更新策略,和insert插入查询策略

    前言 最近在使用mybatis-plus做项目的时候,发现使用updatById方法的时候,更新某个字段时候出现了问题,一般业务操作都是更新不为空的字段,结果发现更新了所有字段,这是由于mybatis ...