驱动开发-R0与R3通信

驱动开发:应用DeviceIoContro模板精讲 (opens new window)

R0

#include <ntifs.h>

#define DEVICE_NAME L"\\Device\\KDTest"
#define SYMBOLICLINK_NAME L"\\??\\KDTestLnk"

#define OPER1 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x700, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define OPER2 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define OPER3 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS)

VOID DriverUnload(PDRIVER_OBJECT pDriver);

NTSTATUS IrpCreateProc(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS IrpCloseProc(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS IrpDeviceControlProc(PDEVICE_OBJECT pDevObj, PIRP pIrp);


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

	RegistryPath;
	KdPrint(("qsir:r0:进入驱动入口 DriverObject=%p RegistryPath=%ws 行号=%d\n", DriverObject, RegistryPath->Buffer, __LINE__));

	// 0.设置分发回调函数
	DriverObject->DriverUnload = DriverUnload;
	DriverObject->MajorFunction[IRP_MJ_CREATE] = IrpCreateProc;
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = IrpCloseProc;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IrpDeviceControlProc;


	PDEVICE_OBJECT DeviceObject = NULL; // 设备对象指针
	UNICODE_STRING DeviceName;        // 设备名,0环用
	UNICODE_STRING SymbolicLinkName;  // 符号链接名,3环用

	// 1.创建设备 根据驱动对象生成设备对象 并关联设备名
	RtlInitUnicodeString(&DeviceName, DEVICE_NAME);
	NTSTATUS status = IoCreateDevice(DriverObject, 0, &DeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &DeviceObject);
	if (status != STATUS_SUCCESS)
	{
		IoDeleteDevice(DeviceObject);
		DbgPrint("qsir:r0:创建设备失败.\n");
		return status;
	}
	DbgPrint("qsir:创建设备成功.\n");

	// 2.创建符号链接 根据设备名设置符号链接
	RtlInitUnicodeString(&SymbolicLinkName, SYMBOLICLINK_NAME);
	IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);

	return STATUS_SUCCESS;
}

void DriverUnload(PDRIVER_OBJECT DriverObject)
{
	KdPrint(("qsir:r0:进入驱动卸载\n"));
	// 删除符号链接
	UNICODE_STRING SymbolicLinkName;
	RtlInitUnicodeString(&SymbolicLinkName, SYMBOLICLINK_NAME);
	IoDeleteSymbolicLink(&SymbolicLinkName);
	// 删除设备对象
	IoDeleteDevice(DriverObject->DeviceObject);
}

// 不设置这个函数,则Ring3调用CreateFile会返回1
// IRP_MJ_CREATE 处理函数
NTSTATUS IrpCreateProc(PDEVICE_OBJECT DeviceObject, PIRP pIrp)
{
	DbgPrint("qsir:r0:进入IrpCreateProc\n");
	DeviceObject;
	// 返回状态如果不设置,Ring3返回值是失败
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

// IRP_MJ_CLOSE 处理函数
NTSTATUS IrpCloseProc(PDEVICE_OBJECT DeviceObject, PIRP pIrp)
{
	DeviceObject;
	DbgPrint("qsir:r0:进入IrpCloseProc\n");
	// 返回状态如果不设置,Ring3返回值是失败
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

// IRP_MJ_DEVICE_CONTROL 处理函数
NTSTATUS IrpDeviceControlProc(PDEVICE_OBJECT DeviceObject, PIRP pIrp)
{
	DbgPrint("qsir:r0:进入IrpDeviceControlProc\n");
	DeviceObject;
	NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;

	PIO_STACK_LOCATION pIrpStack;
	ULONG uIoControlCode;
	PVOID pIoBuffer;
	ULONG uInLength;
	ULONG uOutLength;
	ULONG uRead;
	ULONG uWrite;

	// 设置临时变量的值
	uRead = 0;
	uWrite = 0x12345678;
	// 获取IRP数据
	pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
	// 获取控制码
	uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
	// 获取缓冲区地址(输入输出是同一个)
	pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
	// Ring3 发送数据的长度
	uInLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
	// Ring0 发送数据的长度
	uOutLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;

	DbgPrint("qsir:r0:控制码=%X,缓冲区=%s,inLen=%d,outLen=%d\n", uIoControlCode, pIoBuffer, uInLength, uOutLength);

	switch (uIoControlCode)
	{
	case OPER1:
	{
		DbgPrint("qsir:r0:进入OPER1\n");
		pIrp->IoStatus.Information = 0;
		status = STATUS_SUCCESS;
		break;
	}
	case OPER2:
	{
		DbgPrint("qsir:r0:进入OPER2\n");
		// 读取缓冲区
		memcpy(&uRead, pIoBuffer, 4);

		// 杀进程
		//KillProcessByPid(g_driver, uRead);
		// DbgPrint("IrpDeviceControlProc -> OPER2 uRead: %x\n", uRead);

		// 写入缓冲区
		memcpy(pIoBuffer, &uWrite, 4);
		// 设置状态
		pIrp->IoStatus.Information = 2; // 实际返回两字节 = R3 中的 lpBytesReturned 
		status = STATUS_SUCCESS;
		break;
	}
	case OPER3:
	{
		DbgPrint("qsir:r0:进入OPER3\n");

		int *p = (int*)pIoBuffer;

		int result = p[0] + p[1] + p[2];

		DbgPrint("qsir:r0:(%d+%d+%d)=%d\n", p[0], p[1], p[2],result);

		// 写入缓冲区
		memcpy(pIoBuffer, &result, sizeof(result));

		pIrp->IoStatus.Information = sizeof(result);
		status = STATUS_SUCCESS;
		break;
	}
	}

	// 返回状态如果不设置,Ring3返回值是失败
	pIrp->IoStatus.Status = status;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

copy success
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

R3


#include <winioctl.h>

#define SYMBOLICLINK_NAME L"\\??\\KDTestLnk"

#define OPER1 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x700, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define OPER2 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define OPER3 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS)


static HANDLE gDeviceHandle = NULL; //全局驱动设备句柄

void CKDTestMFCDlg::OnBnClickedButton1Create()
{
	// 获取设备句柄 会产生IRP_MJ_CREATE 事件
	gDeviceHandle = CreateFileW(SYMBOLICLINK_NAME, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
	DWORD dwError = GetLastError();
	if (gDeviceHandle == NULL)
	{
		return;
	}
	//MessageBoxW(L"获取驱动设备句柄成功", L"提示", (MB_OK | MB_ICONINFORMATION));
	OutputDebugStringW(L"qsir:r3;获取驱动设备句柄成功\n");
}


void CKDTestMFCDlg::OnBnClickedButton2Close()
{
	//关闭驱动设备 会产生IRP_MJ_CLOSE 事件
	CloseHandle(gDeviceHandle);
	OutputDebugStringW(L"qsir:r3;关闭驱动设备句柄\n");
}


void CKDTestMFCDlg::OnBnClickedButton3Io()
{
	char buftest[256];
	sprintf_s(buftest, "qsirr3: 控制码=%X\n", OPER1);
	OutputDebugStringA(buftest);

	DWORD dwRetSize = 0;//返回字节数

	char InBuf[] = "hello qsir";
	char OutBuf[1] = { 0 };

	DeviceIoControl(gDeviceHandle, OPER1, InBuf, sizeof(InBuf), &OutBuf, sizeof(OutBuf), &dwRetSize, NULL);
}


void CKDTestMFCDlg::OnBnClickedButton3Io2()
{
	char buftest[256];
	sprintf_s(buftest, "qsirr3: 控制码=%X\n", OPER2);
	OutputDebugStringA(buftest);

	DWORD dwRetSize = 0;//返回字节数

	char InBuf[] = "hello qsir";
	DWORD OutBuf = 0xFFFFFFFF;

	DeviceIoControl(gDeviceHandle, OPER2, InBuf, sizeof(InBuf), &OutBuf, sizeof(OutBuf), &dwRetSize, NULL);

	sprintf_s(buftest, "qsirR3: OutBuf=%08X dwRetSize=%08X\n", OutBuf,dwRetSize);
	OutputDebugStringA(buftest);
}


void CKDTestMFCDlg::OnBnClickedButton3Io3()
{
	char buftest[256];
	sprintf_s(buftest, "qsirr3: 控制码=%X\n", OPER3);
	OutputDebugStringA(buftest);

	DWORD dwRetSize = 0;//返回字节数

	int InBuf[] = { 3,7,8 };
	int OutBuf = 0;

	DeviceIoControl(gDeviceHandle, OPER3, InBuf, sizeof(InBuf), &OutBuf, sizeof(OutBuf), &dwRetSize, NULL);

	sprintf_s(buftest, "qsirR3: OutBuf=%08X dwRetSize=%08X\n", OutBuf,dwRetSize);
	OutputDebugStringA(buftest);
}


copy success
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