今天学习驱动保护进程。

实现原理

我们在驱动层注册一个进程回调,当调用 OpenProcess 的时候,会触发这个回调,我们在这里取消掉进程结束的权限就可以达到防止进程被结束的目的。

回调函数

先写一下回调函数:

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
OB_PREOP_CALLBACK_STATUS MyProtect(
PVOID RegistrationContext,
POB_PRE_OPERATION_INFORMATION OperationInformation){
if (OperationInformation->KernelHandle) {

}
else {
ACCESS_MASK AccessBitsToClear = PROCESS_TERMINATE;
PEPROCESS process = (PEPROCESS)OperationInformation->Object;
PUCHAR processName = PsGetProcessImageFileName(process);
if (_stricmp((char *)processName, "msedge.exe") != 0) {
return OB_PREOP_SUCCESS;
}
ACCESS_MASK Origin = OperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess;
if(Origin&AccessBitsToClear){
if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE) {
OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~AccessBitsToClear;
}
if (OperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE) {
OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= ~AccessBitsToClear;
}
kprintf(("xia0ji233: old=%p new=%p\n"), Origin, OperationInformation->Parameters->CreateHandleInformation.DesiredAccess);
}
}
return OB_PREOP_SUCCESS;
}

上面这个回调函数的意思就是获取进程名,判断是否为 msedge.exe,如果是,那么把在获取这个进程的权限时,把 PROCESS_TERMINATE 给去掉,也就是防止被其它进程杀掉。

创建回调

在加载驱动的入口点调用这个函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void startProtect() {
OB_CALLBACK_REGISTRATION obl_callback_reg = { 0 };
OB_OPERATION_REGISTRATION ob2_operation = { 0 };
RtlInitUnicodeString(&obl_callback_reg.Altitude,L"321000");
obl_callback_reg.RegistrationContext = NULL;
obl_callback_reg.Version = OB_FLT_REGISTRATION_VERSION;//ObGetFilterVersion)://
obl_callback_reg.OperationRegistrationCount = 1;//只注册一个回调
obl_callback_reg.OperationRegistration = &ob2_operation;
ob2_operation.ObjectType = PsProcessType;//设置为进程事件,PsThreadType为线程事件
ob2_operation.Operations = OB_OPERATION_HANDLE_CREATE;
ob2_operation.PostOperation = NULL;
ob2_operation.PreOperation = MyProtect;//设置回调函数
ObRegisterCallbacks(&obl_callback_reg, &gs_HandleCallback);//注册回调,获得句柄,等会用于关闭
kprintf(("xia0ji233:Process Proctect start\n"));
kprintf(("xia0ji233:gs_HandleCallback=%p\n"), gs_HandleCallback);
}

但是可能会发现,调用是失败的,这是因为我们的驱动没有签名导致的,绕过方法也很简单,把驱动设备的某个flag & 上 0x20 即可。

在入口点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
typedef struct _LDR_DATA
{
struct _LIST_ENTRY InLoadOrderLinks;
struct _LIST_ENTRY InMemoryOrderLinks;
struct _LIST_ENTRY InInitializationOrderLinks;
VOID* DllBase;
VOID* EntryPoint;
ULONG32 SizeOfImage;
UINT8 _PADDING0_[0x4];
struct _UNICODE_STRING FullDllName;
struct _UNICODE_STRING BaseDllName;
ULONG32 Flags;
}LDR_DATA, *PLDR_DATA;
PLDR_DATA ldr;
ldr = (PLDR_DATA)DriverObject->DriverSection;
ldr->Flags |= 0x20;
startProtect();

就可以正常注册回调了。

卸载回调

非常简单,就一句话,但是注意判断回调是否调用成功,不然就蓝屏。。

1
2
3
4
void endProtect() {
if(gs_HandleCallback)ObUnRegisterCallbacks(gs_HandleCallback);
kprintf(("xia0ji233:Process Proctect end\n"));
}

在DriverUnload中调用就可以。

运行结果

当然,我们在要取消的权限位上面加其它的权限位,就可以防止进程被跨进程读写内存,或者是被创建线程注入等等,下面也演示一下开启驱动保护之后的进程,看看用CE附加是什么状态。

首先可以试试拒绝跨进程读内存:

可以看到 msedge.exe 这个进程图标都不显示,读取进程的图标是有进程读权限的,这里没有说明该进程不允许被跨进程读取内存。

代码汇总

驱动加载程序

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
#include <iostream>
#include <winsvc.h>
void LoadDriver(const char * ServeName, const char * DriverPath) {
char FullPath[256] = { 0 };
GetFullPathNameA(DriverPath, 256, FullPath, NULL);
SC_HANDLE hServiceMgr = NULL;//SCM管理器的句柄
SC_HANDLE hServiceDDK = NULL;//NT驱动程序的服务句柄
hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
printf("Open SCM handle=%p,GetLastError=%p\n", hServiceMgr, GetLastError());
hServiceDDK = CreateServiceA(
hServiceMgr,
ServeName,//驱动程序的在注册表中的名字
ServeName,//注册表驱动程序的DisplayName值
SERVICE_START,//加载驱动程序的访问权限 SERVICE_START 或者 SERVICE_ALL-ACCESS
SERVICE_KERNEL_DRIVER,//表示加载的服务是驱动程序
SERVICE_DEMAND_START,//注册表驱动程序的Start值
SERVICE_ERROR_NORMAL,//SERVICE_ERROR_IGNORE,//注册表驱动程序的ErrorControl值//指定当进程调用StartService函数时由服务控制管理器启动的服务。
FullPath,//szDriverImagePath注册表驱动程序的路径如:C:\\222\1.sys
NULL,//GroupOrder HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GroupOrderList
NULL,
NULL,
NULL,
NULL
);



if (GetLastError() == ERROR_SERVICE_EXISTS) {
printf("Service Already Exists\n");
hServiceDDK = OpenServiceA(hServiceMgr, ServeName, SERVICE_START);
}
else if (GetLastError() != 0) {
printf("GetLastError=%p\n", GetLastError());

return;
}
printf("hServiceDDK=%p\n", hServiceDDK);
int bRet = StartService(hServiceDDK, NULL, NULL);
if (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING) {
printf("Service Already Running\n");
}
else {
if (bRet == 0) {
printf("Service Running Failed\n");
printf("GetLastError=%p\n", GetLastError());
}
else {
printf("Service Start Success\n");
}
}
}
void UnloadDriver(const char *ServeName) {
SC_HANDLE hServiceMgr = NULL;//SCM管理器的句柄
SC_HANDLE hServiceDDK = NULL;//NT驱动程序的服务句柄
hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
printf("Open SCM handle=%p,GetLastError=%p\n", hServiceMgr, GetLastError());
hServiceDDK = OpenServiceA(hServiceMgr, ServeName, SERVICE_ALL_ACCESS);
if (hServiceDDK) {
int bRet = 0;
SERVICE_STATUS status;
bRet = ControlService(hServiceDDK, SERVICE_CONTROL_STOP, &status);
if (bRet) {
puts("Stop Service Success");
}
else {
puts("Can't Stop Service");
goto GETLASTERROR;
}
bRet=DeleteService(hServiceDDK);
if (bRet) {
puts("Unload Success");
}
else {
puts("Unload Fail");
}
GETLASTERROR:
printf("GetLastError=%p\n", GetLastError());
}
else {
printf("OpenServe Failed\n");
}
}
int main()
{
LoadDriver("xia0ji233", ".\\KMDFDriver2.sys");
getchar();
UnloadDriver("xia0ji233");
}

驱动程序

这里为了方便,分了三个文件

main.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
#include<ntifs.h>
#include"Protect.h"
#define SYMBOL L"\\??\\xia0ji2333"
#define WriteCode CTL_CODE (FILE_DEVICE_UNKNOWN,0x803,METHOD_BUFFERED, FILE_ANY_ACCESS)
#define ReadCode CTL_CODE (FILE_DEVICE_UNKNOWN,0x804,METHOD_BUFFERED, FILE_ANY_ACCESS)
#define ReadWriteCode CTL_CODE (FILE_DEVICE_UNKNOWN,0x805,METHOD_BUFFERED, FILE_ANY_ACCESS)

void DeleteDevice(PDRIVER_OBJECT);

NTSTATUS CreateDevice(PDEVICE_OBJECT driver) {
NTSTATUS status;
UNICODE_STRING MyDriver;
PDEVICE_OBJECT device = NULL;
RtlInitUnicodeString(&MyDriver, L"\\DEVICE\\xia0ji233");
status = IoCreateDevice(
driver,
sizeof(driver->DeviceExtension),
&MyDriver,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&device
);
if (status == STATUS_SUCCESS) {
UNICODE_STRING Sym;
RtlInitUnicodeString(&Sym, SYMBOL);
status = IoCreateSymbolicLink(&Sym, &MyDriver);
if (status == STATUS_SUCCESS) {
kprintf(("Line %d:xia0ji233: symbol linked success\n"), __LINE__);
}
else {
kprintf(("Line %d:xia0ji233: symbol linked failed status=%x\n"), __LINE__, status);
}
}
else {
kprintf(("Line %d:xia0ji233: create device fail status=%x\n"), __LINE__, status);
}
}
NTSTATUS DeviceIrpCtl(PDEVICE_OBJECT driver, PIRP pirp) {
kprintf(("Line %d:xia0ji233: enter IRP Function\n"), __LINE__);
PIO_STACK_LOCATION irpStackL;
ULONG CtlCode;
ULONG InputBuffLength;
irpStackL = IoGetCurrentIrpStackLocation(pirp);//获取应用层传来的参数
switch (irpStackL->MajorFunction)
{
case IRP_MJ_DEVICE_CONTROL: {
UINT32 code = irpStackL->Parameters.DeviceIoControl.IoControlCode;
kprintf(("Line %d:xia0ji233: ring3 calls DEVICE CONTROL,control code=%x\n"), __LINE__, code);
switch (code) {
case WriteCode: {
char * buffer = (char *)pirp->AssociatedIrp.SystemBuffer;
kprintf(("Line %d:xia0ji233: Get Message:%s\n"), __LINE__, buffer);
break;
}
case ReadCode: {
char * buffer = (char *)pirp->AssociatedIrp.SystemBuffer;
char msg[] = "xia0ji233 in ring0";
kprintf(("Line %d:xia0ji233: return Message:%s\n"), __LINE__, msg);
memcpy(buffer, msg, sizeof(msg));
pirp->IoStatus.Information = sizeof(msg);
break;
}
case ReadWriteCode: {
typedef struct AB {
int a, b;
}AB;
char * buffer = (char *)pirp->AssociatedIrp.SystemBuffer;
AB *s = (AB *)buffer;
kprintf(("Line %d:xia0ji233:get two number %d and %d\n"), __LINE__, s->a, s->b);
int result = s->a + s->b;
memcpy(buffer, &result, sizeof(result));
pirp->IoStatus.Information = sizeof(result);
break;
}
}

break;
}
case IRP_MJ_CREATE: {
kprintf(("Line %d:xia0ji233: ring3 calls CREATE\n"), __LINE__);
break;
}
case IRP_MJ_CLOSE: {
kprintf(("Line %d:xia0ji233: ring3 calls CLOSE\n"), __LINE__);
break;
}
case IRP_MJ_READ: {
char *ptr1 = pirp->UserBuffer;
char *ptr2 = pirp->MdlAddress;
char *ptr3 = pirp->AssociatedIrp.SystemBuffer;
kprintf(("Line %d:xia0ji233: ring3 calls ReadFile ptr1=%p ptr2=%p ptr3=%p\n"), __LINE__, ptr1, ptr2, ptr3);
char msg[] = "xia0ji233 Read file";
if (ptr1&&irpStackL->Parameters.Read.Length > sizeof(msg)) {
strcpy(ptr1, msg);
pirp->IoStatus.Information = sizeof(msg);
}
break;
}
case IRP_MJ_WRITE: {
char *ptr1 = pirp->UserBuffer;
char *ptr2 = pirp->MdlAddress;
char *ptr3 = pirp->AssociatedIrp.SystemBuffer;
kprintf(("Line %d:xia0ji233: ring3 calls ReadFile ptr1=%p ptr2=%p ptr3=%p\n"), __LINE__, ptr1, ptr2, ptr3);
int len = strlen(ptr1);
kprintf(("Line %d:xia0ji233: ring3 write string %s,len=%d\n"), __LINE__, ptr1,len);
pirp->IoStatus.Information = len;
break;
}
default:
break;
}
pirp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pirp, IO_NO_INCREMENT);
kprintf(("Line %d:xia0ji233: leave IRP Function\n"), __LINE__);
return STATUS_SUCCESS;

}

void DriverUnload(PDRIVER_OBJECT pDriver) {
kprintf(("Line %d:xia0ji233: start unload\n"), __LINE__);
endProtect();
DeleteDevice(pDriver);
}

NTSTATUS DriverEntry(
_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath
) {

typedef struct _LDR_DATA
{
struct _LIST_ENTRY InLoadOrderLinks;
struct _LIST_ENTRY InMemoryOrderLinks;
struct _LIST_ENTRY InInitializationOrderLinks;
VOID* DllBase;
VOID* EntryPoint;
ULONG32 SizeOfImage;
UINT8 _PADDING0_[0x4];
struct _UNICODE_STRING FullDllName;
struct _UNICODE_STRING BaseDllName;
ULONG32 Flags;
}LDR_DATA, *PLDR_DATA;
PLDR_DATA ldr;
ldr = (PLDR_DATA)DriverObject->DriverSection;
ldr->Flags |= 0x20;

startProtect();

DriverObject->DriverUnload = DriverUnload;
DriverObject->MajorFunction[IRP_MJ_CREATE] = DeviceIrpCtl;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DeviceIrpCtl;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceIrpCtl;
DriverObject->MajorFunction[IRP_MJ_READ] = DeviceIrpCtl;
DriverObject->MajorFunction[IRP_MJ_WRITE] = DeviceIrpCtl;
CreateDevice(DriverObject);

kprintf(("Line %d:xia0ji233: RegistryPath = %S\n"), __LINE__, RegistryPath->Buffer);
kprintf(("Line %d:xia0ji233: work success\n"), __LINE__);

return 0;
}

void DeleteDevice(PDRIVER_OBJECT pDriver) {
kprintf(("Line %d:xia0ji233: start delete device\n"), __LINE__);
if (pDriver->DeviceObject) {
//删除符号链接
UNICODE_STRING Sym;//符号链接名字
RtlInitUnicodeString(&Sym, SYMBOL);//CreateFile
kprintf(("Line %d:xia0ji233: Delete Symbol\n"), __LINE__);
IoDeleteSymbolicLink(&Sym);
kprintf(("Line %d:xia0ji233: Delete Device\n"), __LINE__);
IoDeleteDevice(pDriver->DeviceObject);//删除设备对象
}
kprintf(("Line %d:xia0ji233: end delete device\n"), __LINE__);
}

protect.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#pragma once
#include<ntifs.h>
#define PROCESS_TERMINATE (0x0001)
#define PROCESS_CREATE_THREAD (0x0002)
#define PROCESS_SET_SESSIONID (0x0004)
#define PROCESS_VM_OPERATION (0x0008)
#define PROCESS_VM_READ (0x0010)
#define PROCESS_VM_WRITE (0x0020)
#define PROCESS_DUP_HANDLE (0x0040)
#define PROCESS_CREATE_PROCESS (0x0080)
#define PROCESS_SET_QUOTA (0x0100)
#define PROCESS_SET_INFORMATION (0x0200)
#define PROCESS_QUERY_INFORMATION (0x0400)
#define PROCESS_SUSPEND_RESUME (0x0800)
#define PROCESS_QUERY_LIMITED_INFORMATION (0x1000)
#define PROCESS_SET_LIMITED_INFORMATION (0x2000)
#define kprintf(format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, format, ##__VA_ARGS__)

void startProtect();

void endProtect();

protect.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
#include "Protect.h"
PVOID gs_HandleCallback;
NTKERNELAPI
UCHAR*
PsGetProcessImageFileName(
__in PEPROCESS Process
);
OB_PREOP_CALLBACK_STATUS MyProtect(
PVOID RegistrationContext,
POB_PRE_OPERATION_INFORMATION OperationInformation){
if (OperationInformation->KernelHandle) {

}
else {
ACCESS_MASK AccessBitsToClear = PROCESS_TERMINATE|PROCESS_VM_READ;
PEPROCESS process = (PEPROCESS)OperationInformation->Object;
PUCHAR processName = PsGetProcessImageFileName(process);
if (_stricmp((char *)processName, "msedge.exe") != 0) {
return OB_PREOP_SUCCESS;
}
ACCESS_MASK Origin = OperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess;
if(Origin&AccessBitsToClear){
if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE) {
OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~AccessBitsToClear;
}
if (OperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE) {
OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= ~AccessBitsToClear;
}

kprintf(("xia0ji233: old=%p new=%p\n"), Origin, OperationInformation->Parameters->CreateHandleInformation.DesiredAccess);
}



}
return OB_PREOP_SUCCESS;
}

void startProtect() {
OB_CALLBACK_REGISTRATION obl_callback_reg = { 0 };
OB_OPERATION_REGISTRATION ob2_operation = { 0 };
RtlInitUnicodeString(&obl_callback_reg.Altitude,L"321000");
obl_callback_reg.RegistrationContext = NULL;
obl_callback_reg.Version = OB_FLT_REGISTRATION_VERSION;//ObGetFilterVersion)://
obl_callback_reg.OperationRegistrationCount = 1;//只注册一个回调
obl_callback_reg.OperationRegistration = &ob2_operation;
ob2_operation.ObjectType = PsProcessType;//设置为进程事件,PsThreadType为线程事件
ob2_operation.Operations = OB_OPERATION_HANDLE_CREATE;
ob2_operation.PostOperation = NULL;
ob2_operation.PreOperation = MyProtect;//设置回调函数
ObRegisterCallbacks(&obl_callback_reg, &gs_HandleCallback);//注册回调,获得句柄,等会用于关闭
kprintf(("xia0ji233:Process Proctect start\n"));
kprintf(("xia0ji233:gs_HandleCallback=%p\n"), gs_HandleCallback);
}
void endProtect() {
if(gs_HandleCallback)ObUnRegisterCallbacks(gs_HandleCallback);
kprintf(("xia0ji233:Process Proctect end\n"));
}