Windows ObjectType Hook 之 OkayToCloseProcedure

news2024/11/27 8:48:05

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 进行解除占用关闭句柄时失败了,目的实现。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(后续补充)vue+express、gitee pm2部署轻量服务器

首先 防火墙全部关闭算了 首先 防火墙全部关闭算了 首先 防火墙全部关闭算了 首先 防火墙全部关闭算了 首先 防火墙全部关闭算了 首先 防火墙全部关闭算了 关闭防火墙 systemctl stop firewalld 重新载入防火墙使设置生效 firewall-cmd --reload 后端的 pm2.config.cjs …

一文理解JPA中的save()方法为什么有时候只能插入无法更新

总结&#xff1a;使用save()方法更新某一具体的记录&#xff08;如用户密码&#xff09;&#xff0c;必须要提供该记录的ID。 以常见的用户管理为例&#xff0c;当我们调用userRepository.save()时&#xff0c;这是它背后的逻辑&#xff1a; 如果实体的ID为null或者不在数据库…

C++标准模板(STL)- 类型支持 (类型属性,is_abstract,is_signed,is_unsigned)

类型特性 类型特性定义一个编译时基于模板的结构&#xff0c;以查询或修改类型的属性。 试图特化定义于 <type_traits> 头文件的模板导致未定义行为&#xff0c;除了 std::common_type 可依照其所描述特化。 定义于<type_traits>头文件的模板可以用不完整类型实例…

Qt学习:图形视图框架的使用

文章目录 前言一、场景、视图和图形项的介绍二、图形视图框架的坐标系统三、图形视图框架的事件处理四、示例完整代码五、QtCreator官方示例总结 前言 近期重温了一下Qt中的图形视图框架&#xff0c;这里将所学习的内容进行记录总结。这个框架提供了一个基于图形项的模型视图编…

基于match_phrase搜索的分词优化

ES 的match_phrase 搜索需要完整匹配输入的内容&#xff0c;比如我们搜索 ‘中国人民’ &#xff0c;要保证的是doc中必须有 ‘中国人民’ 的内容出现。再比如我们搜索 ‘国人民’ 时&#xff0c;结果集中的 doc 中就要有 ‘国人民’ 的内容。一般在使用match 或 term 搜索的时…

DL Homework 6

目录 一、概念 &#xff08;1&#xff09;卷积 &#xff08;2&#xff09;卷积核 &#xff08;3&#xff09;特征图 &#xff08;4&#xff09;特征选择 &#xff08;5&#xff09;步长 &#xff08;6&#xff09;填充 &#xff08;7&#xff09;感受野 二、探究不同卷…

植物花粉深度学习图片数据集大合集

最近收集了一波有关于植物花粉的图片数据集&#xff0c;可以用于相关深度学习模型的搭建&#xff0c;废话不多说&#xff0c;上数据集&#xff01;&#xff01;&#xff01; 1、23种花粉类型805张花粉图像数据集 关于此数据&#xff1a;花粉种类和类型的分类是法医抱粉学、考…

2023年中国金融控股公司研究报告

第一章 行业概况 1.1 定义 金融控股公司这一术语最初源自美国&#xff0c;特别是在美国的《金融服务法案》关于银行控股公司组织结构的条文中&#xff0c;首次出现了“金融控股公司”&#xff08;Financial Holding Company&#xff09;这一法律术语&#xff0c;尽管法案中并…

2023年【高压电工】报名考试及高压电工最新解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 高压电工报名考试考前必练&#xff01;安全生产模拟考试一点通每个月更新高压电工最新解析题目及答案&#xff01;多做几遍&#xff0c;其实通过高压电工作业考试题库很简单。 1、【单选题】 ()是指继电器不动作时处于…

Windows 内置Linux子系统的配置(From WSL1 to WSL2)

目录 我是如何从WSL1转到WSL2的? WSL1与WSL2的功能区别: 配置下载源 SSH配置 优雅使用windows的Linux子系统 我是如何从WSL1转到WSL2的? 第一次安装的子系统是WSL1的&#xff0c;因为不能使用systemctl &#xff0c;以及因为WSL1没有完整的Linux内核,所以使得WSL1很多命令…

vivado查看报告和消息1

AMD Vivado ™ 集成设计环境 (IDE) 可生成报告和消息 &#xff0c; 以便告知您各种工具交互期间的设计或设计进程状态。报告由 您&#xff08; 或工具 &#xff09; 在执行设计流程中的任意关键步骤时生成。报告可汇总有关设计的具体信息。 本工具可在设计进程中每个步骤自动…

软通杯算法竞赛--周赛题目(一)

目录 一、S属性大爆发 二、日期杯 三、 三人行必由我师 四、集合之差 五、咱们计算机不懂烷烃 六、适度跑步健康长寿 一、S属性大爆发 测试用例 5 esS qwert codeforces PoSgju LkkJKkO 输出案例 二、日期杯 输入案例&#xff1a; 3 2022 2022 11 1900 2100 15 1989 20…

EtherCAT主站写从站EEPROM抓包分析

0 工具准备 1.EtherCAT主站 2.EtherCAT从站&#xff08;本文使用步进电机驱动器&#xff09; 3.Wireshark1 抓包分析 1.1 报文总览 本文主站设置从站1字地址为0的EEPROM数据为0x3C00&#xff08;设置完毕后请还原字0的EEPROM数据&#xff09;&#xff0c;使用Wireshark抓取到…

检索已删除的视频方法,12 个最佳 Android 视频恢复应用程序/软件

您可能倾向于定期从 Android 设备中删除不必要的视频&#xff0c;同时保留精美的视频以使其保持井井有条。然而&#xff0c;有些人在删除一些有价值的视频而不是无用的视频时无意中犯了错误。如果您错误地从移动设备中删除了视频或清除了其内存&#xff0c;您可能想知道是否有办…

某大厂伺服驱动器量产方案

本文介一款大厂量产伺服驱动器方案&#xff01;带2500线省线式编码器&#xff0c;17位增量编码器&#xff0c;20位绝对值编码器&#xff01;标配CANopen、高精度运动控制&#xff0c;高速总线通讯&#xff0c;主芯片28335FPGA&#xff0c;已验证过&#xff0c;带can和485通讯&a…

OSError: libomp.so: cannot open shared object file: No such file or directory

报错&#xff1a;OSError: libomp.so: cannot open shared object file: No such file or directory https://stackoverflow.com/questions/52401840/what-is-the-ctypes-cdll-default-path 没有libomp.so 总算找到啦&#xff01;链接 export LD_LIBRARY_PATH/usr/lib/llvm…

【java学习—十二】文件字符流(3)

文章目录 1. 文件字符输入流2. 文件字符输出流3. 字符流完成拷贝文件 1. 文件字符输入流 读取文件操作步骤 : &#xff08;1&#xff09;建立一个流对象&#xff0c;将已存在的一个文件加载进流。 FileReader fr new FileReader(“Test.txt”);&#xff08;2&#xff09;创建…

C站你好,和你相遇的第1825天

文章目录 机缘收获日常成就憧憬 机缘 ①. 你好,C站 ②. 初识JAVA编程,遇到问题,粘贴问题百度搜索,大都数出来的解决方案都能在C站得到解决,对C站有一定的好感 ③. 起初在CSDN写博客,主要用来记录日常学习过程中的笔记、不断调整自己的笔记,如JAVA基础、框架、虚拟机等,为后…

【Linux】搭建Linux环境等——小喵爱上了林利克斯1

希望你开心&#xff0c;希望你健康&#xff0c;希望你幸福&#xff0c;希望你点赞&#xff01; 最后的最后&#xff0c;关注喵&#xff0c;关注喵&#xff0c;关注喵&#xff0c;大大会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的…

Elasticsearch:使用你的 RAG 来进行聊天

什么是人工智能中的检索增强生成&#xff08;RAG&#xff09;&#xff1f; 检索增强生成 (RAG)&#xff0c;与你的文档聊天的超级英雄&#xff0c;架起信息检索和文本生成世界的桥梁&#xff01; 这就像福尔摩斯和莎士比亚联手解决需要大量知识的复杂任务。 RAG 突然介入&…