Windows ObjectType Hook 之 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, 然后在进程管理器中结束该进程,效果如下:

  

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

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

相关文章

图神经网络 (GNN)

目录 一、GNN介绍1.1引入1.1.1图的介绍1.1.2怎样将内容表示成图1.1.4图神经网络是在做什么 1.2基本概念 二、GNN流程2.1聚合2.2更新2.2.1一次GNN操作 2.3循环2.3.1多层GNN操作2.3.2能做什么 三、GNN算法原理3.1数据3.2变量定义3.3GNN算法3.3.1Forward3.3.2Backward 四、GNN优势…

使用idea插件快速生成arthas命令

这里分享一个插件&#xff0c;叫做arthas idea。 这个插件我主要是用来在本地生成一些要使用的arthas命令&#xff0c;然后复制到线上使用&#xff0c;这样可以避免记忆大量的arthas命令&#xff0c;加速排查效率&#xff0c;不过哪种情况要用哪些arthas命令&#xff0c;还是需…

直播间自动评论神器的运行分享,与开发需要到的技术分析

先来看实操成果&#xff0c;↑↑需要的同学可看我名字↖↖↖↖↖&#xff0c;或评论888无偿分享 随着互联网的发展&#xff0c;直播带货越来越受欢迎。为了更好地服务观众&#xff0c;许多直播间开始使用自动回复机器人。本文将介绍直播间自动回复机器人需要用到的技术和流程。…

合成数据如何改变制造业

人工智能正在工厂车间使用&#xff0c;以识别生产线中的低效率。它可以有效地预测设备何时需要维护&#xff0c;以避免停机。人工智能被用于发现产品中的缺陷。 为了完成所有这些工作&#xff0c;使用从人工智能应该学习的过程中收集的数据来创建或训练模型。对于缺陷识别&…

如何将NetCore Web程序独立发布部署到Linux服务器

简介 在将 .NET Core 应用程序部署到 Linux 服务器上时,可以采用独立发布的方式,以便在目标服务器上运行应用程序而无需安装 .NET Core 运行时。本文介绍如果将NetCore Web程序独立发布部署到Linux服务器。 1、准备一台服务器 服务器配置:2核2G 系统环境:Alibaba Cloud…

如果有一款专门用于3D纹理贴图的工具,大家会愿意用吗?

专业建模软件通常具有丰富的功能和工具&#xff0c;能够帮助用户进行三维建模、模拟分析、可视化呈现等多个方面的工作&#xff0c;几乎可满足用户所有的建模相关工作。 1、专业建模软件的使用门槛 学习曲线陡峭&#xff1a;专业建模软件通常需要较长时间来学习和掌握&#xf…

图论10-哈密尔顿回路和哈密尔顿路径+状态压缩+记忆化搜索

文章目录 1 哈密尔顿回路2 哈密尔顿回路算法实现2.1 常规回溯算法2.2 引入变量记录剩余未访问的节点数量 3 哈密尔顿路径问题4 状态压缩4.1 查看第i位是否为14.2 设置第i位是为1或者04.3 小结4.4 状态压缩在哈密尔顿问题中的应用 5 记忆化搜索5.1 记忆化搜索与递推区别5.2 记忆…

【Unity细节】Failed importing package???Unity导包失败?

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 &#x1f636;‍&#x1f32b;️收录于专栏&#xff1a;unity细节和bug &#x1f636;‍&#x1f32b;️优质专栏 ⭐【…

阿里云服务器怎么样?阿里云服务器优势、价格及常见问题介绍

阿里云&#xff08;Alibaba Cloud&#xff09;是阿里巴巴集团旗下的云计算服务提供商&#xff0c;其提供的云服务器&#xff08;ECS&#xff09;是其核心服务之一。在云计算市场中&#xff0c;阿里云服务器备受用户的青睐&#xff0c;那么&#xff0c;阿里云服务器究竟怎么样呢…

现在个人想上架微信小游戏已经这么难了吗...

点击上方亿元程序员关注和★星标 引言 大家好&#xff0c;最近我突然想起来我还有一款微信小游戏还没有上架&#xff0c;于是捣鼓了一天把游戏完善了一下&#xff0c;然后准备提交审核&#xff0c;却发现异常的艰难… 1.为什么难&#xff1f; 相信大家都大概知道&#xff0c…

基于SSM的数据结构课程网络学习平台

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

基于SpringBoot的SSMP整合案例(实体类开发与数据层开发)

实体类开发 导入依赖 Lombok&#xff0c;一个Java类库&#xff0c;提供了一组注解&#xff0c;简化POJO实体类开发<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId> </dependency>lombok版本由SpringB…

02MyBatisPlus条件构造器,自定义SQL,Service接口

一、条件构造器 1.MyBatis支持各种复杂的where条件&#xff0c;满足开发的需求 Wrapper是条件构造器&#xff0c;构建复杂的where查询 AbstractWrapper有构造where条件的所有方法&#xff0c;QueryWrapper继承后并有自己的select指定查询字段。UpdateWrapper有指定更新的字段的…

c: CLion 2023.1.1

/** # encoding: utf-8 # 版权所有 2023 涂聚文有限公司 # 许可信息查看&#xff1a;https://www.learnc.net/c-data-structures/c-linked-list/ # 描述&#xff1a;https://blog.jetbrains.com/clion/2016/05/keep-your-code-documented/ # Author : geovindu,Geovin Du 涂…

将VS工程转为pro工程及VS安装Qt插件后没有create basic .pro file菜单问题解决

目录 1. 前言 2. VS工程转为pro工程 3. 没有create basic .pro file菜单 1. 前言 很多小伙伴包括本人&#xff0c;如果是在Windows下开发Qt程序&#xff0c;偏好用Visual Studio外加装个Qt插件进行Qt开发&#xff0c;毕竟Visual Studio确实是功能强大的IDE&#xff0c;但有时…

【Truffle】四、通过Ganache部署连接

目录 一、下载安装 Ganache&#xff1a; 二、在本地部署truffle 三、配置ganache连接truffle 四、交易发送 除了用Truffle Develop&#xff0c;还可以选择使用 Ganache, 这是一个桌面应用&#xff0c;他同样会创建一个个人模拟的区块链。 对于刚接触以太坊的同学来说&#x…

LeetCode16的最接近的三数之和

目录 优化解法暴力搜索 优化解法 看了题解之后的根据题解的意思编写的优化解法,感觉还行,代码算是比较简短了,没有复杂的逻辑,就是写的时候总是只记得记录那个sum,忘记要记录最小的差值,更新min_minus. class Solution {public int threeSumClosest(int[] nums, int target) {…

NLP领域的突破催生大模型范式的形成与发展

当前的大模型领域的发展&#xff0c;只是范式转变的开始&#xff0c;基础大模型才刚刚开始改变人工智能系统在世界上的构建和部署方式。 1、大模型范式 1.1 传统思路&#xff08;2019年以前&#xff09; NLP领域历来专注于为具有挑战性的语言任务定义和设计系统&#xff0c…

【算法与数据结构】93、LeetCode复原 IP 地址

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;参照【算法与数据结构】131、LeetCode分割回文串的思路&#xff0c;需要将IP字符串进行分割&#xff0…

“基于RflySim平台飞控底层算法开发”系列专题培训 (第三期)

>> RflySim平台系列专题培训 RflySim平台是一个生态系统或工具链&#xff08;官网&#xff1a;https://doc.rflysim.com&#xff09;&#xff0c;发起于北航可靠飞行控制研究组&#xff0c;主要用于遵循基于模型设计的思想进行无人系统的控制和安全测试。本平台选择MATL…
最新文章