Windows ObjectType Hook 之 OkayToCloseProcedure

1、背景

  Object Type Hook 是基于 Object Type的一种深入的 Hook,比起常用的 SSDT Hook 更为深入。

  有关 Object Type 的分析见文章 《Windows驱动开发学习记录-ObjectType Hook之ObjectType结构相关分析》。

  这里进行的 Hook 为 其中之一的 OkayToCloseProcedure。文章实现文件对象的过滤。

2、OkayToCloseProcedure函数声明

  见文章 《Windows驱动开发学习记录-ObjectType Hook之ObjectType结构相关分析》。

  这里取 x64 环境下结构:

typedef BOOLEAN (*OB_OKAYTOCLOSE_METHOD)(
    IN PEPROCESS Process OPTIONAL,
    IN PVOID Object,
    IN HANDLE Handle,
    IN KPROCESSOR_MODE PreviousMode
    );

  

3、OkayToCloseProcedure 使用逻辑分析

  用 IDA 分析 Win11 22621 版本的 ntoskrnl.exe,查找 OkayToCloseProcedure 的使用逻辑,如下:

NTSTATUS __stdcall NtClose(HANDLE Handle)
{
        char v2; // di
        ULONG_PTR v4; // rcx

        v2 = KeGetCurrentThread()->PreviousMode;
        if ((MmVerifierData & 0x100) != 0 && !v2 && !(unsigned __int8)ObpIsKernelHandle(Handle, 0i64))
                VfCheckUserHandle(v4);
        return ObpCloseHandle((ULONG_PTR)Handle);
}
__int64 __fastcall ObpCloseHandle(ULONG_PTR BugCheckParameter1, unsigned __int8 a2)
{
        ......
                v9 = ExGetHandlePointer(v7);
        v51 = BYTE1(v9);
        v10 = (_OBJECT_TYPE*)ObTypeIndexTable[(unsigned __int8)ObHeaderCookie ^ *(unsigned __int8*)(v9 + 24) ^ (unsigned __int64)BYTE1(v9)];
        if (v10->TypeInfo.OkayToCloseProcedure)
        {
                if (KeGetCurrentThread()->ApcState.Process != (struct _KPROCESS*)BugCheckParameter1a)
                {
                        KiStackAttachProcess(BugCheckParameter1a);
                        v42 = 1;
                }
                v20 = (struct _EX_RUNDOWN_REF*)BugCheckParameter1a;
                if (!v10->TypeInfo.OkayToCloseProcedure((_EPROCESS*)BugCheckParameter1a, (void*)(v9 + 48), (void*)v4, a2))
                {
                        _InterlockedExchangeAdd64(v7, 1ui64);
                        _InterlockedOr(v41, 0);
                        if (*(_QWORD*)(v6 + 48))
                                ExfUnblockPushLock(v6 + 48, 0i64);
                        KeLeaveCriticalRegion();
                        if (v42)
                                KiUnstackDetachProcess(v52, 0i64);
                        v12 = 0xC0000235;
                        goto LABEL_36;
                }
        }
        ......
}

  可以看到在调用 NtClose,然后 NtClose 调用 ObpCloseHandle,而在 ObpCloseHandle 中有判断 OkayToCloseProcedure 是否为空,不为空则调用 OkayToCloseProcedure,若 OkayToCloseProcedure 返回失败,则整个 ObpCloseHandle 返回失败,也即 NtClose 返回失败。

  于是我们的实验逻辑即在驱动中打开一个文件句柄,然后过滤文件对象的 OkayToCloseProcedure,再使用 IObit Unlocker 进行解除占用删除。

4、文件对象过滤

4.1 使用驱动打开一个文件占用

  主要代码如下:

EXTERN_C NTSTATUS  DriverEntry(PDRIVER_OBJECT DriverObject,
        PUNICODE_STRING RegistryPath)
{

        KDPRINT("【Hello】", "Enter...\r\n");
        KDPRINT("【Hello】", "Hello Kernel World! CurrentProcessId:0x%p CurrentIRQL:0x%u\r\n", PsGetCurrentProcessId(), KeGetCurrentIrql());
        if (RegistryPath != NULL)
        {
                KDPRINT("【Hello】", "RegistryPath:%wZ\r\n", RegistryPath);
        }

        DriverObject->DriverUnload = DriverUnload;

        OBJECT_ATTRIBUTES oba = { 0 };
        IO_STATUS_BLOCK iosb = { 0 };
        UNICODE_STRING usFilePath = RTL_CONSTANT_STRING(L"\\??\\C:\\Users\\Administrator\\Desktop\\HelloDriver.exe");
        InitializeObjectAttributes(
                &oba,
                &usFilePath,
                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_OPENIF,
                NULL,
                NULL);
        NTSTATUS ntStatus = ZwCreateFile(
                &hSysFile,
                GENERIC_READ,
                &oba,
                &iosb,
                NULL,
                FILE_ATTRIBUTE_NORMAL,
                FILE_SHARE_READ,
                FILE_OPEN_IF,
                FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS | FILE_SYNCHRONOUS_IO_NONALERT,
                NULL,
                0);
        if (!NT_SUCCESS(ntStatus))
        {
                KDPRINT("【Hello】", "ZwCreateFile Failed, Code:0x%08x\r\n", ntStatus);
        }
        else
        {
                KDPRINT("【Hello】", "ZwCreateFile File OK\r\n");
        }

        return STATUS_SUCCESS;
}

  驱动打开了桌面的一个文件 HelloDriver.exe,并占用, 此时直接删除文件是会提示失败。

  安装此驱动后,DebugView信息如下:

  直接删除如下:

  之后使用 IObit Unlocker 解除占用并删除,如下:

  文件直接被删除。

4.2 Hook 文件对象 OkayToCloseProcedure 

  .h文件

#pragma once
#include <ntifs.h>


#if DBG
#define KDPRINT(projectName, format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,\
																						  projectName "::【" __FUNCTION__  "】" ##format, \
																						  ##__VA_ARGS__ ) 
#else
#define KDPRINT(format, ...)
#endif

typedef struct _OBJECT_TYPE_FLAGS {
        UCHAR CaseInsensitive : 1;
        UCHAR UnnamedObjectsOnly : 1;
        UCHAR UseDefaultObject : 1;
        UCHAR SecurityRequired : 1;
        UCHAR MaintainHandleCount : 1;
        UCHAR MaintainTypeList : 1;
        UCHAR SupportsObjectCallbacks : 1;
        UCHAR CacheAligned : 1;
}OBJECT_TYPE_FLAGS, * P_OBJECT_TYPE_FLAGS;

#ifdef _AMD64_
typedef struct _OBJECT_TYPE_INITIALIZER {
        USHORT				wLength;
        OBJECT_TYPE_FLAGS	ObjectTypeFlags;
        ULONG				ObjcetTypeCode;
        ULONG				InvalidAttributes;
        GENERIC_MAPPING		GenericMapping;
        ULONG				ValidAccessMask;
        ULONG				RetainAccess;
        ULONG				PoolType;
        ULONG				DefaultPagedPoolCharge;
        ULONG				DefaultNonPagedPoolCharge;
        PVOID				DumpProcedure;
        PVOID				OpenProcedure;
        PVOID				CloseProcedure;
        PVOID				DeleteProcedure;
        PVOID				ParseProcedure;
        PVOID				SecurityProcedure;
        PVOID				QueryNameProcedure;
        PVOID				OkayToCloseProcedure;
}OBJECT_TYPE_INITIALIZER, * POBJECT_TYPE_INITIALIZER;
#else // _AMD64_
typedef struct _OBJECT_TYPE_INITIALIZER {
        USHORT Length;
        BOOLEAN UseDefaultObject;
        BOOLEAN CaseInsensitive;
        ULONG InvalidAttributes;
        _GENERIC_MAPPING GenericMapping;
        ULONG ValidAccessMask;
        UCHAR SecurityRequired;
        UCHAR MaintainHandleCount;
        UCHAR MaintainTypeList;
        _POOL_TYPE PoolType;
        ULONG DefaultPagedPoolCharge;
        ULONG DefaultNonPagedPoolCharge;
        PVOID DumpProcedure;
        PVOID OpenProcedure;
        PVOID CloseProcedure;
        PVOID DeleteProcedure;
        PVOID ParseProcedure;
        PVOID SecurityProcedure;
        PVOID QueryNameProcedure;
        PVOID OkayToCloseProcedure;
}OBJECT_TYPE_INITIALIZER, * POBJECT_TYPE_INITIALIZER;
#endif



#ifdef _AMD64_
typedef struct _OBJECT_TYPE_EX {
        LIST_ENTRY					TypeList;
        UNICODE_STRING				Name;
        PVOID					DefaultObject;
        ULONG						Index;
        ULONG						TotalNumberOfObjects;
        ULONG						TotalNumberOfHandles;
        ULONG						HighWaterNumberOfObjects;
        ULONG						HighWaterNumberOfHandles;
        OBJECT_TYPE_INITIALIZER		TypeInfo;
        ULONGLONG					TypeLock;
        ULONG						Key;
        LIST_ENTRY					CallbackList;
}OBJECT_TYPE_EX, * POBJECT_TYPE_EX;
#else
typedef struct _OBJECT_TYPE_EX {
        UCHAR                                           Unamed[0x38];
        LIST_ENTRY					TypeList;
        UNICODE_STRING				Name;
        PVOID					DefaultObject;
        ULONG						Index;
        ULONG						TotalNumberOfObjects;
        ULONG						TotalNumberOfHandles;
        ULONG						HighWaterNumberOfObjects;
        ULONG						HighWaterNumberOfHandles;
        OBJECT_TYPE_INITIALIZER		TypeInfo;
        ULONG						Key;
        LIST_ENTRY					CallbackList;
}OBJECT_TYPE_EX, * POBJECT_TYPE_EX;
#endif

typedef enum _OB_OPEN_REASON {
        ObCreateHandle,
        ObOpenHandle,
        ObDuplicateHandle,
        ObInheritHandle,
        ObMaxOpenReason
} OB_OPEN_REASON;

typedef
BOOLEAN
(NTAPI* POKAYTOCLOSE_PROCEDURE)(
        IN PEPROCESS Process OPTIONAL,
        IN PVOID Object,
        IN HANDLE Handle,
        IN KPROCESSOR_MODE PreviousMode);



typedef struct _OBJECT_TYPE_HOOK_INFORMATION
{
        POBJECT_TYPE_EX pHookedObject;
        POKAYTOCLOSE_PROCEDURE pOringinalOkToCloseProcedureAddress;
}OBJECT_TYPE_HOOK_INFORMATION, * POBJECT_TYPE_HOOK_INFORMATION;



EXTERN_C
NTKERNELAPI
POBJECT_TYPE
NTAPI
ObGetObjectType(
        PVOID Object
);


#ifdef _AMD64_
EXTERN_C
NTKERNELAPI
NTSTATUS
PsReferenceProcessFilePointer(
        IN PEPROCESS Process,
        OUT PVOID* pFilePointer
);
#endif

EXTERN_C
NTKERNELAPI
PCHAR 
PsGetProcessImageFileName(PEPROCESS pEProcess);

void UnHookObjectType();

  .cpp 文件

#include "ObjectTypeHook.h"


OBJECT_TYPE_HOOK_INFORMATION g_HookInfomation = { 0 };
UNICODE_STRING g_usProtectedFileName = RTL_CONSTANT_STRING(L"*HELLODRIVER.EXE*");
UNICODE_STRING g_usSeperator = RTL_CONSTANT_STRING(L"\\");


BOOLEAN
NTAPI
CustomOkayToCloseProcedure(
        IN PEPROCESS Process OPTIONAL,
        IN PVOID Object,
        IN HANDLE Handle,
        IN KPROCESSOR_MODE PreviousMode)
{
        BOOLEAN bReturn = true;

        if (Object)
        {
                POBJECT_TYPE pObjectType = ObGetObjectType(Object);
                if (pObjectType == *IoFileObjectType)
                {
                       

                        if (FsRtlIsNameInExpression(&g_usProtectedFileName, &((PFILE_OBJECT)Object)->FileName, true, NULL))
                        {
                                if (PsGetProcessId(Process) == (HANDLE)4)
                                {
                                        KDPRINT("【ObjectTypeHook】", "Need Filter File Path Is %wZ\r\n", ((PFILE_OBJECT)Object)->FileName);
                                        KDPRINT("【ObjectTypeHook】", "Denied Process Id is 0x%08d\r\n", PsGetCurrentProcessId());
                                        bReturn = false;
                                } 
                        }
                }
        }

        if (!bReturn)
        {
                return false;
        }
        else
        {
                if (g_HookInfomation.pOringinalOkToCloseProcedureAddress)
                {
                        bReturn = g_HookInfomation.pOringinalOkToCloseProcedureAddress(
                                Process, Object, Handle, PreviousMode);
                }

                return bReturn;
        }

}

void UnHookObjectType()
{
        KDPRINT("【ObjectTypeHook】", "UnHook...\r\n");
        if (g_HookInfomation.pHookedObject)
        {
                InterlockedExchangePointer(
                        (PVOID*)(&g_HookInfomation.pHookedObject->TypeInfo.OkayToCloseProcedure),
                        g_HookInfomation.pOringinalOkToCloseProcedureAddress);
        }
}

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
        UNREFERENCED_PARAMETER(pDriverObject);
        KDPRINT("【ObjectTypeHook】", "CurrentProcessId : 0x%p CurrentIRQL : 0x%u \r\n",
                PsGetCurrentProcessId(),
                KeGetCurrentIrql());
        UnHookObjectType();
}



EXTERN_C NTSTATUS  DriverEntry(PDRIVER_OBJECT pDriverObject,
        PUNICODE_STRING pRegistryPath)
{
        UNREFERENCED_PARAMETER(pDriverObject);
        UNREFERENCED_PARAMETER(pRegistryPath);
        NTSTATUS ntStatus = STATUS_SUCCESS;
        KDPRINT("【ObjectTypeHook】", " Hello Kernel World! CurrentProcessId:0x%p CurrentIRQL:0x%u\r\n",
                PsGetCurrentProcessId(),
                KeGetCurrentIrql());
        pDriverObject->DriverUnload = DriverUnload;
        g_HookInfomation.pHookedObject = (POBJECT_TYPE_EX)(*IoFileObjectType);
        g_HookInfomation.pOringinalOkToCloseProcedureAddress =
                (POKAYTOCLOSE_PROCEDURE)(((POBJECT_TYPE_EX)(*IoFileObjectType))->TypeInfo.OkayToCloseProcedure);
        InterlockedExchangePointer(
                (PVOID*)(&g_HookInfomation.pHookedObject->TypeInfo.OkayToCloseProcedure),
                CustomOkayToCloseProcedure);
        KDPRINT("【ObjectTypeHook】", "Hook OkayToCloseProcedure!\r\n");
        return ntStatus;
}

  

4.3 实验效果

  加载第一个驱动实现文件占用,之后再加载第二个驱动进行钩子安装,如下:

  之后使用 使用 IObit Unlocker 进行解除占用删除。效果如下:

  虽然提示解锁删除成功,但文件还在,说明实际 IObit Unlocker 进行解除占用关闭句柄时失败了,目的实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/116716.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2023全新小程序广告流量主奖励发放系统源码 流量变现系统 带安装教程

2023全新小程序广告流量主奖励发放系统源码 流量变现系统 分享软件&#xff0c;吃瓜视频&#xff0c;或其他资源内容&#xff0c;通过用户付费买会员来变现&#xff0c;用户需要付费&#xff0c;有些人喜欢白嫖&#xff0c;所以会流失一部分用户&#xff0c;所以就写了这个系统…

【并行计算】多核处理器

这张图连接了几个并行计算的思想。 从上往下。 1.两个fetch/decode部件&#xff0c;是superscalar技术&#xff0c;每个cycle可以发射多个指令。 2.多个执行单元&#xff0c;支持乱序执行&#xff0c;是ILP&#xff0c;指令级并行。 3.每个执行单元里还支持SIMD操作。 4.有…

Centos 7.9.2009 firewalld 防火墙无法拦截Docker映射端口

一、linux版本&#xff1a; lsb_release -a 二、现象&#xff1a; firewalld 防火墙开启状态&#xff0c;未开放3306端口&#xff1b;但是本地依然可以链接mysql服务 三、原因&#xff1a; docker run -p 启动的时候会往iptables里面添加规则&#xff0c;firewall底层是基于…

Leetcode1122. 数组的相对排序

Every day a Leetcode 题目来源&#xff1a;1122. 数组的相对排序 解法1&#xff1a;哈希 用集合 set 存储 arr2 中的元素。 遍历数组 arr1 &#xff0c;设当前元素为 num&#xff1a; 如果 num 在 set 中出现&#xff0c;用哈希表 hash 记录 num 和它出现的次数。否则&a…

中文大语言模型汇总

推荐一篇非常棒的github&#xff1a;Awesome-Chinese-LLM 另附语言模型排行榜&#xff1a;FastChat 里面总结了几乎所有目前主流的中文大语言模型。在此记录一下&#xff0c;方便以后慢慢学习。

ELK极简上手

目录 引言 首先&#xff0c;下载相关的包 其次&#xff0c;安装启动elasticsearch 下一步&#xff0c;安装并启动logstash 最后&#xff0c;安装并启动kibana 进一步的&#xff0c;测试数据的流动 引言 最近整理电脑发现之前的一篇ELK极简入门笔记&#xff0c;现整理发出…

5G物联网关相较有线网关有哪些独特优势

5G为产业物联网应用带来了质的飞跃&#xff0c;5G技术实现更高速率、更低延迟和更大带宽&#xff0c;使得物联网能够接入更多数量的设备&#xff0c;实现更稳定、高效的连接和数据传输&#xff0c;在提高生产效率的同时&#xff0c;也进一步促进了物联网的应用发展和升级。 针对…

心理咨询服务预约小程序的效果如何

心理咨询机构很多&#xff0c;随着人们生活压力提升及生活多样化&#xff0c;部分人群在心理方面可能会面对各种不适&#xff0c;因此寻找心理咨询机构成为优先选项。 对商家来说&#xff0c;市场中拥有很多需求客户&#xff0c;且具备跨区域服务性&#xff0c;传统线下引流拓…

面试算法51:节点值之和最大的路径

题目 在二叉树中将路径定义为顺着节点之间的连接从任意一个节点开始到达任意一个节点所经过的所有节点。路径中至少包含一个节点&#xff0c;不一定经过二叉树的根节点&#xff0c;也不一定经过叶节点。给定非空的一棵二叉树&#xff0c;请求出二叉树所有路径上节点值之和的最…

在pycharm中配置GPU训练环境(Anaconda)(yolov5)

目录 1. 具体的配置过程&#xff1a; 2. 在指定位置&#xff08;路径&#xff09;创建虚拟环境&#xff1a; 3. conda常用命令&#xff1a; 4: 在跑模型时候遇到的一些问题&#xff1a; 4.1: conda添加python解释器找不到对应的python.exe文件 4.2: 报错“OSError: [WinErr…

描述低轨星座的特点和通信挑战,以及它们在5G和B5G中的作用。

文章目录 2章4 章5章&#xff08;没看&#xff09;6章&#xff08;没看&#xff09; 2章 将卫星星座中每个物理链路中可实现的数据速率、传播延迟和多普勒频移与3GPP技术报告中的参数进行分析和比较[3]。 相关配置 面向连接的网络&#xff0c;预先简历链路 卫星和地面终端有…

LV.12 D16 轮询与中断 学习笔记

一、CPU与硬件的交互方式 轮询 CPU执行程序时不断地询问硬件是否需要其服务&#xff0c;若需要则给予其服务&#xff0c;若不需要一段时间后再次询问&#xff0c;周而复始 中断 CPU执行程序时若硬件需要其服务&#xff0c;对应的硬件给CPU发送中断信号&#xff0c…

Linux中的进程等待

文章目录 1.进程等待1.1进程等待必要性1.1.1为什么有进程等待这个概念1.1.2进程等待是什么&#xff1f;1.1.3进程等待具体干什么&#xff1f; 1.2进程退出方法&#xff1a; 2.具体代码实现 1.进程等待 1.1进程等待必要性 1.1.1为什么有进程等待这个概念 之前讲过&#xff0c…

2-爬虫-代理池搭建、代理池使用(搭建django后端测试)、爬取某视频网站、爬取某视频网站、bs4介绍和遍历文档树

1 代理池搭建 2 代理池使用 2.1 搭建django后端测试 3 爬取某视频网站 4爬取某视频网站 5 bs4介绍和遍历文档树 1 代理池搭建 # ip代理-每个设备都会有自己的IP地址-电脑有ip地址---》访问一个网站---》访问太频繁---》封ip-收费&#xff1a;靠谱稳定--提供api-免费&#xff…

WebGL:基础练习 / 简单学习 / demo / canvas3D

一、前置内容 canvas&#xff1a;理解canvas / 基础使用 / 实用demo-CSDN博客 WebGL&#xff1a;开始学习 / 理解 WebGL / WebGL 需要掌握哪些知识 / 应用领域 / 前端值得学WebGL吗_webgl培训-CSDN博客 二、在线运行HTML 用来运行WebGL代码&#xff0c;粘贴--运行&#xff…

【教3妹学编程-java基础5】java多态详解

3妹&#xff1a;“太阳当空照&#xff0c;花儿对我笑&#xff0c;小鸟说早早早&#xff0c;你为什么背上炸药包” 2哥 :3妹&#xff0c;什么事呀这么开心呀。 3妹&#xff1a;2哥你看今天的天气多好啊&#xff0c;阳光明媚、万里无云、秋高气爽&#xff0c;适合秋游。 2哥&…

基于STM32HAL库看门狗(独立看门狗)-简述

目录 概述 一、开发环境 二、STM32CubeMx配置 三、编码 四、运行结果 五、总结 概述 一个成熟靠谱的项目&#xff0c;离不开“看门狗”的必选项&#xff0c;凡是人写的程序多少都会有出现bug的情况&#xff08;或芯片外设受外界干扰导致故障程序卡死、跑飞的情况&#xf…

vue基于ElementUI/Plus自定义的一些组件

vue3-my-ElementPlus 源码请到GitHub下载使用MyTable、MySelect、MyPagination 置顶|Top | 使用案例&#xff1a; 1.0 定义表格数据&#xff08;测试使用&#xff09; data() {return {tableData: [],value:[],valueList: [],}; },// 构造表格测试数据// 1 第一行&#xf…

重生奇迹mu召唤师怎么加点?

召唤师在重生奇迹mu游戏里面是一个智力型的职业&#xff0c;所以智力自然就成为主要加点属性&#xff0c;但是此职业却又算是近身攻击&#xff0c;因为她的技能范围并不算远&#xff0c;而且还是呈现出一种半径趋势&#xff0c;一方面是攻击伤害&#xff0c;另一方面则是辅助造…

Python 中的 Gzip 解压

我们将介绍Python中的gzip解压。 我们还将介绍如何使用 gzip 解压缩来解压缩压缩内容。 Python 中的 Gzip 解压 Python 中构建了许多用于压缩和解压缩目的的库&#xff0c;但我们将介绍 Gzip 库。 它是一种流行的数据压缩工具。 我们可以使用 gzip 通过将数据编码为人类无法读…