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. vue element-ui 组件上传图片 之后 对上传按钮 进行隐藏,删除之后重新显示

    注:如果在当前的 vue 文件里 写了 style 样式,得 去除 scoped [私有属性必须去除,不能保留](这个是重点,不去除不生效), template 部分 <el-upload    ...

  2. 第三课:GDB 常用的调试命令概览

    先给出一个常用命令的列表,后面会结合具体的例子详细介绍每个命令的用法. 命令名称 命令缩写 命令说明 run r 运行一个程序 continue c 让暂停的程序继续运行 next n 运行到下一行 ...

  3. 链表 Linked List

    目录 链表介绍 单链表 单链表的应用实例 添加-直接添加到末尾 添加-顺序添加 更新 删除 单链表的面试题 双链表 链表介绍 链表时有序的列表,但是它在内存中是存储如下 小结 链表是以节点的方式来存储 ...

  4. 远程桌面无法复制粘贴 rdpclip.exe

    在一些意外情况下,远程桌面无法与桌面共享复制内容,这时候需要杀掉一个进程并重新启动 远程桌面复制之后,无法在本地桌面粘贴   在远程桌面中右键点击,选择启动任务管理器   找到一个进行rdpclip. ...

  5. IP 地址无效化

    给你一个有效的 IPv4 地址 address,返回这个 IP 地址的无效化版本. 所谓无效化 IP 地址,其实就是用 "[.]" 代替了每个 ".". 示例 ...

  6. Django学习day03随堂笔记

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

  7. 【PHP数据结构】图的概念和存储结构

    随着学习的深入,我们的知识也在不断的扩展丰富.树结构有没有让大家蒙圈呢?相信我,学完图以后你就会觉得二叉树简直是简单得没法说了.其实我们说所的树,也是图的一种特殊形式. 图的概念 还记得我们学习树的第 ...

  8. 关于当前PHP脚本运行时系统信息相关函数

    我们的 PHP 在执行的时候,其实可以获取到非常多的当前系统相关的信息.就像很多开源的 CMS 一般会在安装的时候来检测一些环境信息一样,这些信息都是可以方便地动态获取的. 脚本文件运行时的系统用户相 ...

  9. PC+PLC通过Modbus协议构建工控系统

    一. 概述 工业设备采用HMI+PLC控制是比较常见的方案,随着工业自动化的要求越来越高,现在很多设备都要求接入企业MES系统,MES系统一般为WEB系统,接口形式大部分为HTTP协议,这种传统方案和 ...

  10. jmeter调度器的使用

    前言 使用jmeter 做压测的时候,希望对一个接口持续压测 10 分钟或者半小时,可以使用调度器设置持续压测时间. https://www.cnblogs.com/yoyoketang/p/1415 ...