• Windows ObjectType Hook 之 ParseProcedure


    1、背景

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

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

      这里进行的 Hook 为 其中之一的 ParseProcedure。文章实现注册表 Key 对象的过滤。

    2、ParseProcedure 函数声明

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

      这里取 x64 环境下结构:

    1. typedef NTSTATUS (*OB_PARSE_METHOD)(
    2. IN PVOID ParseObject,
    3. IN PVOID ObjectType,
    4. IN OUT PACCESS_STATE AccessState,
    5. IN KPROCESSOR_MODE AccessMode,
    6. IN ULONG Attributes,
    7. IN OUT PUNICODE_STRING CompleteName,
    8. IN OUT PUNICODE_STRING RemainingName,
    9. IN OUT PVOID Context OPTIONAL,
    10. IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
    11. OUT PVOID *Object
    12. );

      在Win11 x64 环境下结构如下:

    1. typedef NTSTATUS (*OB_PARSE_METHOD)(
    2. IN PVOID ParseObject,
    3. IN PVOID ObjectType,
    4. IN OUT PACCESS_STATE AccessState,
    5. IN KPROCESSOR_MODE AccessMode,
    6. IN ULONG Attributes,
    7. IN OUT PUNICODE_STRING CompleteName,
    8. IN OUT PUNICODE_STRING RemainingName,
    9. IN OUT PVOID Context OPTIONAL,
    10. IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
    11. IN POB_EXTENDED_PARSE_PARAMETERS Paramters, //Win 11上有这个参数
    12. OUT PVOID *Object
    13. );

    3、Key 对象过滤

    3.1 实验目标

      这里实现对注册表 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run 键值过滤,达到不能打开该键的逻辑。

    3.2 实现逻辑

      经过实验分析以及在小节 2 中的结构声明,对于路径的判断可以先用 ObQueryNameString 查询参数 ParseObject,得到一个路径。 

      但该路径并不一定是完整的全路径,需要再附加上参数 RemainingName 所对应的路径,加上该路径后的就是完整的全路径。

      Key对象的指针是导出的,可以直接使用,名称为 CmKeyObjectType, 也可以参考 《遍历Windows内核ObjectType》来获取。

    3.3 实现代码

    1. #if DBG
    2. #define KDPRINT(projectName, format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,\
    3. projectName "::【" __FUNCTION__ "】" ##format, \
    4. ##__VA_ARGS__ )
    5. #else
    6. #define KDPRINT(format, ...)
    7. #endif
    8. typedef struct _OBJECT_TYPE_FLAGS {
    9. UCHAR CaseInsensitive : 1;
    10. UCHAR UnnamedObjectsOnly : 1;
    11. UCHAR UseDefaultObject : 1;
    12. UCHAR SecurityRequired : 1;
    13. UCHAR MaintainHandleCount : 1;
    14. UCHAR MaintainTypeList : 1;
    15. UCHAR SupportsObjectCallbacks : 1;
    16. UCHAR CacheAligned : 1;
    17. }OBJECT_TYPE_FLAGS, * P_OBJECT_TYPE_FLAGS;
    18. typedef struct _OB_EXTENDED_PARSE_PARAMETERS
    19. {
    20. USHORT Length;
    21. ULONG RestrictedAccessMask;
    22. PVOID Silo;
    23. }OB_EXTENDED_PARSE_PARAMETERS, *POB_EXTENDED_PARSE_PARAMETERS;
    24. typedef struct _OBJECT_TYPE_INITIALIZER {
    25. USHORT wLength;
    26. OBJECT_TYPE_FLAGS ObjectTypeFlags;
    27. ULONG ObjcetTypeCode;
    28. ULONG InvalidAttributes;
    29. GENERIC_MAPPING GenericMapping;
    30. ULONG ValidAccessMask;
    31. ULONG RetainAccess;
    32. ULONG PoolType;
    33. ULONG DefaultPagedPoolCharge;
    34. ULONG DefaultNonPagedPoolCharge;
    35. PVOID DumpProcedure;
    36. PVOID OpenProcedure;
    37. PVOID CloseProcedure;
    38. PVOID DeleteProcedure;
    39. union
    40. {
    41. PVOID ParseProcedure;
    42. PVOID ParseProcedureEx;
    43. };
    44. PVOID SecurityProcedure;
    45. PVOID QueryNameProcedure;
    46. PVOID OkayToCloseProcedure;
    47. }OBJECT_TYPE_INITIALIZER, * POBJECT_TYPE_INITIALIZER;
    48. typedef struct _OBJECT_TYPE_EX {
    49. LIST_ENTRY TypeList;
    50. UNICODE_STRING Name;
    51. ULONGLONG DefaultObject;
    52. ULONG Index;
    53. ULONG TotalNumberOfObjects;
    54. ULONG TotalNumberOfHandles;
    55. ULONG HighWaterNumberOfObjects;
    56. ULONG HighWaterNumberOfHandles;
    57. OBJECT_TYPE_INITIALIZER TypeInfo;
    58. ULONGLONG TypeLock;
    59. ULONG Key;
    60. LIST_ENTRY CallbackList;
    61. }OBJECT_TYPE_EX, * POBJECT_TYPE_EX;
    62. typedef enum _OB_OPEN_REASON {
    63. ObCreateHandle,
    64. ObOpenHandle,
    65. ObDuplicateHandle,
    66. ObInheritHandle,
    67. ObMaxOpenReason
    68. } OB_OPEN_REASON;
    69. typedef
    70. NTSTATUS
    71. (NTAPI* PPARSE_PROCEDURE_EX)(
    72. IN PVOID ParseObject,
    73. IN POBJECT_TYPE ObjectType,
    74. IN OUT PACCESS_STATE AccessState,
    75. IN CHAR Flag,
    76. IN ULONG Attributes,
    77. IN OUT PUNICODE_STRING CompleteName,
    78. IN OUT PUNICODE_STRING RemainingName,
    79. IN OUT PVOID Context OPTIONAL,
    80. IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
    81. IN POB_EXTENDED_PARSE_PARAMETERS Paramters, //Win 11上有这个参数
    82. OUT PVOID* Object
    83. );
    84. typedef struct _OBJECT_TYPE_HOOK_INFORMATION
    85. {
    86. POBJECT_TYPE_EX pHookedObject;
    87. PPARSE_PROCEDURE_EX pOringinalParseProcedureAddress;
    88. }OBJECT_TYPE_HOOK_INFORMATION, * POBJECT_TYPE_HOOK_INFORMATION;
    89. OBJECT_TYPE_HOOK_INFORMATION g_HookInfomation = { 0 };
    90. UNICODE_STRING g_usRunKeyName =
    91. RTL_CONSTANT_STRING(L"*\\REGISTRY\\MACHINE\\SOFTWARE\\MICROSOFT\\WINDOWS\\CURRENTVERSION\\RUN*");
    92. UNICODE_STRING g_usSeperator = RTL_CONSTANT_STRING(L"\\");
    93. NTSTATUS
    94. NTAPI
    95. CustomKeyParseProcedure(
    96. IN PVOID ParseObject,
    97. IN POBJECT_TYPE ObjectType,
    98. IN OUT PACCESS_STATE AccessState,
    99. IN CHAR Flag,
    100. IN ULONG Attributes,
    101. IN OUT PUNICODE_STRING CompleteName,
    102. IN OUT PUNICODE_STRING RemainingName,
    103. IN OUT PVOID Context OPTIONAL,
    104. IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
    105. IN POB_EXTENDED_PARSE_PARAMETERS Paramters,
    106. OUT PVOID* Object)
    107. {
    108. NTSTATUS ntStatus = STATUS_SUCCESS;
    109. ULONG ulRet = 0;
    110. BOOLEAN bFilterKey = false;
    111. if (ParseObject && (ObjectType == *CmKeyObjectType))
    112. {
    113. POBJECT_NAME_INFORMATION pName = (POBJECT_NAME_INFORMATION)ExAllocatePoolWithTag(
    114. NonPagedPool, 1024, 'Mut');
    115. if (pName)
    116. {
    117. ntStatus = ObQueryNameString(ParseObject, pName, 1024, &ulRet);
    118. if (NT_SUCCESS(ntStatus))
    119. {
    120. //KDPRINT("【ObjectTypeHook】", "ParseObject is %wZ\r\n", &pName->Name);
    121. if (RemainingName)
    122. {
    123. //KDPRINT("【ObjectTypeHook】", "CompleteName is %wZ\r\n", CompleteName);
    124. //KDPRINT("【ObjectTypeHook】", "RemainingName is %wZ\r\n", RemainingName);
    125. pName->Name.MaximumLength = 1024 - sizeof(UNICODE_STRING);
    126. RtlAppendUnicodeStringToString(&pName->Name, &g_usSeperator);
    127. ntStatus = RtlAppendUnicodeStringToString(&pName->Name, RemainingName);
    128. if (NT_SUCCESS(ntStatus))
    129. {
    130. if (FsRtlIsNameInExpression(&g_usRunKeyName, &pName->Name, true, NULL))
    131. {
    132. KDPRINT("【ObjectTypeHook】", "Need Filter Key Path Is %wZ\r\n", &pName->Name);
    133. KDPRINT("【ObjectTypeHook】", "Denied Process Id is 0x%08d\r\n", PsGetCurrentProcessId());
    134. bFilterKey = true;
    135. }
    136. }
    137. }
    138. }
    139. ExFreePoolWithTag(pName, 'name');
    140. }
    141. }
    142. if (bFilterKey)
    143. {
    144. return STATUS_ACCESS_DENIED;
    145. }
    146. else
    147. {
    148. ntStatus = STATUS_SUCCESS;
    149. if (g_HookInfomation.pOringinalParseProcedureAddress)
    150. {
    151. ntStatus = g_HookInfomation.pOringinalParseProcedureAddress(
    152. ParseObject, ObjectType, AccessState, Flag, Attributes, CompleteName, RemainingName, Context,
    153. SecurityQos, Paramters, Object);
    154. }
    155. return ntStatus;
    156. }
    157. }
    158. void UnHookObjectType()
    159. {
    160. KDPRINT("【ObjectTypeHook】", "UnHook...\r\n");
    161. if (g_HookInfomation.pHookedObject)
    162. {
    163. InterlockedExchangePointer(
    164. (PVOID*)(&g_HookInfomation.pHookedObject->TypeInfo.ParseProcedure),
    165. g_HookInfomation.pOringinalParseProcedureAddress);
    166. }
    167. }
    168. VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
    169. {
    170. UNREFERENCED_PARAMETER(pDriverObject);
    171. KDPRINT("【ObjectTypeHook】", "CurrentProcessId : 0x%p CurrentIRQL : 0x%u \r\n",
    172. PsGetCurrentProcessId(),
    173. KeGetCurrentIrql());
    174. UnHookObjectType();
    175. }
    176. EXTERN_C NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,
    177. PUNICODE_STRING pRegistryPath)
    178. {
    179. UNREFERENCED_PARAMETER(pDriverObject);
    180. UNREFERENCED_PARAMETER(pRegistryPath);
    181. NTSTATUS ntStatus = STATUS_SUCCESS;
    182. KDPRINT("【ObjectTypeHook】", " Hello Kernel World! CurrentProcessId:0x%p CurrentIRQL:0x%u\r\n",
    183. PsGetCurrentProcessId(),
    184. KeGetCurrentIrql());
    185. pDriverObject->DriverUnload = DriverUnload;
    186. g_HookInfomation.pHookedObject = (POBJECT_TYPE_EX)(*CmKeyObjectType);
    187. g_HookInfomation.pOringinalParseProcedureAddress =
    188. (PPARSE_PROCEDURE_EX)(((POBJECT_TYPE_EX)(*CmKeyObjectType))->TypeInfo.ParseProcedure);
    189. InterlockedExchangePointer(
    190. (PVOID*)(&g_HookInfomation.pHookedObject->TypeInfo.ParseProcedure),
    191. CustomKeyParseProcedure);
    192. return ntStatus;
    193. }

    3.4 实现效果

      安装驱动后去打开注册表 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run 键,效果如下:

  • 相关阅读:
    走进乌镇峰会,《个人信息保护法》实施一周年实践与展望
    Qt 开发使用VSCode
    自动驾驶学习笔记(六)——Apollo安装
    两段锁协议
    Windows下配置MySQL源码调试环境
    【组成原理-总线】总线的概念和计算
    华为常用命令
    刘二大人 PyTorch深度学习实践 笔记 P6 逻辑斯蒂回归
    如何用Excel做最小二乘法②
    蓝桥杯:模拟、枚举
  • 原文地址:https://blog.csdn.net/zhuting__xf/article/details/134178149