首页 > 系统相关 >Windows ObjectType Hook 之 OkayToCloseProcedure

Windows ObjectType Hook 之 OkayToCloseProcedure

时间:2023-11-05 11:24:31浏览次数:49  
标签:ULONG Windows OBJECT OkayToCloseProcedure Hook KDPRINT PVOID TYPE

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

标签:ULONG,Windows,OBJECT,OkayToCloseProcedure,Hook,KDPRINT,PVOID,TYPE
From: https://www.cnblogs.com/ImprisonedSoul/p/17810279.html

相关文章

  • Windows下,Jar包启动时,自定义cmd窗口名称
    新建bat文件;输入并替换内容; @echoofftitleAPI_XXXX-%date%-%time%-%cd%)java-Dfile.encoding=utf-8 -jar-Xms1024m-Xmx2048m-XX:PermSize=128M-XX:MaxPermSize=256M-Xdebug-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=6002XXXX.jar ......
  • 如何做到像坚果云这样自定义 Windows 文件资源管理器的 UI?
    要像坚果云那样自定义Windows文件资源管理器的UI,你可以尝试以下几个步骤:开发一个Shell扩展:使用WindowsShell编程,你可以开发一个Shell扩展程序,它可以插入到Windows文件资源管理器中,并扩展其功能。可以使用编程语言,如C++或C#来编写Shell扩展。注册Shell扩展:一旦你开发完成Shell扩展,......
  • Windows系统 C/C++程序编译后首次执行时间很长 断网则正常执行 的解决方法
    Windows系统C/C++程序编译后首次执行时间很长断网则正常执行的解决方法问题描述运行环境:Win10、Win11或其他Win环境。在各类IDE(包括但不限于VC6/VisualStuido等)编译任意C/C++源码(无论该程序有多简单),首次运行时间异常地长,即在黑窗口无任何输出。等待一段时间后有程序正......
  • Gitlab加入LDAP认证 (windows AD)<03>
    环境信息:主机名称IP角色AD-Server192.168.61.237AD服务器gitlab192.168.61.112AD服务器[root@gitlab~]#curl-shttps://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh|sudobash[root@gitlab~]#yum-yinstallgitlab......
  • 程序员笔记本电脑选 windows 还是 MAC
    计算机选择是每个进入IT行业同学的第一个重要选择,那么你是怎么选择的呢?选择操作系统(Windows还是macOS)取决于程序员的需求、偏好和工作流程。每个操作系统都有其优点和缺点,下面将分别讨论它们,以帮助你做出决策。视频:https://www.bilibili.com/video/BV13c411d7eK/Windows:**......
  • hook_so
    在对应的so加载后再执行hook代码//刚注入的时候这个so还没加载,需要hookdlopenfunctioninline_hook(){varbase_hello_jni=Module.findBaseAddress("libxxxx.so");console.log("base_hello_jni:",base_hello_jni);if(base_hello_jni){console.lo......
  • 什么是 Windows 操作系统 DLL 文件的 Side-by-Side Assemblies 技术
    .dll文件是Windows操作系统中的一种重要文件类型。全名为“动态链接库”(DynamicLinkLibraries),它包含了一些可以由多个程序共享的代码和数据。这使得在Windows下的开发者可以将一些公共的功能和数据集中到一些.dll文件中,而这些功能和数据可以被任何需要的程序所调用和使用......
  • Windows Server2019安装MySQL8.0.32
    安装包下载:https://downloads.mysql.com/archives/community/下载mysql-8.0.32-winx64.zip1、制定目录配置basedir=D:\\mysql8.0.32#mysql数据存放目录datadir=D:\\mysql8.0.32\\data将.zip压缩包解压到D盘,并重命名为mysql8.0.322、编辑my.ini文件[client]#max_a......
  • 保姆级教学之解决Windows系统下shutil zipfile解压缩中文乱码问题
    使用shutil,zipfile模块解压文件,若待解压文件路径中带有中文,则会出现一下乱码情况。解决方案:直接对python库文件zipfile.py进行修改即可。以本人正在使用的Python3.10.4版为例。以下时具体操作流程。1、找到python所在文件路径如不知道python装在哪里,可以利用python的内置模块sys的s......
  • Windows 11 搭建Stable Diffusion遇到的问题
    趁着双11,将我的i54690+ddr34gx2换掉了,换成了AMD5600+ddr4x2,另外加了个1t的m2的ssd。原先的硬件部分留下了:500w的金河田电源kingstonsdd128g系统启动盘保留wdblue1t也保留下来,但是最近待机之后总是会找不到,暂时没去调查什么原因之前的1650s显卡然后......