恢复句柄权限的方法

1.使用高度拦截在回调函数中恢复句柄权限

回调函数在系统中依次由高到低执行,查看回调函数的高度,此时注册一个回调函数只要高度比降低权限的回调低,就会形成先降低权限再提高权限。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include<ntifs.h>

PVOID RegistrationHandle = NULL;
BOOLEAN is_callback = FALSE;
HANDLE g_pid;
VOID uninstall_callback()
{
if (RegistrationHandle != NULL && is_callback)
ObUnRegisterCallbacks(RegistrationHandle);
}

//回调提升进程权限
OB_PREOP_CALLBACK_STATUS PobPreOperationCallbackUp(PVOID RegistrationContext,
POB_PRE_OPERATION_INFORMATION OperationInformation)
{
if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE && OperationInformation->ObjectType == *PsProcessType)
{

HANDLE cmpid = PsGetProcessId((PEPROCESS)OperationInformation->Object);
if (cmpid == *(PHANDLE)RegistrationContext)
{
DbgPrintEx(0, 0, "R0:inside 3\n");
PACCESS_MASK OriginalDesiredAccess = &OperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess;
PACCESS_MASK DesiredAccess = &OperationInformation->Parameters->CreateHandleInformation.DesiredAccess;
*DesiredAccess = 0x1fffff;
DbgPrintEx(0, 0, "R0:赋予读写权限成功\n");
}
}
return OB_PREOP_SUCCESS;
}

//回调拦截赋予进程所有权限
VOID install_callback(HANDLE pid)
{

//static PHANDLE pid=0;
//NTSTATUS status = GetProcessId_byName(pname,sizeof(pname),pid);
g_pid = pid;
if (!g_pid)
{
DbgPrintEx(0, 0, "pid ERROR\n");
return;
}
else
DbgPrintEx(0, 0, "Protect:%d\n", g_pid);
OB_CALLBACK_REGISTRATION obreg = { 0 };
OB_OPERATION_REGISTRATION opreg = { 0 };
obreg.Version = OB_FLT_REGISTRATION_VERSION;
obreg.OperationRegistrationCount = 1;
obreg.RegistrationContext = &g_pid;
RtlInitUnicodeString(&obreg.Altitude, L"322100");

opreg.ObjectType = PsProcessType;
opreg.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
opreg.PreOperation = PobPreOperationCallbackUp;
obreg.OperationRegistration = &opreg;

NTSTATUS status = ObRegisterCallbacks(&obreg, &RegistrationHandle);
if (NT_SUCCESS(status))
{
is_callback = TRUE;
}
else
DbgPrintEx(0, 0, "Install ObCallBack Error\n");

}
VOID DriverUnload(PDRIVER_OBJECT pDriverOBject)
{
uninstall_callback();
DbgPrintEx(0, 0, "Driver Unload Success!");
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{

pDriverObject->DriverUnload = DriverUnload;
DbgPrintEx(0, 0, "Driver Load Success!");
//回调验证签名
*(PULONG)((ULONG64)pDriverObject->DriverSection + 0x68) |= 0x20;
install_callback(6364);

return STATUS_SUCCESS;
}

2.替换回调函数入口点地址

在驱动程序中注册一个回调函数,再将此前找到的函数入口点替换为新的。

3. 将函数入口的第一个指令替换为ret(C3),如果有额外检测可能会蓝屏。

4.设置进程回调函数链表CallbackList中的OB_CALLBACK_ENTRY_t.Entry为0,这样此回调函数就无效了。

5.设置进程回调函数链表CallbackList为空,头尾指针相同达到清空回调函数的目的。

6.通过设置进程_OBJECT_TYPE的_OBJECT_TYPE_INITIALIZER.SupportsObjectCallbacks 字段为0,使进程对象不支持回调函数。

7.通过重新给被降权的句柄进行提权,OpenProcess后得到降权的句柄,然后驱动程序通过枚举句柄表修改此被降权句柄的GrantedAccessBits 达到提权的目的。

https://www.cnblogs.com/revercc/p/16931238.html

8.设置所有进程回调失效

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include<ntifs.h>

#ifdef DBG
#define DebugMessage(x, ...) DbgPrintEx(0, 0, "qi:" x, __VA_ARGS__)
#else
#define DebugMessage(x, ...) DbgPrintEx(0, 0, "qi:" x, __VA_ARGS__)
#endif

//设置所有进程回调失效
ULONG SetAccessAllProcess()
{
PVOID addr = (PVOID)((ULONG64)*PsProcessType + 0x40 + 0x20);
DebugMessage("%p\n", *(PULONG)addr);
*(PULONG)addr = 0x1fffff;
DebugMessage("%p\n", *(PULONG)addr);
return *(PULONG)addr;
}
//恢复所有进程回调
ULONG SetAccessAllProcessOff()
{
PVOID addr = (PVOID)((ULONG64)*PsProcessType + 0x40 + 0x20);
DebugMessage("%p\n", *(PULONG)addr);
*(PULONG)addr = 0x101000;
DebugMessage("%p\n", *(PULONG)addr);
return *(PULONG)addr;
}

VOID DriverUnload(PDRIVER_OBJECT pDriverOBject)
{
DbgPrintEx(0, 0, "Driver Unload Success!");
SetAccessAllProcessOff();
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{

pDriverObject->DriverUnload = DriverUnload;
DbgPrintEx(0, 0, "Driver Load Success!");
SetAccessAllProcess();

return STATUS_SUCCESS;
}

PsProcessType 是一个 全局导出的内核符号,代表 进程对象类型(Process 类型对象)在 Object Manager 中的结构定义

这个结构体由内核维护,其定义大致如下(实际内部结构未完全公开):

1
2
3
4
5
6
7
8
9
cCopyEdittypedef struct _OBJECT_TYPE {
ERESOURCE Mutex;
LIST_ENTRY TypeList;
UNICODE_STRING Name;
// ...
PVOID DefaultObject;
PSECURITY_DESCRIPTOR TypeInfo;
// 各种回调、标志、属性等
} OBJECT_TYPE, *POBJECT_TYPE;

猜测此代码目的

这种写法常用于 逆向或探索内核结构,典型用途包括:

  • 访问 OBJECT_TYPE_INITIALIZER 结构(它可能位于 OBJECT_TYPE 内部某偏移)
  • 获取其中的回调函数、属性、标志等字段

例如,在旧版本 Windows 中,OBJECT_TYPE_INITIALIZER 嵌套在 OBJECT_TYPE 中的偏移可能就是 0x40,而再加 0x20 是在访问该初始化结构体中的某个回调或标志字段。

举例推测:

比如在某些版本中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cCopyEdittypedef struct _OBJECT_TYPE_INITIALIZER {
USHORT Length;
BOOLEAN UseDefaultObject;
BOOLEAN CaseInsensitive;
ULONG InvalidAttributes;
GENERIC_MAPPING GenericMapping;
ULONG ValidAccessMask;
BOOLEAN SecurityRequired;
BOOLEAN MaintainHandleCount;
BOOLEAN MaintainTypeList;
POOL_TYPE PoolType;
ULONG DefaultPagedPoolCharge;
ULONG DefaultNonPagedPoolCharge;
POB_PRE_OPERATION_CALLBACK PreOperationCallback; // 可能就在偏移 0x20 附近
// ...
} OBJECT_TYPE_INITIALIZER;

在这样的布局下,加 0x40 访问 OBJECT_TYPE 内部的 OBJECT_TYPE_INITIALIZER,再加 0x20 即访问其中的某个字段,比如回调或权限限制字段。

查看ob回调高度

1.使用windbg查看回调高度

1.查看CallbackList链表偏移

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0: kd> dt nt!_OBJECT_TYPE
+0x000 TypeList : _LIST_ENTRY
+0x010 Name : _UNICODE_STRING
+0x020 DefaultObject : Ptr64 Void
+0x028 Index : UChar
+0x02c TotalNumberOfObjects : Uint4B
+0x030 TotalNumberOfHandles : Uint4B
+0x034 HighWaterNumberOfObjects : Uint4B
+0x038 HighWaterNumberOfHandles : Uint4B
+0x040 TypeInfo : _OBJECT_TYPE_INITIALIZER
+0x0b8 TypeLock : _EX_PUSH_LOCK
+0x0c0 Key : Uint4B
+0x0c8 CallbackList : _LIST_ENTRY
0: kd> dt nt!_OBJECT_TYPE -y CallbackList
+0x0c8 CallbackList : _LIST_ENTRY
  1. 打印链表中所有节点的地址

    1
    2
    3
    4
    5
    0: kd> dps poi(nt!PsProcessType)+0xc8 L4
    ffff9107`8a4bd5a8 ffffa100`5f8865b0
    ffff9107`8a4bd5b0 ffffa100`5f87e630
    ffff9107`8a4bd5b8 00000000`00000000
    ffff9107`8a4bd5c0 4c706354`02160000
  2. 查看回调偏移

    1
    2
    du (0xffff91078a4bd5a8+0x20)+0x30
    du

2.驱动中查看回调高度

1.使用结构体成员变量查找ob回调高度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#include <ntddk.h>
#include <wdf.h>
#include <stdbool.h>

// 添加必要的结构体定义
typedef struct _RTL_PROCESS_MODULE_INFORMATION {
HANDLE Section;
PVOID MappedBase;
PVOID ImageBase;
ULONG ImageSize;
ULONG Flags;
USHORT LoadOrderIndex;
USHORT InitOrderIndex;
USHORT LoadCount;
USHORT OffsetToFileName;
UCHAR FullPathName[256];
} RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION;

typedef struct _RTL_PROCESS_MODULES {
ULONG NumberOfModules;
RTL_PROCESS_MODULE_INFORMATION Modules[1];
} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES;

// 声明 ZwQuerySystemInformation
NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation(
_In_ ULONG SystemInformationClass,
_Out_opt_ PVOID SystemInformation,
_In_ ULONG SystemInformationLength,
_Out_opt_ PULONG ReturnLength
);

#define SystemModuleInformation 11

#ifdef DBG
#define DebugMessage(x, ...) DbgPrintEx(0, 0, "qi:" x, __VA_ARGS__)
#else
#define DebugMessage(x, ...) DbgPrintEx(0, 0, "qi:" x, __VA_ARGS__)
#endif

// 添加回调函数类型定义

typedef NTSTATUS(*POB_PRE_OPERATION_CALLBACK)(
PVOID RegistrationContext,
POB_PRE_OPERATION_INFORMATION OperationInformation
);

// ObCallback 结构定义
// First, forward declare the OB_CALLBACK_ENTRY_t structure
struct OB_CALLBACK_ENTRY_t;

// ObCallback structure definition
typedef struct OB_CALLBACK_t {
USHORT Version; // usually 0x100
USHORT OperationRegistrationCount; // number of registered callbacks
PVOID RegistrationContext; // arbitrary data passed at registration time
UNICODE_STRING AltitudeString; // used to determine callbacks order
struct OB_CALLBACK_ENTRY_t* EntryItems; // pointer to array of OperationRegistrationCount items
WCHAR AltitudeBuffer[1]; // is AltitudeString.MaximumLength bytes long, and pointed by AltitudeString.Buffer
} CALLBACK_ENTRY, * PCALLBACK_ENTRY;

typedef struct OB_CALLBACK_ENTRY_t {
LIST_ENTRY CallbackList; // linked element tied to _OBJECT_TYPE.CallbackList
OB_OPERATION Operations; // bitfield : 1 for Creations, 2 for Duplications
bool Enabled; // self-explanatory
struct OB_CALLBACK_t* CallbackEntry; // points to the structure in which it is included
POBJECT_TYPE ObjectType; // points to the object type affected by the callback
POB_PRE_OPERATION_CALLBACK PreOperation; // callback function called before each handle operation
POB_POST_OPERATION_CALLBACK PostOperation; // callback function called after each handle operation
KSPIN_LOCK Lock; // lock object used for synchronization
} OB_CALLBACK_ENTRY, * POB_CALLBACK_ENTRY;


// 在结构体定义部分添加
extern POBJECT_TYPE* PsProcessType;

// 查找 OBJECT_TYPE 中 CallbackListHead 的偏移
ULONG FindCallbackListHeadOffset(POBJECT_TYPE ObjectType) {
// 初始偏移值,可能需要根据具体 Windows 版本调整
ULONG offset = 0x0C8; // Windows 11 23H2 默认偏移

// 这里可以添加确认偏移正确的逻辑
// 例如:检查偏移处是否为有效的 LIST_ENTRY 结构
PLIST_ENTRY possibleListHead = (PLIST_ENTRY)((PUCHAR)ObjectType + offset);

if (MmIsAddressValid(possibleListHead) &&
MmIsAddressValid(possibleListHead->Flink) &&
MmIsAddressValid(possibleListHead->Blink)) {

// 进一步验证 Flink 和 Blink 是否指向合法的内存
if (possibleListHead->Flink != NULL && possibleListHead->Blink != NULL) {
DebugMessage("qi:找到 CallbackListHead 偏移: 0x%X\n", offset);
return offset;
}
}

// 如果默认偏移不正确,可以尝试搜索可能的偏移
// 这里为简化代码,不实现完整搜索
DebugMessage("qi:警告: 使用默认 CallbackListHead 偏移: 0x%X\n", offset);
return offset;
}

// 卸载驱动函数
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
DebugMessage("驱动卸载成功\r\n");
}

// 驱动入口函数
NTSTATUS DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
NTSTATUS status = STATUS_SUCCESS;

// 设置卸载函数
DriverObject->DriverUnload = DriverUnload;

DebugMessage("驱动加载成功\r\n");
DebugMessage("开始查找 ObCallback 高度\r\n");

// 获取 PsProcessType
POBJECT_TYPE processType = *PsProcessType;
if (processType && MmIsAddressValid(processType)) {
// 查找 CallbackListHead 偏移
ULONG callbackListHeadOffset = FindCallbackListHeadOffset(processType);

// 获取 CallbackListHead
PLIST_ENTRY callbackListHead = (PLIST_ENTRY)((PUCHAR)processType + callbackListHeadOffset);

if (MmIsAddressValid(callbackListHead)) {
DebugMessage("CallbackListHead 地址: 0x%llX\n", (ULONG64)callbackListHead);

PLIST_ENTRY currentEntry = callbackListHead->Flink;
int callbackCount = 0;

// 遍历回调链表
while (currentEntry != callbackListHead && MmIsAddressValid(currentEntry)) {
callbackCount++;
POB_CALLBACK_ENTRY cbEntry = CONTAINING_RECORD(currentEntry, OB_CALLBACK_ENTRY, CallbackList);

if (MmIsAddressValid(cbEntry)) {
DebugMessage("回调 #%d: 地址=0x%llX, Pre=0x%llX, Post=0x%llX\n",
callbackCount,
(ULONG64)cbEntry,
(ULONG64)cbEntry->PreOperation,
(ULONG64)cbEntry->PostOperation);
// 尝试获取 Altitude (高度) 信息
if (MmIsAddressValid(cbEntry->CallbackEntry)) {
PCALLBACK_ENTRY callbackEntry = (PCALLBACK_ENTRY)cbEntry->CallbackEntry;
DebugMessage(" CallbackEntry 地址: 0x%llX\n", (ULONG64)callbackEntry);

if (MmIsAddressValid(&callbackEntry->AltitudeString)) {
DebugMessage(" AltitudeString 地址: 0x%llX\n", (ULONG64)&callbackEntry->AltitudeString);

if (MmIsAddressValid(callbackEntry->AltitudeString.Buffer)) {
DebugMessage(" 高度(Altitude): %wZ\n", &callbackEntry->AltitudeString);
}
else {
DebugMessage(" AltitudeString.Buffer 无效\n");
}
}
else {
DebugMessage(" AltitudeString 无效\n");
}
}
else {
DebugMessage(" CallbackEntry 无效\n");
}
}

// 移动到下一个条目
currentEntry = currentEntry->Flink;

// 防止无限循环
if (callbackCount > 100) {
DebugMessage("警告: 可能的循环引用,停止遍历\n");
break;
}
}

DebugMessage("总共找到 %d 个回调\n", callbackCount);
}
else {
DebugMessage("无法访问 CallbackListHead\n");
}
}
else {
DebugMessage("无法访问 PsProcessType\n");
}

return status;
}

2. 遍历多个结构体偏移查找高度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#include <ntddk.h>
#include <wdf.h>
#include <stdbool.h>
// 添加必要的结构体定义
typedef struct _RTL_PROCESS_MODULE_INFORMATION {
HANDLE Section;
PVOID MappedBase;
PVOID ImageBase;
ULONG ImageSize;
ULONG Flags;
USHORT LoadOrderIndex;
USHORT InitOrderIndex;
USHORT LoadCount;
USHORT OffsetToFileName;
UCHAR FullPathName[256];
} RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION;

typedef struct _RTL_PROCESS_MODULES {
ULONG NumberOfModules;
RTL_PROCESS_MODULE_INFORMATION Modules[1];
} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES;

// 声明 ZwQuerySystemInformation
NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation(
_In_ ULONG SystemInformationClass,
_Out_opt_ PVOID SystemInformation,
_In_ ULONG SystemInformationLength,
_Out_opt_ PULONG ReturnLength
);

#define SystemModuleInformation 11

#ifdef DBG
#define DebugMessage(x, ...) DbgPrintEx(0, 0, "qi:" x, __VA_ARGS__)
#else
#define DebugMessage(x, ...) DbgPrintEx(0, 0, "qi:" x, __VA_ARGS__)
#endif

// 添加回调函数类型定义

typedef NTSTATUS(*POB_PRE_OPERATION_CALLBACK)(
PVOID RegistrationContext,
POB_PRE_OPERATION_INFORMATION OperationInformation
);

// ObCallback 结构定义
// First, forward declare the OB_CALLBACK_ENTRY_t structure
struct OB_CALLBACK_ENTRY_t;

// ObCallback structure definition
typedef struct OB_CALLBACK_t {
USHORT Version; // usually 0x100
USHORT OperationRegistrationCount; // number of registered callbacks
PVOID RegistrationContext; // arbitrary data passed at registration time
UNICODE_STRING AltitudeString; // used to determine callbacks order
struct OB_CALLBACK_ENTRY_t* EntryItems; // pointer to array of OperationRegistrationCount items
WCHAR AltitudeBuffer[1]; // is AltitudeString.MaximumLength bytes long, and pointed by AltitudeString.Buffer
} CALLBACK_ENTRY, * PCALLBACK_ENTRY;

typedef struct OB_CALLBACK_ENTRY_t {
LIST_ENTRY CallbackList; // linked element tied to _OBJECT_TYPE.CallbackList
OB_OPERATION Operations; // bitfield : 1 for Creations, 2 for Duplications
bool Enabled; // self-explanatory
struct OB_CALLBACK_t* CallbackEntry; // points to the structure in which it is included
POBJECT_TYPE ObjectType; // points to the object type affected by the callback
POB_PRE_OPERATION_CALLBACK PreOperation; // callback function called before each handle operation
POB_POST_OPERATION_CALLBACK PostOperation; // callback function called after each handle operation
KSPIN_LOCK Lock; // lock object used for synchronization
} OB_CALLBACK_ENTRY, * POB_CALLBACK_ENTRY;

// 在结构体定义部分添加
extern POBJECT_TYPE* PsProcessType;

// 查找 OBJECT_TYPE 中 CallbackListHead 的偏移
ULONG FindCallbackListHeadOffset(POBJECT_TYPE ObjectType) {
// 初始偏移值,可能需要根据具体 Windows 版本调整
ULONG offset = 0x0C8; // Windows 11 23H2 默认偏移

// 这里可以添加确认偏移正确的逻辑
// 例如:检查偏移处是否为有效的 LIST_ENTRY 结构
PLIST_ENTRY possibleListHead = (PLIST_ENTRY)((PUCHAR)ObjectType + offset);

if (MmIsAddressValid(possibleListHead) &&
MmIsAddressValid(possibleListHead->Flink) &&
MmIsAddressValid(possibleListHead->Blink)) {

// 进一步验证 Flink 和 Blink 是否指向合法的内存
if (possibleListHead->Flink != NULL && possibleListHead->Blink != NULL) {
DebugMessage("qi:找到 CallbackListHead 偏移: 0x%X\n", offset);
return offset;
}
}

// 如果默认偏移不正确,可以尝试搜索可能的偏移
// 这里为简化代码,不实现完整搜索
DebugMessage("qi:警告: 使用默认 CallbackListHead 偏移: 0x%X\n", offset);
return offset;
}

// 卸载驱动函数
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
DebugMessage("驱动卸载成功\r\n");
}

// 驱动入口函数
NTSTATUS DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
NTSTATUS status = STATUS_SUCCESS;

// 设置卸载函数
DriverObject->DriverUnload = DriverUnload;

DebugMessage("驱动加载成功\r\n");
DebugMessage("开始查找 ObCallback 高度\r\n");

// 获取 PsProcessType
POBJECT_TYPE processType = *PsProcessType;
if (processType && MmIsAddressValid(processType)) {
// 查找 CallbackListHead 偏移
ULONG callbackListHeadOffset = FindCallbackListHeadOffset(processType);

// 获取 CallbackListHead
PLIST_ENTRY callbackListHead = (PLIST_ENTRY)((PUCHAR)processType + callbackListHeadOffset);

if (MmIsAddressValid(callbackListHead)) {
DebugMessage("CallbackListHead 地址: 0x%llX\n", (ULONG64)callbackListHead);

PLIST_ENTRY currentEntry = callbackListHead->Flink;
int callbackCount = 0;

// 遍历回调链表
while (currentEntry != callbackListHead && MmIsAddressValid(currentEntry)) {
callbackCount++;
POB_CALLBACK_ENTRY cbEntry = CONTAINING_RECORD(currentEntry, OB_CALLBACK_ENTRY, CallbackList);

if (MmIsAddressValid(cbEntry)) {
DebugMessage("回调 #%d: 地址=0x%llX, Pre=0x%llX, Post=0x%llX\n",
callbackCount,
(ULONG64)cbEntry,
(ULONG64)cbEntry->PreOperation,
(ULONG64)cbEntry->PostOperation);

// 输出 CallbackEntry 值以便调试
if (MmIsAddressValid(cbEntry->CallbackEntry)) {
DebugMessage(" CallbackEntry 地址: 0x%llX\n", (ULONG64)cbEntry->CallbackEntry);

// 尝试多个可能的偏移来查找 AltitudeString
// 根据 OB_CALLBACK_REGISTRATION 结构,Altitude 在偏移 0x4 后
// 但实际存储可能有所不同
for (ULONG offset = 0x8; offset <= 0x100; offset += 0x8) {
PUNICODE_STRING pAltitude = (PUNICODE_STRING)((PUCHAR)cbEntry->CallbackEntry + offset);

if (MmIsAddressValid(pAltitude) &&
MmIsAddressValid(pAltitude->Buffer) &&
pAltitude->Length > 0 &&
pAltitude->Length < 100) { // 合理的长度范围

DebugMessage(" 偏移 0x%X 处可能的高度: %wZ\n", offset, pAltitude);
}
}
}
else {
DebugMessage(" CallbackEntry 无效\n");
}
}

// 移动到下一个条目
currentEntry = currentEntry->Flink;

// 防止无限循环
if (callbackCount > 100) {
DebugMessage("警告: 可能的循环引用,停止遍历\n");
break;
}
}

DebugMessage("总共找到 %d 个回调\n", callbackCount);
}
else {
DebugMessage("无法访问 CallbackListHead\n");
}
}
else {
DebugMessage("无法访问 PsProcessType\n");
}

return status;
}

3.结构体偏移查找ob回调高度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#include <ntddk.h>
#include <wdf.h>
#include <stdbool.h>


// 添加必要的结构体定义
typedef struct _RTL_PROCESS_MODULE_INFORMATION {
HANDLE Section;
PVOID MappedBase;
PVOID ImageBase;
ULONG ImageSize;
ULONG Flags;
USHORT LoadOrderIndex;
USHORT InitOrderIndex;
USHORT LoadCount;
USHORT OffsetToFileName;
UCHAR FullPathName[256];
} RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION;

typedef struct _RTL_PROCESS_MODULES {
ULONG NumberOfModules;
RTL_PROCESS_MODULE_INFORMATION Modules[1];
} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES;

// 声明 ZwQuerySystemInformation
NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation(
_In_ ULONG SystemInformationClass,
_Out_opt_ PVOID SystemInformation,
_In_ ULONG SystemInformationLength,
_Out_opt_ PULONG ReturnLength
);

#define SystemModuleInformation 11

#ifdef DBG
#define DebugMessage(x, ...) DbgPrintEx(0, 0, "qi:" x, __VA_ARGS__)
#else
#define DebugMessage(x, ...) DbgPrintEx(0, 0, "qi:" x, __VA_ARGS__)
#endif

// 添加回调函数类型定义

typedef NTSTATUS(*POB_PRE_OPERATION_CALLBACK)(
PVOID RegistrationContext,
POB_PRE_OPERATION_INFORMATION OperationInformation
);

// ObCallback 结构定义
// ObCallback structure definition
typedef struct OB_CALLBACK_t {
USHORT Version; // usually 0x100
USHORT OperationRegistrationCount; // number of registered callbacks
PVOID RegistrationContext; // arbitrary data passed at registration time
UNICODE_STRING AltitudeString; // used to determine callbacks order
struct OB_CALLBACK_ENTRY_t* EntryItems; // pointer to array of OperationRegistrationCount items
WCHAR AltitudeBuffer[1]; // is AltitudeString.MaximumLength bytes long, and pointed by AltitudeString.Buffer
} CALLBACK_ENTRY, * PCALLBACK_ENTRY;

typedef struct OB_CALLBACK_ENTRY_t {
LIST_ENTRY CallbackList; // linked element tied to _OBJECT_TYPE.CallbackList
OB_OPERATION Operations; // bitfield : 1 for Creations, 2 for Duplications
bool Enabled; // self-explanatory
struct OB_CALLBACK_t* CallbackEntry; // points to the structure in which it is included
POBJECT_TYPE ObjectType; // points to the object type affected by the callback
POB_PRE_OPERATION_CALLBACK PreOperation; // callback function called before each handle operation
POB_POST_OPERATION_CALLBACK PostOperation; // callback function called after each handle operation
KSPIN_LOCK Lock; // lock object used for synchronization
} OB_CALLBACK_ENTRY, * POB_CALLBACK_ENTRY;

// 在结构体定义部分添加
extern POBJECT_TYPE* PsProcessType;

// 查找 OBJECT_TYPE 中 CallbackListHead 的偏移
ULONG FindCallbackListHeadOffset(POBJECT_TYPE ObjectType) {
// 初始偏移值,可能需要根据具体 Windows 版本调整
ULONG offset = 0x0C8; // Windows 11 23H2 默认偏移

// 这里可以添加确认偏移正确的逻辑
// 例如:检查偏移处是否为有效的 LIST_ENTRY 结构
PLIST_ENTRY possibleListHead = (PLIST_ENTRY)((PUCHAR)ObjectType + offset);

if (MmIsAddressValid(possibleListHead) &&
MmIsAddressValid(possibleListHead->Flink) &&
MmIsAddressValid(possibleListHead->Blink)) {

// 进一步验证 Flink 和 Blink 是否指向合法的内存
if (possibleListHead->Flink != NULL && possibleListHead->Blink != NULL) {
DebugMessage("qi:找到 CallbackListHead 偏移: 0x%X\n", offset);
return offset;
}
}

// 如果默认偏移不正确,可以尝试搜索可能的偏移
// 这里为简化代码,不实现完整搜索
DebugMessage("qi:警告: 使用默认 CallbackListHead 偏移: 0x%X\n", offset);
return offset;
}

// 卸载驱动函数
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
DebugMessage("驱动卸载成功\r\n");
}

// 驱动入口函数
NTSTATUS DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
NTSTATUS status = STATUS_SUCCESS;

// 设置卸载函数
DriverObject->DriverUnload = DriverUnload;

DebugMessage("驱动加载成功\r\n");
DebugMessage("开始查找 ObCallback 高度\r\n");

// 获取 PsProcessType
POBJECT_TYPE processType = *PsProcessType;
if (processType && MmIsAddressValid(processType)) {
// 查找 CallbackListHead 偏移
ULONG callbackListHeadOffset = FindCallbackListHeadOffset(processType);

// 获取 CallbackListHead
PLIST_ENTRY callbackListHead = (PLIST_ENTRY)((PUCHAR)processType + callbackListHeadOffset);

if (MmIsAddressValid(callbackListHead)) {
DebugMessage("CallbackListHead 地址: 0x%llX\n", (ULONG64)callbackListHead);

PLIST_ENTRY currentEntry = callbackListHead->Flink;
int callbackCount = 0;

// 遍历回调链表
while (currentEntry != callbackListHead && MmIsAddressValid(currentEntry)) {
callbackCount++;
POB_CALLBACK_ENTRY cbEntry = CONTAINING_RECORD(currentEntry, OB_CALLBACK_ENTRY, CallbackList);

if (MmIsAddressValid(cbEntry)) {
DebugMessage("回调 #%d: 地址=0x%llX, Pre=0x%llX, Post=0x%llX\n",
callbackCount,
(ULONG64)cbEntry,
(ULONG64)cbEntry->PreOperation,
(ULONG64)cbEntry->PostOperation);

// 尝试获取 Altitude (高度) 信息
// 在遍历回调时
if (MmIsAddressValid(cbEntry->CallbackEntry)) {
// 假设 AltitudeString 在 CallbackEntry 结构的偏移为 0x10
// 这个偏移需要通过逆向工程或调试确定
PUNICODE_STRING pAltitude = (PUNICODE_STRING)((PUCHAR)cbEntry->CallbackEntry + 0x10);

if (MmIsAddressValid(pAltitude) && MmIsAddressValid(pAltitude->Buffer)) {
DebugMessage(" 高度(Altitude): %wZ\n", pAltitude);
}
else {
DebugMessage(" 无法访问高度信息 (偏移 0x10)\n");
}
}
}

// 移动到下一个条目
currentEntry = currentEntry->Flink;

// 防止无限循环
if (callbackCount > 100) {
DebugMessage("警告: 可能的循环引用,停止遍历\n");
break;
}
}

DebugMessage("总共找到 %d 个回调\n", callbackCount);
}
else {
DebugMessage("无法访问 CallbackListHead\n");
}
}
else {
DebugMessage("无法访问 PsProcessType\n");
}

return status;
}

4.通过计算结构体偏移打印高度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#include <ntddk.h>
#include <wdf.h>
#include <stdbool.h>
#include <stddef.h>

// 添加必要的结构体定义
typedef struct _RTL_PROCESS_MODULE_INFORMATION {
HANDLE Section;
PVOID MappedBase;
PVOID ImageBase;
ULONG ImageSize;
ULONG Flags;
USHORT LoadOrderIndex;
USHORT InitOrderIndex;
USHORT LoadCount;
USHORT OffsetToFileName;
UCHAR FullPathName[256];
} RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION;

typedef struct _RTL_PROCESS_MODULES {
ULONG NumberOfModules;
RTL_PROCESS_MODULE_INFORMATION Modules[1];
} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES;

// 声明 ZwQuerySystemInformation
NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation(
_In_ ULONG SystemInformationClass,
_Out_opt_ PVOID SystemInformation,
_In_ ULONG SystemInformationLength,
_Out_opt_ PULONG ReturnLength
);

#define SystemModuleInformation 11

#ifdef DBG
#define DebugMessage(x, ...) DbgPrintEx(0, 0, "qi:" x, __VA_ARGS__)
#else
#define DebugMessage(x, ...) DbgPrintEx(0, 0, "qi:" x, __VA_ARGS__)
#endif

// 添加回调函数类型定义

typedef NTSTATUS(*POB_PRE_OPERATION_CALLBACK)(
PVOID RegistrationContext,
POB_PRE_OPERATION_INFORMATION OperationInformation
);

// ObCallback 结构定义
// First, forward declare the OB_CALLBACK_ENTRY_t structure
struct OB_CALLBACK_ENTRY_t;

// ObCallback structure definition
typedef struct OB_CALLBACK_t {
USHORT Version; // usually 0x100
USHORT OperationRegistrationCount; // number of registered callbacks
PVOID RegistrationContext; // arbitrary data passed at registration time
UNICODE_STRING AltitudeString; // used to determine callbacks order
struct OB_CALLBACK_ENTRY_t* EntryItems; // pointer to array of OperationRegistrationCount items
WCHAR AltitudeBuffer[1]; // is AltitudeString.MaximumLength bytes long, and pointed by AltitudeString.Buffer
} CALLBACK_ENTRY, * PCALLBACK_ENTRY;

typedef struct OB_CALLBACK_ENTRY_t {
LIST_ENTRY CallbackList; // linked element tied to _OBJECT_TYPE.CallbackList
OB_OPERATION Operations; // bitfield : 1 for Creations, 2 for Duplications
bool Enabled; // self-explanatory
struct OB_CALLBACK_t* CallbackEntry; // points to the structure in which it is included
POBJECT_TYPE ObjectType; // points to the object type affected by the callback
POB_PRE_OPERATION_CALLBACK PreOperation; // callback function called before each handle operation
POB_POST_OPERATION_CALLBACK PostOperation; // callback function called after each handle operation
KSPIN_LOCK Lock; // lock object used for synchronization
} OB_CALLBACK_ENTRY, * POB_CALLBACK_ENTRY;

// 在结构体定义部分添加
extern POBJECT_TYPE* PsProcessType;

// 查找 OBJECT_TYPE 中 CallbackListHead 的偏移
ULONG FindCallbackListHeadOffset(POBJECT_TYPE ObjectType) {
// 初始偏移值,可能需要根据具体 Windows 版本调整
ULONG offset = 0x0C8; // Windows 11 23H2 默认偏移

// 这里可以添加确认偏移正确的逻辑
// 例如:检查偏移处是否为有效的 LIST_ENTRY 结构
PLIST_ENTRY possibleListHead = (PLIST_ENTRY)((PUCHAR)ObjectType + offset);

if (MmIsAddressValid(possibleListHead) &&
MmIsAddressValid(possibleListHead->Flink) &&
MmIsAddressValid(possibleListHead->Blink)) {

// 进一步验证 Flink 和 Blink 是否指向合法的内存
if (possibleListHead->Flink != NULL && possibleListHead->Blink != NULL) {
DebugMessage("qi:找到 CallbackListHead 偏移: 0x%X\n", offset);
return offset;
}
}

// 如果默认偏移不正确,可以尝试搜索可能的偏移
// 这里为简化代码,不实现完整搜索
DebugMessage("qi:警告: 使用默认 CallbackListHead 偏移: 0x%X\n", offset);
return offset;
}

// 卸载驱动函数
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
DebugMessage("驱动卸载成功\r\n");
}

// 驱动入口函数
NTSTATUS DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
NTSTATUS status = STATUS_SUCCESS;

// 设置卸载函数
DriverObject->DriverUnload = DriverUnload;

DebugMessage("驱动加载成功\r\n");
DebugMessage("开始查找 ObCallback 高度\r\n");

// 获取 PsProcessType
POBJECT_TYPE processType = *PsProcessType;
if (processType && MmIsAddressValid(processType)) {
// 查找 CallbackListHead 偏移
ULONG callbackListHeadOffset = FindCallbackListHeadOffset(processType);

// 获取 CallbackListHead
PLIST_ENTRY callbackListHead = (PLIST_ENTRY)((PUCHAR)processType + callbackListHeadOffset);

if (MmIsAddressValid(callbackListHead)) {
DebugMessage("CallbackListHead 地址: 0x%llX\n", (ULONG64)callbackListHead);

PLIST_ENTRY currentEntry = callbackListHead->Flink;
int callbackCount = 0;

// 遍历回调链表
while (currentEntry != callbackListHead && MmIsAddressValid(currentEntry)) {
callbackCount++;
POB_CALLBACK_ENTRY cbEntry = CONTAINING_RECORD(currentEntry, OB_CALLBACK_ENTRY, CallbackList);

if (MmIsAddressValid(cbEntry)) {
DebugMessage("回调 #%d: 地址=0x%llX, Pre=0x%llX, Post=0x%llX\n",
callbackCount,
(ULONG64)cbEntry,
(ULONG64)cbEntry->PreOperation,
(ULONG64)cbEntry->PostOperation);

// 使用 offsetof 计算 CallbackEntry 偏移
ULONG callbackEntryOffset = offsetof(OB_CALLBACK_ENTRY, CallbackEntry);
PCALLBACK_ENTRY pCallback = *(PCALLBACK_ENTRY*)((PUCHAR)cbEntry + callbackEntryOffset);
if (MmIsAddressValid(pCallback)) {
DebugMessage(" callbackEntryOffset: 0x%X\n", callbackEntryOffset);
// 使用 offsetof 计算 AltitudeString 偏移
ULONG altitudeOffset = offsetof(CALLBACK_ENTRY, AltitudeString);
PUNICODE_STRING pAltitude = (PUNICODE_STRING)((PUCHAR)pCallback + altitudeOffset);

if (MmIsAddressValid(pAltitude) &&
MmIsAddressValid(pAltitude->Buffer) &&
pAltitude->Length > 0 &&
pAltitude->Length < 100) {
DebugMessage(" Altitude: %wZ (altitudeOffset: 0x%X)\n", pAltitude, altitudeOffset);
}
}

}

currentEntry = currentEntry->Flink;

if (callbackCount > 100) {
DebugMessage("警告: 可能的循环引用,停止遍历\n");
break;
}
}

DebugMessage("总共找到 %d 个回调\n", callbackCount);
}
else {
DebugMessage("无法访问 CallbackListHead\n");
}
}
else {
DebugMessage("无法访问 PsProcessType\n");
}

return status;
}

3. 遍历打印结构体偏移

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// 获取 PsProcessType
POBJECT_TYPE processType = *PsProcessType;
if (processType && MmIsAddressValid(processType)) {
// 查找 CallbackListHead 偏移
ULONG callbackListHeadOffset = FindCallbackListHeadOffset(processType);

// 获取 CallbackListHead
PLIST_ENTRY callbackListHead = (PLIST_ENTRY)((PUCHAR)processType + callbackListHeadOffset);

if (MmIsAddressValid(callbackListHead)) {
DebugMessage("CallbackListHead 地址: 0x%llX\n", (ULONG64)callbackListHead);

PLIST_ENTRY currentEntry = callbackListHead->Flink;
int callbackCount = 0;

// 遍历回调链表
while (currentEntry != callbackListHead && MmIsAddressValid(currentEntry)) {
callbackCount++;
POB_CALLBACK_ENTRY cbEntry = CONTAINING_RECORD(currentEntry, OB_CALLBACK_ENTRY, CallbackList);

if (MmIsAddressValid(cbEntry)) {
DebugMessage("回调 #%d: 地址=0x%llX\n", callbackCount, (ULONG64)cbEntry);

// 打印回调条目的前 16 个字段 (128 字节)
PULONG64 pMemory = (PULONG64)cbEntry;
for (int i = 0; i < 16; i++) {
if (MmIsAddressValid(&pMemory[i])) {
DebugMessage(" 偏移 0x%02X: 0x%016llX\n", i * 8, pMemory[i]);
}
}

// 根据公共知识尝试访问 PreOperation 和 PostOperation
DebugMessage(" 预测的 Pre: 0x%llX, Post: 0x%llX\n",
(ULONG64)cbEntry->PreOperation,
(ULONG64)cbEntry->PostOperation);

// 直接在内存中查找可能的 UNICODE_STRING 结构
for (int i = 0; i < 10; i++) {
PUNICODE_STRING possibleStr = (PUNICODE_STRING)((PUCHAR)cbEntry + i * 8);
if (MmIsAddressValid(possibleStr) &&
MmIsAddressValid(possibleStr->Buffer) &&
possibleStr->Length > 0 &&
possibleStr->Length < 100) {

DebugMessage(" 可能的字符串在偏移 0x%02X: %wZ\n", i * 8, possibleStr);
}
}
}

// 移动到下一个条目
currentEntry = currentEntry->Flink;
}

DebugMessage("总共找到 %d 个回调\n", callbackCount);
}
else {
DebugMessage("无法访问 CallbackListHead\n");
}
}
else {
DebugMessage("无法访问 PsProcessType\n");
}

查看ob回调并打印对应的驱动名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
#include <ntddk.h>
#include <wdf.h>
#include <stdbool.h>
#include <stddef.h>
// 添加必要的结构体定义
typedef struct _RTL_PROCESS_MODULE_INFORMATION {
HANDLE Section;
PVOID MappedBase;
PVOID ImageBase;
ULONG ImageSize;
ULONG Flags;
USHORT LoadOrderIndex;
USHORT InitOrderIndex;
USHORT LoadCount;
USHORT OffsetToFileName;
UCHAR FullPathName[256];
} RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION;

typedef struct _RTL_PROCESS_MODULES {
ULONG NumberOfModules;
RTL_PROCESS_MODULE_INFORMATION Modules[1];
} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES;

// 声明 ZwQuerySystemInformation
NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation(
_In_ ULONG SystemInformationClass,
_Out_opt_ PVOID SystemInformation,
_In_ ULONG SystemInformationLength,
_Out_opt_ PULONG ReturnLength
);

#define SystemModuleInformation 11

#ifdef DBG
#define DebugMessage(x, ...) DbgPrintEx(0, 0, "qi:" x, __VA_ARGS__)
#else
#define DebugMessage(x, ...) DbgPrintEx(0, 0, "qi:" x, __VA_ARGS__)
#endif

// 添加回调函数类型定义

typedef NTSTATUS(*POB_PRE_OPERATION_CALLBACK)(
PVOID RegistrationContext,
POB_PRE_OPERATION_INFORMATION OperationInformation
);

// ObCallback 结构定义
// First, forward declare the OB_CALLBACK_ENTRY_t structure
struct OB_CALLBACK_ENTRY_t;

// ObCallback structure definition
typedef struct OB_CALLBACK_t {
USHORT Version; // usually 0x100
USHORT OperationRegistrationCount; // number of registered callbacks
PVOID RegistrationContext; // arbitrary data passed at registration time
UNICODE_STRING AltitudeString; // used to determine callbacks order
struct OB_CALLBACK_ENTRY_t* EntryItems; // pointer to array of OperationRegistrationCount items
WCHAR AltitudeBuffer[1]; // is AltitudeString.MaximumLength bytes long, and pointed by AltitudeString.Buffer
} CALLBACK_ENTRY, * PCALLBACK_ENTRY;

typedef struct OB_CALLBACK_ENTRY_t {
LIST_ENTRY CallbackList; // linked element tied to _OBJECT_TYPE.CallbackList
OB_OPERATION Operations; // bitfield : 1 for Creations, 2 for Duplications
bool Enabled; // self-explanatory
struct OB_CALLBACK_t* CallbackEntry; // points to the structure in which it is included
POBJECT_TYPE ObjectType; // points to the object type affected by the callback
POB_PRE_OPERATION_CALLBACK PreOperation; // callback function called before each handle operation
POB_POST_OPERATION_CALLBACK PostOperation; // callback function called after each handle operation
KSPIN_LOCK Lock; // lock object used for synchronization
} OB_CALLBACK_ENTRY, * POB_CALLBACK_ENTRY;

// 在结构体定义部分添加
extern POBJECT_TYPE* PsProcessType;

// 查找 OBJECT_TYPE 中 CallbackListHead 的偏移
ULONG FindCallbackListHeadOffset(POBJECT_TYPE ObjectType) {
// 初始偏移值,可能需要根据具体 Windows 版本调整
ULONG offset = 0x0C8; // Windows 11 23H2 默认偏移

// 这里可以添加确认偏移正确的逻辑
// 例如:检查偏移处是否为有效的 LIST_ENTRY 结构
PLIST_ENTRY possibleListHead = (PLIST_ENTRY)((PUCHAR)ObjectType + offset);

if (MmIsAddressValid(possibleListHead) &&
MmIsAddressValid(possibleListHead->Flink) &&
MmIsAddressValid(possibleListHead->Blink)) {

// 进一步验证 Flink 和 Blink 是否指向合法的内存
if (possibleListHead->Flink != NULL && possibleListHead->Blink != NULL) {
DebugMessage("qi:找到 CallbackListHead 偏移: 0x%X\n", offset);
return offset;
}
}

// 如果默认偏移不正确,可以尝试搜索可能的偏移
// 这里为简化代码,不实现完整搜索
DebugMessage("qi:警告: 使用默认 CallbackListHead 偏移: 0x%X\n", offset);
return offset;
}

// 卸载驱动函数
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
DebugMessage("驱动卸载成功\r\n");
}

// 添加在驱动入口函数之前
PRTL_PROCESS_MODULE_INFORMATION GetModuleByAddress(PRTL_PROCESS_MODULES Modules, PVOID Address)
{
for (ULONG i = 0; i < Modules->NumberOfModules; i++) {
PRTL_PROCESS_MODULE_INFORMATION module = &Modules->Modules[i];
if ((ULONG_PTR)Address >= (ULONG_PTR)module->ImageBase &&
(ULONG_PTR)Address < (ULONG_PTR)module->ImageBase + module->ImageSize) {
return module;
}
}
return NULL;
}

// 驱动入口函数
NTSTATUS DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
NTSTATUS status = STATUS_SUCCESS;

// 设置卸载函数
DriverObject->DriverUnload = DriverUnload;

DebugMessage("驱动加载成功\r\n");
DebugMessage("开始查找 ObCallback 高度\r\n");

// 获取 PsProcessType
POBJECT_TYPE processType = *PsProcessType;
if (processType && MmIsAddressValid(processType)) {
// 查找 CallbackListHead 偏移
ULONG callbackListHeadOffset = FindCallbackListHeadOffset(processType);

// 获取 CallbackListHead
PLIST_ENTRY callbackListHead = (PLIST_ENTRY)((PUCHAR)processType + callbackListHeadOffset);

if (MmIsAddressValid(callbackListHead)) {
DebugMessage("CallbackListHead 地址: 0x%llX\n", (ULONG64)callbackListHead);

PLIST_ENTRY currentEntry = callbackListHead->Flink;
int callbackCount = 0;

// 获取系统模块信息
ULONG modulesSize = 0;
PRTL_PROCESS_MODULES modules = NULL;

status = ZwQuerySystemInformation(SystemModuleInformation, NULL, 0, &modulesSize);
if (modulesSize) {
modules = ExAllocatePoolWithTag(NonPagedPool, modulesSize, 'ldoM');
if (modules) {
status = ZwQuerySystemInformation(SystemModuleInformation, modules, modulesSize, NULL);
}
}

// 遍历回调链表
while (currentEntry != callbackListHead && MmIsAddressValid(currentEntry)) {
callbackCount++;
POB_CALLBACK_ENTRY cbEntry = CONTAINING_RECORD(currentEntry, OB_CALLBACK_ENTRY, CallbackList);

if (MmIsAddressValid(cbEntry)) {
DebugMessage("回调 #%d: 地址=0x%llX, Pre=0x%llX, Post=0x%llX\n",
callbackCount,
(ULONG64)cbEntry,
(ULONG64)cbEntry->PreOperation,
(ULONG64)cbEntry->PostOperation);

// 查找Pre回调所属驱动
if (cbEntry->PreOperation && modules) {
PRTL_PROCESS_MODULE_INFORMATION preModule = GetModuleByAddress(modules, cbEntry->PreOperation);
if (preModule) {
DebugMessage("Pre回调所属驱动: %s\n", preModule->FullPathName);
}
}

// 查找Post回调所属驱动
if (cbEntry->PostOperation && modules) {
PRTL_PROCESS_MODULE_INFORMATION postModule = GetModuleByAddress(modules, cbEntry->PostOperation);
if (postModule) {
DebugMessage("Post回调所属驱动: %s\n", postModule->FullPathName);
}
}

// 使用 offsetof 计算 CallbackEntry 偏移
ULONG callbackEntryOffset = offsetof(OB_CALLBACK_ENTRY, CallbackEntry);
PCALLBACK_ENTRY pCallback = *(PCALLBACK_ENTRY*)((PUCHAR)cbEntry + callbackEntryOffset);

if (MmIsAddressValid(pCallback)) {
// 使用 offsetof 计算 AltitudeString 偏移
ULONG altitudeOffset = offsetof(CALLBACK_ENTRY, AltitudeString);
PUNICODE_STRING pAltitude = (PUNICODE_STRING)((PUCHAR)pCallback + altitudeOffset);

if (MmIsAddressValid(pAltitude) &&
MmIsAddressValid(pAltitude->Buffer) &&
pAltitude->Length > 0 &&
pAltitude->Length < 100) {
DebugMessage(" Altitude: %wZ (偏移: 0x%X)\n", pAltitude, callbackEntryOffset);
}
}
}

currentEntry = currentEntry->Flink;

if (callbackCount > 100) {
DebugMessage("警告: 可能的循环引用,停止遍历\n");
break;
}
}

// 清理模块信息
if (modules) {
ExFreePoolWithTag(modules, 'ldoM');
}

DebugMessage("总共找到 %d 个回调\n", callbackCount);
}
else {
DebugMessage("无法访问 CallbackListHead\n");
}
}
else {
DebugMessage("无法访问 PsProcessType\n");
}

return status;
}