WindowsAPI编程核心技术-对象监控

碎碎念

对象监控指的是线程句柄对象、进程句柄对象、桌面句柄对象的监控。

这个技术病毒木马常用。病毒木马的对象监控回调常用来会自行线程或进程的保护,保护指定程序不被杀毒软件或用户强制结束运行。结束进程时要获取打开的进程句柄,所以病毒木马通过对进程对象进行监控,使系统获取句柄失败,从而实现进程保护。

前置芝士

ObRegisterCallbacks

注册线程、进程和桌面句柄操作的回调函数。驱动程序必须有数字签名。

1
2
3
4
NTSTATUS ObRegisterCallbacks(
_In_ POB_CALLBACK_REGISTER CallBackRegistration, //指定回调例程列表和其他注册信息
_Out_ PVOID* RegistrationHandle //接收已注册回调例程集合的标识
)

ObUnRegisterCallbacks注销回调例程。

OB_CALLBACK_REGISTRATION

1
2
3
4
5
6
7
typedef struct _OB_CALLBACK_REGISTRATION {
_In_ USHORT Version; //请求对象回调注册的版本
_In_ USHORT OperationRegistrationCount; //OperationRegistration数组中条目数
_In_ UNICODE_STRING Altitude; //驱动Altitude 可随意指定但不能不指定
_In_ PVOID RegistrationContext; //回调例程参数
_In_ OB_OPERATION_REGISTRATION *OperationRegistration; //回调例程和操作类型
} OB_CALLBACK_REGISTRATION, *POB_CALLBACK_REGISTRATION;

OB_OPERATION_REGISTRATION

1
2
3
4
5
6
typedef struct _OB_OPERATION_REGISTRATION {
_In_ POBJECT_TYPE *ObjectType; //PsProcessType进程句柄操作 PsThreadType线程句柄操作 ExDesktopObjectType桌面句柄操作
_In_ OB_OPERATION Operations; //标志
_In_ POB_PRE_OPERATION_CALLBACK PreOperation; //请求操作发生前例程
_In_ POB_POST_OPERATION_CALLBACK PostOperation; //请求操作发生后例程
} OB_OPERATION_REGISTRATION, *POB_OPERATION_REGISTRATION;

实现方法

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
// 设置进程回调函数
NTSTATUS SetProcessCallbacks(VOID) {
NTSTATUS status = STATUS_SUCCESS;
OB_CALLBACK_REGISTRATION obCallbackReg = { 0 };
OB_OPERATION_REGISTRATION obOperationReg = { 0 };
RtlZeroMemory(&obCallbackReg, sizeof(OB_CALLBACK_REGISTRATION));
RtlZeroMemory(&obOperationReg, sizeof(OB_OPERATION_REGISTRATION));
// 设置 OB_CALLBACK_REGISTRATION
obCallbackReg.Version = ObGetFilterVersion(); //回调版本
obCallbackReg.OperationRegistrationCount = 1; //回调函数数量
obCallbackReg.RegistrationContext = NULL;
RtlInitUnicodeString(&obCallbackReg.Altitude, L"321000"); //回调Altitude 任意指定
obCallbackReg.OperationRegistration = &obOperationReg;
// 设置 OB_OPERATION_REGISTRATION Thread 和 Process 的区别所在
obOperationReg.ObjectType = PsProcessType; //进程对象PsProcessType 线程对象PsThreadType
obOperationReg.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE; //注册对象已被或将被创建或打开、注册对象将被复制或已被复制
// Thread 和 Process 的区别所在
obOperationReg.PreOperation = (POB_PRE_OPERATION_CALLBACK)(&ProcessPreCall); //回调函数
// 注册回调函数
status = ObRegisterCallbacks(&obCallbackReg, &g_obProcessHandle);
if (!NT_SUCCESS(status)) {
DbgPrint("ObRegisterCallbacks Error[0x%X]\n", status);
return status;
};
return status;
};

想要拒绝结束线程对象或进程对象的操作时,在操作类型句柄信息中去掉响应结束线程对象或结束进程对象操作权限即可。

1
2
3
4
//OB_OPERATION_HANDLE_CREATE
pObPreOperationInfo->Parameters->CreateHandleInformation.DesiredAccess = 0;
//OB_OPERATION_HANDLE_DUPLICATE
pObPreOperationInfo->Parameters->DuplicateHandleInformation.DesiredAccess = 0;

通过线程对象或进程对象pObPreOperationInfo->Object判断是否保护线程或进程。对于进程对象,用PsGetProcessImageFileName从进程结构对象中获取进程名称判断。对于线程对象,用IoThreadToProcess从线程对象获取相应进程对象,再同进程对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 进程回调函数
OB_PREOP_CALLBACK_STATUS ProcessPreCall(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pObPreOperationInfo) {
PEPROCESS pEProcess = NULL;
// 判断对象类型
if (*PsProcessType != pObPreOperationInfo->ObjectType)
return OB_PREOP_SUCCESS;
// 获取进程结构对象
pEProcess = (PEPROCESS)pObPreOperationInfo->Object;
// 判断是否市保护PID, 若是, 则拒绝结束进程
if (IsProtectProcess(pEProcess)) {
// 操作类型: 创建句柄
if (OB_OPERATION_HANDLE_CREATE == pObPreOperationInfo->Operation)
{
if (1 == (1 & pObPreOperationInfo->Parameters->CreateHandleInformation.OriginalDesiredAccess))
pObPreOperationInfo->Parameters->CreateHandleInformation.DesiredAccess = 0;
}
// 操作类型: 复制句柄
else if (OB_OPERATION_HANDLE_DUPLICATE == pObPreOperationInfo->Operation) {
if (1 == (1 & pObPreOperationInfo->Parameters->DuplicateHandleInformation.OriginalDesiredAccess))
pObPreOperationInfo->Parameters->DuplicateHandleInformation.DesiredAccess = 0;
};
};
return OB_PREOP_SUCCESS;
};

源代码

Driver.h:

1
2
3
4
5
6
7
8
9
10
11
12
#ifndef _DRIVER_H_
#define _DRIVER_H_


#include <ntddk.h>


VOID DriverUnload(PDRIVER_OBJECT pDriverObject);
NTSTATUS DriverDefaultHandle(PDEVICE_OBJECT pDevObj, PIRP pIrp);


#endif

NotifyRoutine.h:

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
#ifndef _NOTIFY_ROUTINE_H_
#define _NOTIFY_ROUTINE_H_


#include <ntifs.h>
#include <ntddk.h>


// 未导出函数声明
PUCHAR PsGetProcessImageFileName(PEPROCESS pEProcess);


// 编程方式绕过签名检查
BOOLEAN BypassCheckSign(PDRIVER_OBJECT pDriverObject);

// 设置进程回调函数
NTSTATUS SetProcessCallbacks();

// 设置线程回调函数
NTSTATUS SetThreadCallbacks();

// 删除进程回调函数
VOID RemoveProcessCallbacks();

// 删除线程回调函数
VOID RemoveThreadCallbacks();

// 进程回调函数
OB_PREOP_CALLBACK_STATUS ProcessPreCall(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pObPreOperationInfo);

// 线程回调函数
OB_PREOP_CALLBACK_STATUS ThreadPreCall(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pObPreOperationInfo);

// 判断是否为保护进程
BOOLEAN IsProtectProcess(PEPROCESS pEProcess);


// 进程回调对象句柄
HANDLE g_obProcessHandle;

// 线程回调对象句柄
HANDLE g_obThreadHandle;


#endif

Driver.c:

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
#include "NotifyRoutine.h"
#include "Driver.h"


NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
DbgPrint("Enter DriverEntry\n");

NTSTATUS status = STATUS_SUCCESS;
pDriverObject->DriverUnload = DriverUnload;
for (ULONG i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
{
pDriverObject->MajorFunction[i] = DriverDefaultHandle;
}

// 编程方式绕过签名检查
// BypassCheckSign(pDriverObject);

// 设置进程回调函数
SetProcessCallbacks();

// 设置线程回调函数
SetThreadCallbacks();

DbgPrint("Leave DriverEntry\n");
return status;
}



VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
// 删除进程回调函数
RemoveProcessCallbacks();

// 删除线程回调函数
RemoveThreadCallbacks();
}


NTSTATUS DriverDefaultHandle(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
NTSTATUS status = STATUS_SUCCESS;
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);

return status;
}

NotifyRoutine.c:

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
232
233
234
235
236
237
238
#include "NotifyRoutine.h"


// 编程方式绕过签名检查
BOOLEAN BypassCheckSign(PDRIVER_OBJECT pDriverObject)
{
#ifdef _WIN64
typedef struct _KLDR_DATA_TABLE_ENTRY
{
LIST_ENTRY listEntry;
ULONG64 __Undefined1;
ULONG64 __Undefined2;
ULONG64 __Undefined3;
ULONG64 NonPagedDebugInfo;
ULONG64 DllBase;
ULONG64 EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING path;
UNICODE_STRING name;
ULONG Flags;
USHORT LoadCount;
USHORT __Undefined5;
ULONG64 __Undefined6;
ULONG CheckSum;
ULONG __padding1;
ULONG TimeDateStamp;
ULONG __padding2;
} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;
#else
typedef struct _KLDR_DATA_TABLE_ENTRY
{
LIST_ENTRY listEntry;
ULONG unknown1;
ULONG unknown2;
ULONG unknown3;
ULONG unknown4;
ULONG unknown5;
ULONG unknown6;
ULONG unknown7;
UNICODE_STRING path;
UNICODE_STRING name;
ULONG Flags;
} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;
#endif

PKLDR_DATA_TABLE_ENTRY pLdrData = (PKLDR_DATA_TABLE_ENTRY)pDriverObject->DriverSection;
pLdrData->Flags = pLdrData->Flags | 0x20;

return TRUE;
}


// 设置进程回调函数
NTSTATUS SetProcessCallbacks()
{
NTSTATUS status = STATUS_SUCCESS;
OB_CALLBACK_REGISTRATION obCallbackReg = { 0 };
OB_OPERATION_REGISTRATION obOperationReg = { 0 };

RtlZeroMemory(&obCallbackReg, sizeof(OB_CALLBACK_REGISTRATION));
RtlZeroMemory(&obOperationReg, sizeof(OB_OPERATION_REGISTRATION));

// 设置 OB_CALLBACK_REGISTRATION
obCallbackReg.Version = ObGetFilterVersion();
obCallbackReg.OperationRegistrationCount = 1;
obCallbackReg.RegistrationContext = NULL;
RtlInitUnicodeString(&obCallbackReg.Altitude, L"321000");
obCallbackReg.OperationRegistration = &obOperationReg;

// 设置 OB_OPERATION_REGISTRATION
// Thread 和 Process 的区别所在
obOperationReg.ObjectType = PsProcessType;
obOperationReg.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
// Thread 和 Process 的区别所在
obOperationReg.PreOperation = (POB_PRE_OPERATION_CALLBACK)(&ProcessPreCall);

// 注册回调函数
status = ObRegisterCallbacks(&obCallbackReg, &g_obProcessHandle);
if (!NT_SUCCESS(status))
{
DbgPrint("ObRegisterCallbacks Error[0x%X]\n", status);
return status;
}

return status;
}


// 设置线程回调函数
NTSTATUS SetThreadCallbacks()
{
NTSTATUS status = STATUS_SUCCESS;
OB_CALLBACK_REGISTRATION obCallbackReg = { 0 };
OB_OPERATION_REGISTRATION obOperationReg = { 0 };

RtlZeroMemory(&obCallbackReg, sizeof(OB_CALLBACK_REGISTRATION));
RtlZeroMemory(&obOperationReg, sizeof(OB_OPERATION_REGISTRATION));

// 设置 OB_CALLBACK_REGISTRATION
obCallbackReg.Version = ObGetFilterVersion();
obCallbackReg.OperationRegistrationCount = 1;
obCallbackReg.RegistrationContext = NULL;
RtlInitUnicodeString(&obCallbackReg.Altitude, L"321001");
obCallbackReg.OperationRegistration = &obOperationReg;

// 设置 OB_OPERATION_REGISTRATION
// Thread 和 Process 的区别所在
obOperationReg.ObjectType = PsThreadType;
obOperationReg.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
// Thread 和 Process 的区别所在
obOperationReg.PreOperation = (POB_PRE_OPERATION_CALLBACK)(&ThreadPreCall);

// 注册回调函数
status = ObRegisterCallbacks(&obCallbackReg, &g_obThreadHandle);
if (!NT_SUCCESS(status))
{
DbgPrint("ObRegisterCallbacks Error[0x%X]\n", status);
return status;
}

return status;
}


// 删除进程回调函数
VOID RemoveProcessCallbacks()
{
// 卸载回调
if (NULL != g_obProcessHandle)
{
ObUnRegisterCallbacks(g_obProcessHandle);
g_obProcessHandle = NULL;
}
}


// 删除线程回调函数
VOID RemoveThreadCallbacks()
{
// 卸载回调
if (NULL != g_obThreadHandle)
{
ObUnRegisterCallbacks(g_obThreadHandle);
g_obThreadHandle = NULL;
}
}


// 进程回调函数
OB_PREOP_CALLBACK_STATUS ProcessPreCall(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pObPreOperationInfo)
{
PEPROCESS pEProcess = NULL;

// 判断对象类型
if (*PsProcessType != pObPreOperationInfo->ObjectType)
{
return OB_PREOP_SUCCESS;
}
// 获取进程结构对象
pEProcess = (PEPROCESS)pObPreOperationInfo->Object;
// 判断是否市保护PID, 若是, 则拒绝结束进程
if (IsProtectProcess(pEProcess))
{
// 操作类型: 创建句柄
if (OB_OPERATION_HANDLE_CREATE == pObPreOperationInfo->Operation)
{
if (1 == (1 & pObPreOperationInfo->Parameters->CreateHandleInformation.OriginalDesiredAccess))
{
pObPreOperationInfo->Parameters->CreateHandleInformation.DesiredAccess = 0;
}
}
// 操作类型: 复制句柄
else if (OB_OPERATION_HANDLE_DUPLICATE == pObPreOperationInfo->Operation)
{
if (1 == (1 & pObPreOperationInfo->Parameters->DuplicateHandleInformation.OriginalDesiredAccess))
{
pObPreOperationInfo->Parameters->DuplicateHandleInformation.DesiredAccess = 0;
}
}
}

return OB_PREOP_SUCCESS;
}


// 线程回调函数
OB_PREOP_CALLBACK_STATUS ThreadPreCall(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pObPreOperationInfo)
{
PEPROCESS pEProcess = NULL;

// 判断对象类型
if (*PsThreadType != pObPreOperationInfo->ObjectType)
{
return OB_PREOP_SUCCESS;
}
// 获取线程对应的进程 PEPROCESS
pEProcess = IoThreadToProcess((PETHREAD)pObPreOperationInfo->Object);
// 判断是否市保护PID, 若是, 则拒绝结束线程
if (IsProtectProcess(pEProcess))
{
// 操作类型: 创建句柄
if (OB_OPERATION_HANDLE_CREATE == pObPreOperationInfo->Operation)
{
if (1 == (1 & pObPreOperationInfo->Parameters->CreateHandleInformation.OriginalDesiredAccess))
{
pObPreOperationInfo->Parameters->CreateHandleInformation.DesiredAccess = 0;
}
}
// 操作类型: 复制句柄
else if (OB_OPERATION_HANDLE_DUPLICATE == pObPreOperationInfo->Operation)
{
if (1 == (1 & pObPreOperationInfo->Parameters->DuplicateHandleInformation.OriginalDesiredAccess))
{
pObPreOperationInfo->Parameters->DuplicateHandleInformation.DesiredAccess = 0;
}
}
}

return OB_PREOP_SUCCESS;
}


// 判断是否为保护进程
BOOLEAN IsProtectProcess(PEPROCESS pEProcess)
{
PUCHAR pProcessName = PsGetProcessImageFileName(pEProcess);
if (NULL != pProcessName)
{
if (0 == _stricmp(pProcessName, "520.exe"))
{
DbgPrint("[Protect]");
return TRUE;
}

DbgPrint("ProcessName=%s\n", pProcessName);
}
return FALSE;
}

反对象监控

基本原理

与反注册表监控很像,这里不细讲了。

系统所有ObRegisterCallbacks对象回调函数的地址存储在系统中以CallbackList为表头的双向链表中,包括操作前后回调地址和对象回调句柄信息。

CallbackList双向链表指向的数据结构:

1
2
3
4
5
6
7
8
9
10
#pragma pack(1)
typedef struct _OB_CALLBACK {
LIST_ENTRY ListEntry; //下一个或上一个OB_CALLBACK结构体指针信息
ULONGLONG Unknown;
HANDLE ObHandle; //对象回调句柄
PVOID ObTypeAddr;
PVOID PreCall; //操作前回调
PVOID PostCall; //操作后回调
}OB_CALLBACK, * POB_CALLBACK;
#pragma pack()

获取CallbackList地址方法:直接从对象类型中导出。从*PsProcessType中获取进程对象回调函数双向链表信息,从*PsThreadType中获取线程对象回调函数双向链表信息。这俩数据结构类型分别为POBJECT_TYPE和POBJECT_TYPE,这俩定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
typedef struct _OBJECT_TYPE {
LIST_ENTRY TypeList; // _LIST_ENTRY
UNICODE_STRING Name; // _UNICODE_STRING
PVOID DefaultObject; // Ptr64 Void
UCHAR Index; // UChar
ULONG TotalNumberOfObjects; // Uint4B
ULONG TotalNumberOfHandles; // Uint4B
ULONG HighWaterNumberOfObjects; // Uint4B
ULONG HighWaterNumberOfHandles; // Uint4B
OBJECT_TYPE_INITIALIZER TypeInfo; // _OBJECT_TYPE_INITIALIZER
EX_PUSH_LOCK TypeLock; // _EX_PUSH_LOCK
ULONG Key; // Uint4B
LIST_ENTRY CallbackList; // _LIST_ENTRY 这玩意儿就是要找的表头
}OBJECT_TYPE, * POBJECT_TYPE;

其中OBJECT_TYPE_INITIALIZER结构如下:

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
typedef struct _OBJECT_TYPE_INITIALIZER {
USHORT Length; // Uint2B
UCHAR ObjectTypeFlags; // UChar
ULONG ObjectTypeCode; // Uint4B
ULONG InvalidAttributes; // Uint4B
GENERIC_MAPPING GenericMapping; // _GENERIC_MAPPING
ULONG ValidAccessMask; // Uint4B
ULONG RetainAccess; // Uint4B
POOL_TYPE PoolType; // _POOL_TYPE
ULONG DefaultPagedPoolCharge; // Uint4B
ULONG DefaultNonPagedPoolCharge; // Uint4B
PVOID DumpProcedure; // Ptr64 void
PVOID OpenProcedure; // Ptr64 long
PVOID CloseProcedure; // Ptr64 void
PVOID DeleteProcedure; // Ptr64 void
PVOID ParseProcedure; // Ptr64 long
PVOID SecurityProcedure; // Ptr64 long
PVOID QueryNameProcedure; // Ptr64 long
PVOID OkayToCloseProcedure; // Ptr64 unsigned char
#if (NTDDI_VERSION >= NTDDI_WINBLUE) // Win8.1
ULONG WaitObjectFlagMask; // Uint4B
USHORT WaitObjectFlagOffset; // Uint2B
USHORT WaitObjectPointerOffset; // Uint2B
#endif
}OBJECT_TYPE_INITIALIZER, * POBJECT_TYPE_INITIALIZER;

其实系统在wdm.h中已经为程序导入了*PsProcessType*PsThreadType

1
2
3
4
5
6
7
8
9
10
11
12
extern POBJECT_TYPE *CmKeyObjectType;
extern POBJECT_TYPE *IoFileObjectType;
extern POBJECT_TYPE *ExEventObjectType;
extern POBJECT_TYPE *ExSemaphoreObjectType;
extern POBJECT_TYPE *TmTransactionManagerObjectType;
extern POBJECT_TYPE *TmResourceManagerObjectType;
extern POBJECT_TYPE *TmEnlistmentObjectType;
extern POBJECT_TYPE *TmTransactionObjectType;
extern POBJECT_TYPE *PsProcessType;
extern POBJECT_TYPE *PsThreadType;
extern POBJECT_TYPE *PsJobType;
extern POBJECT_TYPE *SeTokenObjectType;

但是这俩获取方式还不大一样,分别为:

1
2
LIST_ENTRY CallbackList = ((POBJECT_TYPE)(*PsProcessType))->CallbackList;
LIST_ENTRY CallbackList = ((POBJECT_TYPE)(*PsThreadType))->CallbackList;

以下是枚举系统进程对象回调函数的实现代码,线程改一下链表表头地址的获取即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 获取进程对象类型回调
BOOLEAN EnumProcessObCallback(VOID) {
POB_CALLBACK pObCallback = NULL;
// 直接获取 CallbackList 链表
LIST_ENTRY CallbackList = ((POBJECT_TYPE)(*PsProcessType))->CallbackList;
// 开始遍历
pObCallback = (POB_CALLBACK)CallbackList.Flink;
do {
if (FALSE == MmIsAddressValid(pObCallback))
break;
if (NULL != pObCallback->ObHandle) {
// 显示
DbgPrint("[PsProcessType]pObCallback->ObHandle = 0x%p\n", pObCallback->ObHandle);
DbgPrint("[PsProcessType]pObCallback->PreCall = 0x%p\n", pObCallback->PreCall);
DbgPrint("[PsProcessType]pObCallback->PostCall = 0x%p\n", pObCallback->PostCall);
};
// 获取下一链表信息
pObCallback = (POB_CALLBACK)pObCallback->ListEntry.Flink;
} while (CallbackList.Flink != (PLIST_ENTRY)pObCallback);
return TRUE;
};

删除对象回调函数:

1
2
3
4
5
// 移除回调
NTSTATUS RemoveObCallback(PVOID RegistrationHandle) {
ObUnRegisterCallbacks(RegistrationHandle);
return STATUS_SUCCESS;
};

源代码

Driver.h:

1
2
3
4
5
6
7
8
9
10
11
12
#ifndef _DRIVER_H_
#define _DRIVER_H_


#include <ntddk.h>


VOID DriverUnload(PDRIVER_OBJECT pDriverObject);
NTSTATUS DriverDefaultHandle(PDEVICE_OBJECT pDevObj, PIRP pIrp);


#endif

EnumRemove.h:

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
#ifndef _ENUM_REMOVE_H_
#define _ENUM_REMOVE_H_


#include <ntifs.h>
#include <wdm.h>


typedef struct _OBJECT_TYPE_INITIALIZER
{
USHORT Length; // Uint2B
UCHAR ObjectTypeFlags; // UChar
ULONG ObjectTypeCode; // Uint4B
ULONG InvalidAttributes; // Uint4B
GENERIC_MAPPING GenericMapping; // _GENERIC_MAPPING
ULONG ValidAccessMask; // Uint4B
ULONG RetainAccess; // Uint4B
POOL_TYPE PoolType; // _POOL_TYPE
ULONG DefaultPagedPoolCharge; // Uint4B
ULONG DefaultNonPagedPoolCharge; // Uint4B
PVOID DumpProcedure; // Ptr64 void
PVOID OpenProcedure; // Ptr64 long
PVOID CloseProcedure; // Ptr64 void
PVOID DeleteProcedure; // Ptr64 void
PVOID ParseProcedure; // Ptr64 long
PVOID SecurityProcedure; // Ptr64 long
PVOID QueryNameProcedure; // Ptr64 long
PVOID OkayToCloseProcedure; // Ptr64 unsigned char
#if (NTDDI_VERSION >= NTDDI_WINBLUE) // Win8.1
ULONG WaitObjectFlagMask; // Uint4B
USHORT WaitObjectFlagOffset; // Uint2B
USHORT WaitObjectPointerOffset; // Uint2B
#endif
}OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;

typedef struct _OBJECT_TYPE
{
LIST_ENTRY TypeList; // _LIST_ENTRY
UNICODE_STRING Name; // _UNICODE_STRING
PVOID DefaultObject; // Ptr64 Void
UCHAR Index; // UChar
ULONG TotalNumberOfObjects; // Uint4B
ULONG TotalNumberOfHandles; // Uint4B
ULONG HighWaterNumberOfObjects; // Uint4B
ULONG HighWaterNumberOfHandles; // Uint4B
OBJECT_TYPE_INITIALIZER TypeInfo; // _OBJECT_TYPE_INITIALIZER
EX_PUSH_LOCK TypeLock; // _EX_PUSH_LOCK
ULONG Key; // Uint4B
LIST_ENTRY CallbackList; // _LIST_ENTRY
}OBJECT_TYPE, *POBJECT_TYPE;

#pragma pack(1)
typedef struct _OB_CALLBACK
{
LIST_ENTRY ListEntry;
ULONGLONG Unknown;
HANDLE ObHandle;
PVOID ObTypeAddr;
PVOID PreCall;
PVOID PostCall;
}OB_CALLBACK, *POB_CALLBACK;
#pragma pack()


// 获取进程对象类型回调
BOOLEAN EnumProcessObCallback();

// 获取线程对象类型回调
BOOLEAN EnumThreadObCallback();

// 移除回调
NTSTATUS RemoveObCallback(PVOID RegistrationHandle);


#endif

Driver.c:

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
#include "EnumRemove.h"
#include "Driver.h"


NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
DbgPrint("Enter DriverEntry\n");

NTSTATUS status = STATUS_SUCCESS;
pDriverObject->DriverUnload = DriverUnload;
for (ULONG i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
{
pDriverObject->MajorFunction[i] = DriverDefaultHandle;
}

// 获取进程对象类型回调
EnumProcessObCallback();

// 获取线程对象类型回调
EnumThreadObCallback();

DbgPrint("Leave DriverEntry\n");
return status;
}



VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
}


NTSTATUS DriverDefaultHandle(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
NTSTATUS status = STATUS_SUCCESS;
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);

return status;
}

EnumRemove.c:

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
#include "EnumRemove.h"


VOID ShowError(PCHAR lpszText, NTSTATUS ntStatus)
{
DbgPrint("%s Error[0x%X]\n", lpszText, ntStatus);
}


// 获取进程对象类型回调
BOOLEAN EnumProcessObCallback()
{
POB_CALLBACK pObCallback = NULL;

// 直接获取 CallbackList 链表
LIST_ENTRY CallbackList = ((POBJECT_TYPE)(*PsProcessType))->CallbackList;

// 开始遍历
pObCallback = (POB_CALLBACK)CallbackList.Flink;
do
{
if (FALSE == MmIsAddressValid(pObCallback))
{
break;
}
if (NULL != pObCallback->ObHandle)
{
// 显示
DbgPrint("[PsProcessType]pObCallback->ObHandle = 0x%p\n", pObCallback->ObHandle);
DbgPrint("[PsProcessType]pObCallback->PreCall = 0x%p\n", pObCallback->PreCall);
DbgPrint("[PsProcessType]pObCallback->PostCall = 0x%p\n", pObCallback->PostCall);
}
// 获取下一链表信息
pObCallback = (POB_CALLBACK)pObCallback->ListEntry.Flink;

} while (CallbackList.Flink != (PLIST_ENTRY)pObCallback);

return TRUE;
}


// 获取线程对象类型回调
BOOLEAN EnumThreadObCallback()
{
POB_CALLBACK pObCallback = NULL;

// 直接获取 CallbackList 链表
LIST_ENTRY CallbackList = ((POBJECT_TYPE)(*PsThreadType))->CallbackList;

// 开始遍历
pObCallback = (POB_CALLBACK)CallbackList.Flink;
do
{
if (FALSE == MmIsAddressValid(pObCallback))
{
break;
}
if (NULL != pObCallback->ObHandle)
{
// 显示
DbgPrint("[PsThreadype]pObCallback->ObHandle = 0x%p\n", pObCallback->ObHandle);
DbgPrint("[PsThreadType]pObCallback->PreCall = 0x%p\n", pObCallback->PreCall);
DbgPrint("[PsThreadType]pObCallback->PostCall = 0x%p\n", pObCallback->PostCall);
}
// 获取下一链表信息
pObCallback = (POB_CALLBACK)pObCallback->ListEntry.Flink;

} while (CallbackList.Flink != (PLIST_ENTRY)pObCallback);

return TRUE;
}


// 移除回调
NTSTATUS RemoveObCallback(PVOID RegistrationHandle)
{
ObUnRegisterCallbacks(RegistrationHandle);

return STATUS_SUCCESS;
}