在内核中保护特定进程

本来想着掌握一种方法差不多就够了,后面想想还是一步一步走过来吧。

获取进程名

在回调中,每有一个进程相关事件,就会触发这个回调。一般我们很多跨进程的操作第一步都是 OpenProcess 去获得进程句柄,后续操作都通过句柄操作。在回调函数中我们可以使用 OperationInformation->Object 这个对象拿到当前被操作进程的结构体指针。

这样子我们获得了一个 EProcess 的指针,可以用这个所指向的结构来取得进程名,通过访问使用API PsGetProcessImageFileName 来获得进程名。

最后我们使用 _stricmp((char *)processName, "msedge.exe") 进行一波判断即可。

通过进程ID保护进程

同样,还有一个 API 是 PsGetCurrentProcessId 用来获取当前进程的 pid 的,同样我们可以使用这个 API 来和预期的进程 id 进行比较,相同就保护起来,因为我们很可能不确定要保护的进程 ID 是多少,因此不能再 sys 中写死,我们可能需要实现一些驱动设备的读写让 R3 给出进程 id 让 R0 去保护这些进程。

但是这里需要注意的是,在打开进程的过程中,出现了两个对象,一个是主动请求打开进程的进程,一个是被打开的进程。我们可以使用 PEPROCESS pEprocess = (PEPROCESS)OperationInformation->Object; 来得到被操作的进程结构体,然后可以用 PsGetCurrentProcessId 来得到当前进程的 id。

再使用三环和零环通信的思路,去实时添加自己要保护进程的pid,这里多定义两个控制码,使用 deviceIoControl 去写入 pid。

最后成功实现保护指定pid的进程。

最终代码

三环测试程序

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
// Ring3Test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <windows.h>
#include<iostream>
#define SYMBOL L"\\??\\xia0ji2333"
#define ProtectCode CTL_CODE (FILE_DEVICE_UNKNOWN,0x806,METHOD_BUFFERED, FILE_ANY_ACCESS)
#define UnProtectCode CTL_CODE (FILE_DEVICE_UNKNOWN,0x807,METHOD_BUFFERED, FILE_ANY_ACCESS)

HANDLE DeviceHandle;
void menu() {
printf("------------------------\n");
printf("1.create\n");
printf("2.close\n");
printf("3.protect\n");
printf("4.unprotect\n");
printf("------------------------\n");
printf("Your choice:");
}
void create() {
DeviceHandle = CreateFile(SYMBOL, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
}
void close() {
CloseHandle(DeviceHandle);
}
void protect(){
int Pid;
DWORD dwRetSize;
printf("Enter Your Pid you want to Protect>");
scanf("%d",&Pid);
DeviceIoControl(
DeviceHandle,//CreateFile打开驱动设备 返回的句柄
ProtectCode,//控制码 CTL_CODE
&Pid,//输入缓冲区指针
sizeof(Pid),//输入缓冲区大小
NULL,//返回缓冲区
0,//返回缓冲区大小
&dwRetSize,//返回字节数
NULL
);
if (dwRetSize == -1) {
printf("Protect Error\n");
}
else {
printf("Successfully Protect Process Pid=%d\n", Pid);
}
}
void unprotect() {
int Pid;
DWORD dwRetSize;
printf("Enter Your Pid you want to Protect>");
scanf("%d", &Pid);
DeviceIoControl(
DeviceHandle,//CreateFile打开驱动设备 返回的句柄
UnProtectCode,//控制码 CTL_CODE
&Pid,//输入缓冲区指针
sizeof(Pid),//输入缓冲区大小
NULL,//返回缓冲区
0,//返回缓冲区大小
&dwRetSize,//返回字节数
NULL
);
if (dwRetSize == -1) {
printf("UnProtect Error\n");
}
else {
printf("Successfully UnProtect Process Pid=%d\n", Pid);
}
}
int main()
{
while (1) {
int ch;
menu();
scanf("%d", &ch);
switch (ch)
{
case 1:
create();
break;
case 2:
close();
break;
case 3:
protect();
break;
case 4:
unprotect();
break;
default:
exit(0);
break;
}
}
}

驱动程序

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
#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)
#define ProtectCode CTL_CODE (FILE_DEVICE_UNKNOWN,0x806,METHOD_BUFFERED, FILE_ANY_ACCESS)
#define UnProtectCode CTL_CODE (FILE_DEVICE_UNKNOWN,0x807,METHOD_BUFFERED, FILE_ANY_ACCESS)

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 ProtectCode: {
ULONG PID = *(ULONG *)pirp->AssociatedIrp.SystemBuffer;
kprintf(("Line %d:xia0ji233: start Protect PID=%d\n"), __LINE__,PID);
int i = 0;
while (ProtectPid[i] && i < MAXPROTECT)i++;
pirp->IoStatus.Information = -1;
if (i != MAXPROTECT) {//超过保护进程个数,返回错误
ProtectPid[i] = PID;
pirp->IoStatus.Information = 0;
}
break;
}
case UnProtectCode: {
ULONG PID = *(ULONG *)pirp->AssociatedIrp.SystemBuffer;
kprintf(("Line %d:xia0ji233: end Protect PID=%d\n"), __LINE__, PID);
int i = 0;
while (ProtectPid[i]!=PID && i < MAXPROTECT)i++;
pirp->IoStatus.Information = -1;
if (i != MAXPROTECT) {//超过保护进程个数,返回错误
ProtectPid[i] = 0;
pirp->IoStatus.Information = 0;
}
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;
}
default:
break;
}
pirp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pirp, IO_NO_INCREMENT);
kprintf(("Line %d:xia0ji233: leave IRP Function\n"), __LINE__);
return STATUS_SUCCESS;

}

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);
}
}

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__);
}

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;
}

Protect.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#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 MAXPROTECT 10
#define kprintf(format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, format, ##__VA_ARGS__)
void startProtect();

void endProtect();

ULONG ProtectPid[MAXPROTECT];

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
59
60
61
62
63
64
#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 {

ULONG PID = PsGetCurrentProcessId();
int flag = 1;

PEPROCESS pEprocess = (PEPROCESS)OperationInformation->Object;
ULONG dwpid=PsGetProcessId(pEprocess);

for (int i = 0; i < MAXPROTECT; i++) {
if (dwpid == ProtectPid[i]) {
flag = 0;
}
}
if (flag)return OB_PREOP_SUCCESS;

kprintf(("start protect:PID=%d\n"), PID);

ACCESS_MASK AccessBitsToClear = PROCESS_TERMINATE | PROCESS_VM_READ;
ACCESS_MASK Origin = OperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess;
//if (Origin&AccessBitsToClear) {
OperationInformation->Parameters->CreateHandleInformation.DesiredAccess = Origin&~AccessBitsToClear;
OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess= Origin & ~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"));
}