Windows ObjectType Hook 之 SecurityProcedure

news2024/10/2 18:20:43

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.coloradmin.cn/o/1180142.html

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

相关文章

CDS(Core Data Service)Annotation 常用属性

1. 抬头信息 @UI: {headerInfo: {typeName: BP,typeNamePlural: BP,title:{type: #STANDARD, value:ApplyNumber},description:{value:Status}} }2. 行信息/分组 @UI.facet: [{id: bp_Tab1,purpose: #STANDARD,type: #FIELDGROUP_REFERENCE,// type: #LINEITEM_REFERENCE,labe…

【Linux】 OpenSSH_7.4p1 升级到 OpenSSH_9.4p1(亲测无问题,建议收藏)

&#x1f468;‍&#x1f393;博主简介 &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01; &#x1f40b; 希望大家多多支…

lazarus:不安装任何驱动,直接使用csv文件作为数据集

目录 1 简介 2 需要的窗体控件很简单 3 定义字段并插入几条记录 4 其他操作 4.1 数据集保存为csv文件 4.2 清空数据 4.3 加载csv文件 5 运行程序 6 导出文件 1 简介 在某些数据操作需求特别简单的情况下&#xff0c;我们希望不要安装任何数据库&#xff0c;甚至连一个…

餐饮加盟信息展示预约小程序的内容如何

餐饮业规模持续增加&#xff0c;相关从业者逐渐增多&#xff0c;对中等规模以上的餐饮品牌来说&#xff0c;当有一定规模后除了开多家直营店外&#xff0c;还会开放招商加盟&#xff0c;扩展品牌、提升营收等。 由于餐饮加盟属于准属性业务&#xff0c;因此传统线下方式不太适…

投资理财:买理财亏损不保本怎么办?

大家好&#xff0c;我是财富智星&#xff0c;今天跟大家讨论一下投资理财&#xff0c;银行理财亏损不保本了&#xff0c;普通老百姓应该怎么办&#xff1f; 银行理财已经不再是保本且没有风险的产品了。对于追求稳健增值的大多数普通人来说&#xff0c;银行理财已经不再是他们的…

Python TCP服务端多线程接收RFID网络读卡器上传数据

本示例使用设备介绍&#xff1a;WIFI/TCP/UDP/HTTP协议RFID液显网络读卡器可二次开发语音播报POE-淘宝网 (taobao.com) #python通过缩进来表示代码块&#xff0c;不可以随意更改每行前面的空白&#xff0c;否则程序会运行错误&#xff01;&#xff01;&#xff01;如果缩进不…

「Verilog学习笔记」使用generate…for语句简化代码

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 分析 generate…for语句是Verilog HDL语言特有的语句&#xff0c;使用循环结构编写可综合的多个形式相近的代码&#xff0c;循环变量必须由特定关键字genvar声明。 timesca…

IDEA Plugin插件开发相关踩坑

1 前言 最近在研究IDEA插件开发&#xff0c;踩了不少坑&#xff0c;特意在这里记录一下…… 2 Java相关类找不到 照着网上一些资料&#xff0c;想要实现代码审计自动提示功能&#xff0c;需要继承AbstractBaseJavaLocalInspectionTool 结果import一片爆红&#xff0c;找不到相…

StackOverflow调查:2021-2022薪酬最高的编程语言

我应该学习哪种编程语言&#xff1f; 对于有抱负的软件工程师来说&#xff0c;这是最常见的问题&#xff0c;答案始终是&#xff1a;这取决于您的偏好以及您想要构建的内容。 但也许您想采取另一条路线并学习公司为您支付最高费用的语言。 如果是这样的话&#xff0c;这篇文章适…

GPT-2:基于无监督多任务学习的语言模型

欢迎来到魔法宝库&#xff0c;传递AIGC的前沿知识&#xff0c;做有格调的分享❗ 喜欢的话记得点个关注吧&#xff01; 今天&#xff0c;我们将共同探索OpenAI的GPT-2&#xff0c;跟随论文深入理解其技术细节。 论文&#xff1a;Language Models are Unsupervised Multitask Le…

ORACLE数据库初始化导入

ORACLE数据库初始化导入 文章目录 ORACLE数据库初始化导入创建表空间创建用户用户授权临时目录授权数据库目录授权导入dump文件 环境&#xff1a;linux 数据库&#xff1a;oracle 19c 创建表空间 -- 查询已创建目录 select directory_path,directory_name from all_directori…

Redis之与SSM集成Spring注解式缓存

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《Redis实战开发》。&#x1f3af;&#x1f3af; …

大数据学习之Spark性能优化

文章目录 Spark三种任务提交模式宽依赖和窄依赖StageSpark Job的三种提交模式 Shuffle机制分析未优化的Hash Based Shuffle优化后的Hash Based ShuffleSort-Based Shuffle Spark之checkpointcheckpoint概述checkpoint与持久化的区别checkPoint的使用checkpoint源码分析 Spark程…

vue前端实现多个url下载并合并为zip文件

一、安装 npm install jszip npm install file-saver 二、引入 import axios from axios import JSZip from "jszip"; import FileSaver from "file-saver"; 三、核心代码 videoData:[/video/26519f026fc012521605563015227403.mp4,/video/f7b9cdae14…

聊聊芯片超净间的颗粒(particle)

在芯片制造领域&#xff0c;颗粒的存在可能对生产过程产生巨大影响。其中&#xff0c;每个微小的颗粒&#xff0c;无论是来自人员、设备&#xff0c;还是自然环境&#xff0c;都有可能在制程中引发故障&#xff0c;从而对产品性能产生负面影响。这就是为什么在芯片厂中&#xf…

【日积月累】SpringBoot 通过注解@CacheConfig @Cacheable @CacheEvict @CachePut @Caching使用缓存

目录 1.前言2.引入依赖3.启动类加入注解EnableCaching4.常用注解4.1CacheConfig4.2Cacheable4.3CacheEvict4.4CachePut4.5Caching 5.总结6.参考 文章所属专区 日积月累 1.前言 Spring在3.1版本&#xff0c;就提供了一条基于注解的缓存策略&#xff0c;实际使用起来还是很丝滑…

【内功修炼】详解函数栈帧的创建和销毁

文章目录 1. 什么是函数栈帧2. 理解函数栈帧能解决什么问题呢&#xff1f;3. 函数栈帧的创建和销毁解析3.1 什么是栈&#xff1f;3.2 认识相关寄存器和汇编指令常见寄存器常用汇编指令 3.3 详解函数栈帧的创建和销毁3.3.1 函数的调用堆栈&#xff08;main函数也是被其它函数调用…

手握“发展密钥”,TCL科技或迎价值重估?

在高度竞争且快速变化的泛半导体产业&#xff0c;每一次周期性或结构性的变化&#xff0c;都会对企业经营策略带来深远的影响。 2023年前三季度&#xff0c;泛半导体产业迎来结构性复苏。其中&#xff0c;主流显示领域供需关系趋向健康化&#xff0c;半导体显示行业整体上量价…

C语言 每日一题 PTA 11.7 day13

1.求e的近似值 自然常数 e 可以用级数 1 1 / 1! 1 / 2! ⋯ 1 / n! ⋯ 来近似计算。 本题要求对给定的非负整数 n&#xff0c;求该级数的前 n 1 项和。 代码实现 #include<stdio.h> void main() {int a, i, j; double b 1; double c 1;printf("请输入一个数\n…

零信任安全:构建无懈可击的网络防护体系

随着网络技术的飞速发展&#xff0c;信息安全问题日益凸显&#xff0c;传统的安全防护手段已经无法满足复杂多变的安全需求。在此背景下&#xff0c;零信任安全模型逐渐受到广泛关注。本文将探讨零信任安全的概念、优势以及如何构建无懈可击的网络防护体系。 一、零信任安全概念…