Joe1sn's Cabin

windows内核驱动 9-进程回调保护与注册表回调保护

又开始学内核编程

注册表回调保护

使用系统API CmRegisterCallback

1
2
3
4
5
NTSTATUS CmRegisterCallback(
[in] PEX_CALLBACK_FUNCTION Function,
[in, optional] PVOID Context,
[out] PLARGE_INTEGER Cookie
);

指向LARGE_INTEGER变量的指针,该变量接收标识回调例程的值。 注销回调例程时,请将此值作为 Cookie 参数传递给 CmUnRegisterCallback

1
[in] Function

指向要注册的 RegistryCallback 例程的指针。

1
[in, optional] Context

配置管理器将作为 CallbackContext 参数传递给 RegistryCallback 例程的驱动程序定义值

1
[out] Cookie

指向LARGE_INTEGER变量的指针,该变量接收标识回调例程的值。 注销回调例程时,请将此值作为 Cookie 参数传递给 CmUnRegisterCallback

设置注册表回调参数

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

LARGE_INTEGER cookie = {0};

NTSTATUS RegCallback(PVOID callbackContext, PVOID optType, PVOID optData)
{
REG_NOTIFY_CLASS tempclass = (REG_NOTIFY_CLASS)optType; //通知的类型
switch (tempclass) {
case RegNtPreOpenKey:
case RegNtPreOpenKeyEx:
case RegNtPreCreateKeyEx:
case RegNtPreCreateKey: {
DbgPrint("Create/Open Key\n");
PREG_CREATE_KEY_INFORMATION pkey = (PREG_CREATE_KEY_INFORMATION)optData;
__try {
DbgPrint("key: <%wZ>\n", pkey->CompleteName);
}
__except(1){
DbgPrint("bad memory\n");
}

break;
}
default:
break;
}
return STATUS_SUCCESS;
}

VOID
DriverUnload(PDRIVER_OBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);
DbgPrint("Driver Stopping -> %wZ\n", &DriverObject->DriverName);
CmUnRegisterCallback(cookie);
}

NTSTATUS
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(RegistryPath);

DbgPrint("Driver Running -> %wZ\n", &DriverObject->DriverName);
DriverObject->DriverUnload = DriverUnload;

NTSTATUS status = STATUS_SUCCESS;
status = CmRegisterCallback(RegCallback, (PVOID)0x123456, &cookie);


return STATUS_SUCCESS;
}

image-20260307123841380

进行拦截操作,就是稍微匹配一下

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
NTSTATUS RegCallback(PVOID callbackContext, PVOID optType, PVOID optData) 
{
NTSTATUS status = STATUS_SUCCESS;
REG_NOTIFY_CLASS tempclass = (REG_NOTIFY_CLASS)optType; //通知的类型

UNICODE_STRING tempname = { 0 };
RtlInitUnicodeString(&tempname, L"*DRIVERTEST"); //其实是一个正则表达式

switch (tempclass) {
case RegNtPreOpenKey:
case RegNtPreOpenKeyEx:
case RegNtPreCreateKeyEx:
case RegNtPreCreateKey: {
PREG_CREATE_KEY_INFORMATION pkey = (PREG_CREATE_KEY_INFORMATION)optData;
__try {
//DbgPrint("key: <%wZ>\n", pkey->CompleteName);
if (FsRtlIsNameInExpression(&tempname, pkey->CompleteName, TRUE, NULL)) {
DbgPrint("can't create such reg\n");
status = STATUS_UNSUCCESSFUL;
}
}
__except(1){
DbgPrint("bad memory\n");
}

break;
}
default:
break;
}
return status;
}

image-20260307125036585

对象/进程回调

也就是注册一个 对 进程对象 的回调函数

1
2
3
4
5
6
7
typedef struct _OB_CALLBACK_REGISTRATION {
USHORT Version;
USHORT OperationRegistrationCount;
UNICODE_STRING Altitude;
PVOID RegistrationContext;
OB_OPERATION_REGISTRATION *OperationRegistration;
} OB_CALLBACK_REGISTRATION, *POB_CALLBACK_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
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
#include <ntifs.h>
#include <windef.h>

PCHAR PsGetProcessImageFileName(PEPROCESS EProcess);

typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT TlsIndex;
union
{
LIST_ENTRY HashLinks;
struct
{
PVOID SectionPointer;
ULONG CheckSum;
};
};
union
{
ULONG TimeDateStamp;
PVOID LoadedImports;
};
PVOID EntryPointActivationContext;
PVOID PatchInformation;
} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;

PVOID Handle = NULL;

static OB_PREOP_CALLBACK_STATUS ProtectProcess(
_In_ PVOID RegistrationContext,
_Inout_ POB_PRE_OPERATION_INFORMATION OperationInformation
) {
PUCHAR imageFileName = PsGetProcessImageFileName(OperationInformation->Object);
DbgPrint("open/duplicate process: %s\n", imageFileName);
return OB_PREOP_SUCCESS;
}

VOID
DriverUnload(PDRIVER_OBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);
DbgPrint("Driver Stopping -> %wZ\n", &DriverObject->DriverName);
ObUnRegisterCallbacks(Handle);
}

NTSTATUS
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(RegistryPath);

DbgPrint("Driver Running -> %wZ\n", &DriverObject->DriverName);
DriverObject->DriverUnload = DriverUnload;

NTSTATUS status = STATUS_SUCCESS;

PLDR_DATA_TABLE_ENTRY ldr = (PLDR_DATA_TABLE_ENTRY)DriverObject->DriverSection;
ldr->Flags |= 0x20;
OB_CALLBACK_REGISTRATION ob = { 0 };
OB_OPERATION_REGISTRATION obReg = { 0 };
UNICODE_STRING altitude = { 0 };
RtlInitUnicodeString(&altitude, L"32199");
ob.Version = ObGetFilterVersion();
ob.OperationRegistrationCount = 1;
ob.OperationRegistration = &obReg;
ob.Altitude = altitude;
ob.RegistrationContext = NULL;

obReg.ObjectType = PsProcessType; //注册进程的回调
obReg.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
obReg.PreOperation = ProtectProcess;
obReg.PostOperation = NULL;

status = ObRegisterCallbacks(&ob, &Handle);
return status;
}

image-20260307132606680

设置访问等级可以让进程不会被关闭

1
2
3
4
5
6
7
8
9
10
11
12
static OB_PREOP_CALLBACK_STATUS ProtectProcess(
_In_ PVOID RegistrationContext,
_Inout_ POB_PRE_OPERATION_INFORMATION OperationInformation
) {
PUCHAR imageFileName = PsGetProcessImageFileName(OperationInformation->Object);
//DbgPrint("open/duplicate process: %s\n", imageFileName);
if (strstr(imageFileName, "Calc")) { //如果打开/复制计算器,权限清0
OperationInformation->Parameters->CreateHandleInformation.DesiredAccess = 0;
OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess = 0;
}
return OB_PREOP_SUCCESS;
}

image-20260307133110436

同时也可以保护进程内存不被访问到

image-20260307133546003