Object Type Hook 是基于 Object Type的一种深入的 Hook,比起常用的 SSDT Hook 更为深入。
有关 Object Type 的分析见文章 《Windows驱动开发学习记录-ObjectType Hook之ObjectType结构相关分析》。
这里进行的 Hook 为 其中之一的 ParseProcedure。文章实现注册表 Key 对象的过滤。
见文章 《Windows驱动开发学习记录-ObjectType Hook之ObjectType结构相关分析》。
这里取 x64 环境下结构:
- typedef NTSTATUS (*OB_PARSE_METHOD)(
- IN PVOID ParseObject,
- IN PVOID ObjectType,
- IN OUT PACCESS_STATE AccessState,
- IN KPROCESSOR_MODE AccessMode,
- IN ULONG Attributes,
- IN OUT PUNICODE_STRING CompleteName,
- IN OUT PUNICODE_STRING RemainingName,
- IN OUT PVOID Context OPTIONAL,
- IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
- OUT PVOID *Object
- );
在Win11 x64 环境下结构如下:
- typedef NTSTATUS (*OB_PARSE_METHOD)(
- IN PVOID ParseObject,
- IN PVOID ObjectType,
- IN OUT PACCESS_STATE AccessState,
- IN KPROCESSOR_MODE AccessMode,
- IN ULONG Attributes,
- IN OUT PUNICODE_STRING CompleteName,
- IN OUT PUNICODE_STRING RemainingName,
- IN OUT PVOID Context OPTIONAL,
- IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
- IN POB_EXTENDED_PARSE_PARAMETERS Paramters, //Win 11上有这个参数
- OUT PVOID *Object
- );
这里实现对注册表 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run 键值过滤,达到不能打开该键的逻辑。
经过实验分析以及在小节 2 中的结构声明,对于路径的判断可以先用 ObQueryNameString 查询参数 ParseObject,得到一个路径。
但该路径并不一定是完整的全路径,需要再附加上参数 RemainingName 所对应的路径,加上该路径后的就是完整的全路径。
Key对象的指针是导出的,可以直接使用,名称为 CmKeyObjectType, 也可以参考 《遍历Windows内核ObjectType》来获取。
- #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;
-
- typedef struct _OB_EXTENDED_PARSE_PARAMETERS
- {
- USHORT Length;
- ULONG RestrictedAccessMask;
- PVOID Silo;
- }OB_EXTENDED_PARSE_PARAMETERS, *POB_EXTENDED_PARSE_PARAMETERS;
-
- 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;
- union
- {
- PVOID ParseProcedure;
- PVOID ParseProcedureEx;
- };
-
- PVOID SecurityProcedure;
- PVOID QueryNameProcedure;
- PVOID OkayToCloseProcedure;
- }OBJECT_TYPE_INITIALIZER, * POBJECT_TYPE_INITIALIZER;
-
- typedef struct _OBJECT_TYPE_EX {
- LIST_ENTRY TypeList;
- UNICODE_STRING Name;
- ULONGLONG 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;
-
-
- typedef enum _OB_OPEN_REASON {
- ObCreateHandle,
- ObOpenHandle,
- ObDuplicateHandle,
- ObInheritHandle,
- ObMaxOpenReason
- } OB_OPEN_REASON;
-
- typedef
- NTSTATUS
- (NTAPI* PPARSE_PROCEDURE_EX)(
- IN PVOID ParseObject,
- IN POBJECT_TYPE ObjectType,
- IN OUT PACCESS_STATE AccessState,
- IN CHAR Flag,
- IN ULONG Attributes,
- IN OUT PUNICODE_STRING CompleteName,
- IN OUT PUNICODE_STRING RemainingName,
- IN OUT PVOID Context OPTIONAL,
- IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
- IN POB_EXTENDED_PARSE_PARAMETERS Paramters, //Win 11上有这个参数
- OUT PVOID* Object
- );
-
- typedef struct _OBJECT_TYPE_HOOK_INFORMATION
- {
- POBJECT_TYPE_EX pHookedObject;
- PPARSE_PROCEDURE_EX pOringinalParseProcedureAddress;
- }OBJECT_TYPE_HOOK_INFORMATION, * POBJECT_TYPE_HOOK_INFORMATION;
-
- OBJECT_TYPE_HOOK_INFORMATION g_HookInfomation = { 0 };
- UNICODE_STRING g_usRunKeyName =
- RTL_CONSTANT_STRING(L"*\\REGISTRY\\MACHINE\\SOFTWARE\\MICROSOFT\\WINDOWS\\CURRENTVERSION\\RUN*");
- UNICODE_STRING g_usSeperator = RTL_CONSTANT_STRING(L"\\");
- NTSTATUS
- NTAPI
- CustomKeyParseProcedure(
- IN PVOID ParseObject,
- IN POBJECT_TYPE ObjectType,
- IN OUT PACCESS_STATE AccessState,
- IN CHAR Flag,
- IN ULONG Attributes,
- IN OUT PUNICODE_STRING CompleteName,
- IN OUT PUNICODE_STRING RemainingName,
- IN OUT PVOID Context OPTIONAL,
- IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
- IN POB_EXTENDED_PARSE_PARAMETERS Paramters,
- OUT PVOID* Object)
- {
- NTSTATUS ntStatus = STATUS_SUCCESS;
- ULONG ulRet = 0;
- BOOLEAN bFilterKey = false;
-
- if (ParseObject && (ObjectType == *CmKeyObjectType))
- {
- POBJECT_NAME_INFORMATION pName = (POBJECT_NAME_INFORMATION)ExAllocatePoolWithTag(
- NonPagedPool, 1024, 'Mut');
- if (pName)
- {
- ntStatus = ObQueryNameString(ParseObject, pName, 1024, &ulRet);
- if (NT_SUCCESS(ntStatus))
- {
- //KDPRINT("【ObjectTypeHook】", "ParseObject is %wZ\r\n", &pName->Name);
- if (RemainingName)
- {
- //KDPRINT("【ObjectTypeHook】", "CompleteName is %wZ\r\n", CompleteName);
- //KDPRINT("【ObjectTypeHook】", "RemainingName is %wZ\r\n", RemainingName);
- pName->Name.MaximumLength = 1024 - sizeof(UNICODE_STRING);
- RtlAppendUnicodeStringToString(&pName->Name, &g_usSeperator);
- ntStatus = RtlAppendUnicodeStringToString(&pName->Name, RemainingName);
-
- if (NT_SUCCESS(ntStatus))
- {
- if (FsRtlIsNameInExpression(&g_usRunKeyName, &pName->Name, true, NULL))
- {
- KDPRINT("【ObjectTypeHook】", "Need Filter Key Path Is %wZ\r\n", &pName->Name);
- KDPRINT("【ObjectTypeHook】", "Denied Process Id is 0x%08d\r\n", PsGetCurrentProcessId());
- bFilterKey = true;
- }
- }
- }
- }
- ExFreePoolWithTag(pName, 'name');
- }
- }
-
-
- if (bFilterKey)
- {
- return STATUS_ACCESS_DENIED;
- }
- else
- {
- ntStatus = STATUS_SUCCESS;
- if (g_HookInfomation.pOringinalParseProcedureAddress)
- {
- ntStatus = g_HookInfomation.pOringinalParseProcedureAddress(
- ParseObject, ObjectType, AccessState, Flag, Attributes, CompleteName, RemainingName, Context,
- SecurityQos, Paramters, Object);
- }
-
- return ntStatus;
- }
-
- }
-
- void UnHookObjectType()
- {
- KDPRINT("【ObjectTypeHook】", "UnHook...\r\n");
- if (g_HookInfomation.pHookedObject)
- {
- InterlockedExchangePointer(
- (PVOID*)(&g_HookInfomation.pHookedObject->TypeInfo.ParseProcedure),
- g_HookInfomation.pOringinalParseProcedureAddress);
- }
- }
-
- 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)(*CmKeyObjectType);
- g_HookInfomation.pOringinalParseProcedureAddress =
- (PPARSE_PROCEDURE_EX)(((POBJECT_TYPE_EX)(*CmKeyObjectType))->TypeInfo.ParseProcedure);
- InterlockedExchangePointer(
- (PVOID*)(&g_HookInfomation.pHookedObject->TypeInfo.ParseProcedure),
- CustomKeyParseProcedure);
- return ntStatus;
- }
安装驱动后去打开注册表 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run 键,效果如下:
