Windows ObjectType Hook 之 OkayToCloseProcedure

编程入门 行业动态 更新时间:2024-10-28 17:23:08

Windows <a href=https://www.elefans.com/category/jswz/34/1610808.html style=ObjectType Hook 之 OkayToCloseProcedure"/>

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; // diULONG_PTR v4; // rcxv2 = 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, ...)
#endiftypedef 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;
#endiftypedef 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
);
#endifEXTERN_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 进行解除占用关闭句柄时失败了,目的实现。

更多推荐

Windows ObjectType Hook 之 OkayToCloseProcedure

本文发布于:2023-11-16 14:33:36,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1624796.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:ObjectType   Windows   OkayToCloseProcedure   Hook

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!