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

Windows ObjectType Hook 之 SecurityProcedure

时间:2023-11-07 11:23:15浏览次数:44  
标签:ULONG Windows TYPE OBJECT Hook ntStatus PVOID SecurityProcedure

1、背景

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

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

  这里进行的 Hook 为 其中之一的 SecurityProcedure。文章实现进程打开的过滤。

 

2、SecurityProcedure函数声明

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

  这里取 x64 环境下结构:

typedef NTSTATUS (*OB_SECURITY_METHOD)(
    IN PVOID Object,
    IN SECURITY_OPERATION_CODE OperationCode,
    IN PSECURITY_INFORMATION SecurityInformation,
    IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
    IN OUT PULONG CapturedLength,
    IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
    IN POOL_TYPE PoolType,
    IN PGENERIC_MAPPING GenericMapping
    );

  

3、SecurityProcedure 使用逻辑分析

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

__int64 __fastcall ObpCreateHandle(int a1, _QWORD* a2, signed int a3, __int64 a4, int a5, int a6, char a7, __int64 a8, int a9, PVOID* a10, _QWORD* a11)
{
        ......
        v79 = (_OBJECT_TYPE*)ObTypeIndexTable[(unsigned __int8)ObHeaderCookie ^ v78];
        v139 = v79;
        if ((_UNKNOWN*)v79->TypeInfo.SecurityProcedure == &SeDefaultObjectMethod)
        {
                ......
        }

        v84 = ExAllocatePool2(256i64, (unsigned int)ObpDefaultSecurityDescriptorLength, 1901290063i64);
        if (v84)
        {
                v105 = v79->TypeInfo.SecurityProcedure;
                GenericMapping = &v79->TypeInfo.GenericMapping;
                v122 = v139->TypeInfo.PoolType;
                v138 = (void**)(v77 + 40);
                v29 = v105(
                        Object,
                        QuerySecurityDescriptor,
                        (unsigned int*)&v141,
                        (void*)v84,
                        &v137,
                        (void**)v77 + 5,
                        v122,
                        GenericMapping,
                        AccessMode);
                if (v29 == 0xC0000023)
                {
                        ......
                }
                if (v29 >= 0)
                {
                        ......
                }
                ExFreePoolWithTag((PVOID)v84, 0);
        }

        return (unsigned int)v29;
}

  可以看到在调用 ObpCreateHandle 中有判断 SecurityProcedure 是否为默认的 SeDefaultObjectMethod,不为则调用指定的 SecurityProcedure  ,若 SecurityProcedure  返回失败,则整个 ObpCreateHandle 返回失败。

  于是我们的实验逻辑即过滤进程对象的 SecurityProcedure ,再用任务管理器结束过滤的进程。

 

4、进程对象过滤

4.1 代码

  .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 
NTSTATUS 
(NTAPI *PSECURITY_PROCEDURE)(
        IN PVOID Object,
        IN SECURITY_OPERATION_CODE OperationCode,
        IN PSECURITY_INFORMATION SecurityInformation,
        IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
        IN OUT PULONG CapturedLength,
        IN OUT PSECURITY_DESCRIPTOR* ObjectsSecurityDescriptor,
        IN POOL_TYPE PoolType,
        IN PGENERIC_MAPPING GenericMapping,
        IN CHAR Flag
        );


typedef struct _OBJECT_TYPE_HOOK_INFORMATION
{
        POBJECT_TYPE_EX pHookedObject;
        PSECURITY_PROCEDURE pOringinalSecurityProcedureAddress;
}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_usCurrentProcessName = RTL_CONSTANT_STRING(L"*TASKMGR.EXE*");
UNICODE_STRING g_usTargetProcessName = RTL_CONSTANT_STRING(L"*DBGVIEW64.EXE*");


NTSTATUS
NTAPI CustomQuerySecurityProcedure(
        IN PVOID Object,
        IN SECURITY_OPERATION_CODE OperationCode,
        IN PSECURITY_INFORMATION SecurityInformation,
        IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
        IN OUT PULONG CapturedLength,
        IN OUT PSECURITY_DESCRIPTOR* ObjectsSecurityDescriptor,
        IN POOL_TYPE PoolType,
        IN PGENERIC_MAPPING GenericMapping,
        IN CHAR Flag)
{
        NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
        PFILE_OBJECT pTargetFileObject = NULL;
        PFILE_OBJECT pCurrentFileObject = NULL;
        POBJECT_NAME_INFORMATION pTargetProcessNameInformation = NULL;
        POBJECT_NAME_INFORMATION pCurrentProcessNameInformation = NULL;
        BOOLEAN bDenied = false;
        do 
        {
                if (!Object)
                {
                        KDPRINT("【ObjectTypeHook】", "Object  is Null\r\n");
                        break;
                }
                POBJECT_TYPE pObjectType = ObGetObjectType(Object);
                if (pObjectType != *PsProcessType)
                {
                        break;
                }
                if (OperationCode != SECURITY_OPERATION_CODE::QuerySecurityDescriptor)
                {
                        break;
                }
                ntStatus = PsReferenceProcessFilePointer((PEPROCESS)Object, (PVOID*)&pTargetFileObject);
                if (!NT_SUCCESS(ntStatus))
                {
                        //KDPRINT("【ObjectTypeHook】", "PsReferenceProcessFilePointer failed, cod:0x%08x\r\n", ntStatus);
                        break;
                }
                ntStatus = IoQueryFileDosDeviceName(pTargetFileObject, &pTargetProcessNameInformation);
                if (!NT_SUCCESS(ntStatus))
                {
                        KDPRINT("【ObjectTypeHook】", "IoQueryFileDosDeviceName failed 1\r\n");
                        break;
                }
                
                if (!FsRtlIsNameInExpression(&g_usTargetProcessName, &pTargetProcessNameInformation->Name, true, NULL))
                {
                        break;
                }

                PEPROCESS pCurrentProcess = PsGetCurrentProcess();

                ntStatus = PsReferenceProcessFilePointer(pCurrentProcess, (PVOID*)&pCurrentFileObject);
                if (!NT_SUCCESS(ntStatus))
                {
                        //KDPRINT("【ObjectTypeHook】", "PsReferenceProcessFilePointer failed, cod:0x%08x\r\n", ntStatus);
                        break;
                }
                ntStatus = IoQueryFileDosDeviceName(pCurrentFileObject, &pCurrentProcessNameInformation);
                if (!NT_SUCCESS(ntStatus))
                {
                        KDPRINT("【ObjectTypeHook】", "IoQueryFileDosDeviceName failed 2\r\n");
                        break;
                }

                if (!FsRtlIsNameInExpression(&g_usCurrentProcessName, &pCurrentProcessNameInformation->Name, true, NULL))
                {
                        break;
                }
                KDPRINT("【ObjectTypeHook】", "Action denied\r\n");
                KDPRINT("【ObjectTypeHook】", "Target Process: %wZ\r\n", &pTargetProcessNameInformation->Name);
                KDPRINT("【ObjectTypeHook】", "Current Operation Process: %wZ\r\n", &pCurrentProcessNameInformation->Name);
                bDenied = true;
        } while (false);
        
        if (pCurrentFileObject)
        {
                ObDereferenceObject(pCurrentFileObject);
                pCurrentFileObject = NULL;
        }
        if (pTargetFileObject)
        {
                ObDereferenceObject(pTargetFileObject);
                pTargetFileObject = NULL;
        }
        if (pCurrentProcessNameInformation)
        {
                ExFreePoolWithTag(pCurrentProcessNameInformation, '0');
                pCurrentProcessNameInformation = NULL;
        }
        if (pTargetProcessNameInformation)
        {
                ExFreePoolWithTag(pTargetProcessNameInformation, '0');
                pTargetProcessNameInformation = NULL;
        }
        if (bDenied)
        {
                ntStatus = STATUS_ACCESS_DENIED;
        }
        else
        {
                if (g_HookInfomation.pOringinalSecurityProcedureAddress)
                {
                        ntStatus = g_HookInfomation.pOringinalSecurityProcedureAddress(
                                Object, OperationCode, SecurityInformation, SecurityDescriptor, CapturedLength,
                                ObjectsSecurityDescriptor, PoolType, GenericMapping, Flag);
                }
        }

        return ntStatus;

}

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

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)(*PsProcessType);
        g_HookInfomation.pOringinalSecurityProcedureAddress =
                (PSECURITY_PROCEDURE)(((POBJECT_TYPE_EX)(*PsProcessType))->TypeInfo.SecurityProcedure);
        InterlockedExchangePointer(
                (PVOID*)(&g_HookInfomation.pHookedObject->TypeInfo.SecurityProcedure),
                CustomQuerySecurityProcedure);
        KDPRINT("【ObjectTypeHook】", "Hook QueryNameProcedure!\r\n");
        return ntStatus;
}

  代码实现了任务管理器进程 Taskmgr.exe 打开 DbgView64.exe 时 SecurityProcedure 返回拒绝访问,也即 ObpCreateHandle 返回失败。

 

4.2 实验效果

  加载驱动后打开 DbgView64.exe, 然后在进程管理器中结束该进程,效果如下:

  

  

 

标签:ULONG,Windows,TYPE,OBJECT,Hook,ntStatus,PVOID,SecurityProcedure
From: https://www.cnblogs.com/ImprisonedSoul/p/17814589.html

相关文章

  • VMWare中Red Hat Enterprise Linux 6与Windows XP共享文件夹/共享目录
    虚拟机linux与widows主机的进行文件共享1.安装vmtoolsforlinux注意:如果Linux中已经装载有ISO文件,要先Eject。选择linux虚拟机--右键--installVMwaretools...选择linux虚拟机--右键–settings >CD-ROM>Edit>USEISOImage-选择vmware安装目录中linux.iso(注:如......
  • 怎样取消Windows 2003 server 意外关机提示
    怎样取消Windows2003server意外关机提示取消系统关机原因方法:(1)打开“开始”--“运行”命令,打开一个运行对话框,在其中输入“gpedit.msc”命令,来弹出组策略编辑界面。按回车后打开组策略编辑器。(2)在该界面中,用鼠标左键双击“计算机配置”文件夹----“管理模板”文件夹----“......
  • QEMU for windows
    QEMUDownloadQEMU-QEMUQEMUcanbeinstalledusingMSYS2also.MSYS2usespacmantomanagepackages.First,followtheMSYS2installationprocedure.Thenupdatethepackageswithpacman-Syucommand.Nowchoosethepropercommandforyoursystemasfol......
  • windows环境charles过期处理方法
    首先进行reset删除原来的证书 输入mmc->文件>添加删除管理单元->找到相关证书进行删除  重复安装证书,手机再次下载安装新证书即可......
  • Redis 下载与安装 Windows版教程
    ​ 1、下载windows版本的redis由于redis官方更支持我们使用Linux版本;可以下载微软官方维护的支持 Windows平台的Redis安装包下载地址:Releases·microsoftarchive/redis·GitHubtporadowski大神也提供了支持Windows平台的Redis 安装包,目前仍在维护,目前最新版本......
  • 计算机配置 — 管理模板 — Windows 组件 — 数据收集和预览版本 对应 注册表 位置
    @echooff::切换对预览体验成员内部版本的用户控制regadd"HKLM\SOFTWARE\Policies\Microsoft\WindowsPreviewBuilds"/vAllowBuildPreview/tREG_DWORD/d1/f::允许商业数据管道regadd"HKLM\SOFTWARE\Policies\Microsoft\Windows\DataCollection"/vCommerc......
  • conda环境导入到新的windows 10遇到的问题
    执行condaenvcreate-ffilename.yaml报错Nopackagesfoundincurrentwin-64channelsmatching:ca-certificates2023.01.10haa95532_0删除掉这行,执行还是会报错找不到下一行的包然后执行ca-certificates2023.01.10haa95532_0ca-certificates2023.01.10haa95532......
  • Windows、Linux 和 Mac三个操作系统之间的对比来啦
    Windows系统、Linux系统与Mac系统:操作系统的对比与选择操作系统是管理和控制计算机硬件与软件资源的计算机程序,是直接运行在“裸机”上的最基本的系统软件,任何其他软件都必须在操作系统的支持下才能运行。操作系统是用户和计算机的接口,同时也是计算机硬件和其他软件的接口。以下是W......
  • windows下nginx 配置 开机自启动
    一、windows系统下Nginx安装启动流程:二、设置Nginx开机自动启动1、自启动工具下载2、自启动工具安装3、把nginx加入到windows服务中最后一句话一、windows系统下Nginx安装启动流程:这是我们在正常环境中,Windows下Nginx的安装及启动方式1、到nginx官网下载相应版本(http://nginx.org......
  • Metasploit windows 调试环境搭建
    Metasploitwindows调试环境搭建安装ruby首先确定metasploit的ruby版本metasploit-framework/.ruby-version3.0.5在https://rubyinstaller.org/downloads/archives/下载对应版本的Ruby+DevkitInstallers(x64),默认配置安装即可。输入ruby-v查看是否安装成功安装gem......