Ring3创建事件Ring0设置事件
应用程序中创建的事件和在内核中创建的事件对象,本质上是同一个东西,在用户模式中,他用句柄表示,在内核模式下,他用KEVENT表示数据结构表示。在应用程序中,所有的内核对象都不会被用户看到,用户看到的知识代表内核对象的对象句柄。
这个代码就是要在Ring3与RIng0之间用一个事件对象。
解决的第一个问题就是如何将Ring3创建的事件传递给驱动:
使用DeviceIoControl,在Ring3中创建一个同步事件,然后用DeviceIoControl将事件句柄传递给驱动程序。需要指出的是句柄和进程是相关的,也就是说一个进程的句柄只有在这个进程中有效。句柄相当于事件对象在进程中的索引,通过这个索引操作系统就可以得到事件对象的指针:ObReferenceObjectByHandle,函数返回一个状态值,表示是否成功获得指针
这个函数在得到指针的同时,会为对象的指针维护一个计数,没记调用的时候会使计数+1。因此为了计数平衡,在使用玩ObReferenceObjectByHandle之后要调用ObDereferenceObject函数,它使计数-1
Ring0(设置事件).h
1 #include <ntifs.h> 2 3 #define CTL_EVENT \ 4 CTL_CODE(FILE_DEVICE_UNKNOWN,0x830,METHOD_BUFFERED,FILE_ANY_ACCESS) 5 #define CTL_SET_EVENT \ 6 CTL_CODE(FILE_DEVICE_UNKNOWN,0x831,METHOD_BUFFERED,FILE_ANY_ACCESS) 7 8 #define DEVICE_OBJECT_NAME L"\\Device\\Ring0DeviceObjectName" 9 10 #define DEVICE_LINK_NAME L"\\DosDevices\\Ring0DeviceLinkName" 11 12 13 14 15 16 17 NTSTATUS PassThroughDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp); 18 19 NTSTATUS ControlThroughDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp); 20 21 NTSTATUS Ring3EventHandleToRing0KernelEvent(HANDLE* EventHandle, ULONG_PTR EventHandleCount); 22 23 24 VOID DriverUnload(PDRIVER_OBJECT DriverObject);
Ring0(设置事件).c
1 #include "Ring0(设置事件).h" 2 3 PKEVENT __KernelEvent[20] = { 0 }; 4 ULONG_PTR __KernelEventCount = 0; 5 6 extern 7 POBJECT_TYPE* ExEventObjectType; 8 9 NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegisterPath) 10 { 11 NTSTATUS Status = STATUS_SUCCESS; 12 PDEVICE_OBJECT DeviceObject = NULL; 13 UNICODE_STRING DeviceObjectName; 14 UNICODE_STRING DeviceLinkName; 15 16 17 DbgPrint("DriverEntry()\r\n"); 18 DriverObject->DriverUnload = DriverUnload; 19 20 RtlInitUnicodeString(&DeviceObjectName, DEVICE_OBJECT_NAME); 21 22 Status = IoCreateDevice( 23 DriverObject, 24 NULL, 25 &DeviceObjectName, 26 FILE_DEVICE_UNKNOWN, 27 0, 28 FALSE, 29 &DeviceObject 30 ); 31 if (!NT_SUCCESS(Status)) 32 { 33 return Status; 34 } 35 36 //创建设备连接名称 37 RtlInitUnicodeString(&DeviceLinkName, DEVICE_LINK_NAME); 38 39 //将设备连接名称与设备名称关联 40 Status = IoCreateSymbolicLink(&DeviceLinkName, &DeviceObjectName); 41 if (!NT_SUCCESS(Status)) 42 { 43 IoDeleteDevice(DeviceObject); 44 return Status; 45 } 46 47 //我们要的派遣函数 48 for (int i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) 49 { 50 DriverObject->MajorFunction[i] = PassThroughDispatch; 51 } 52 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ControlThroughDispatch; 53 54 55 56 return Status; 57 } 58 59 60 61 62 63 64 NTSTATUS ControlThroughDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) 65 { 66 NTSTATUS Status = STATUS_UNSUCCESSFUL; 67 ULONG_PTR Information = 0; 68 PVOID InputData = NULL; 69 ULONG InputDataLength = 0; 70 PVOID OutputData = NULL; 71 ULONG OutputDataLength = 0; 72 ULONG IoControlCode = 0; 73 PEPROCESS EProcess = NULL; 74 PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp); //Irp堆栈 75 IoControlCode = IoStackLocation->Parameters.DeviceIoControl.IoControlCode; 76 InputData = Irp->AssociatedIrp.SystemBuffer; 77 OutputData = Irp->AssociatedIrp.SystemBuffer; 78 InputDataLength = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength; 79 OutputDataLength = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength; 80 switch (IoControlCode) 81 { 82 case CTL_EVENT: 83 { 84 85 if (InputData != NULL&&InputDataLength == sizeof(HANDLE) * 2) 86 { 87 88 Status = Ring3EventHandleToRing0KernelEvent((HANDLE*)InputData, InputDataLength / sizeof(HANDLE)); 89 90 } 91 92 93 Information = 0; 94 95 break; 96 97 } 98 99 case CTL_SET_EVENT: 100 { 101 102 DbgPrint("Ring0触发Ring3\r\n"); 103 KeSetEvent(__KernelEvent[0], IO_NO_INCREMENT, FALSE); 104 105 DbgPrint("Ring0等待\r\n"); 106 Status = KeWaitForSingleObject(__KernelEvent[1], 107 Executive, KernelMode, FALSE, NULL); //注意这里的最后一个参数NULL 是永久等待 108 109 DbgPrint("Ring3触发Ring0\r\n"); 110 111 Information = 0; 112 break; 113 114 } 115 116 default: 117 { 118 119 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; 120 Irp->IoStatus.Information = 0; 121 122 123 124 break; 125 } 126 } 127 128 Irp->IoStatus.Status = Status; 129 Irp->IoStatus.Information = Information; 130 IoCompleteRequest(Irp, IO_NO_INCREMENT); 131 return Status; 132 } 133 134 NTSTATUS Ring3EventHandleToRing0KernelEvent(HANDLE* EventHandle, ULONG_PTR EventHandleCount) 135 { 136 NTSTATUS Status = STATUS_SUCCESS; 137 PULONG_PTR HandleArray = NULL; 138 ULONG i = 0; 139 140 if (EventHandle == NULL) 141 { 142 return STATUS_UNSUCCESSFUL; 143 } 144 __KernelEventCount = EventHandleCount; 145 146 for (i = 0; i < EventHandleCount; i++) 147 { 148 Status = ObReferenceObjectByHandle((HANDLE)EventHandle[i], 149 SYNCHRONIZE, 150 *ExEventObjectType, 151 KernelMode, 152 &__KernelEvent[i], 153 NULL 154 ); 155 if (!NT_SUCCESS(Status)) 156 { 157 break; 158 } 159 } 160 161 if (Status != STATUS_SUCCESS) 162 { 163 for (i = 0; i < EventHandleCount; i++) 164 { 165 if (__KernelEvent[i] != NULL) 166 { 167 ObDereferenceObject(__KernelEvent[i]); 168 169 __KernelEvent[i] = NULL; 170 } 171 } 172 } 173 return Status; 174 } 175 176 VOID DriverUnload(PDRIVER_OBJECT DriverObject) 177 { 178 179 DbgPrint("DriverUnload()\r\n"); 180 } 181 182 183 184 185 186 NTSTATUS PassThroughDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) 187 { 188 Irp->IoStatus.Status = STATUS_SUCCESS; //LastError() 189 Irp->IoStatus.Information = 0; //ReturnLength 190 IoCompleteRequest(Irp, IO_NO_INCREMENT); //将Irp返回给Io管理器 191 return STATUS_SUCCESS; 192 }
Ring3(创建事件).cpp
1 // Ring3(创建事件).cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include <windows.h> 6 #include <iostream> 7 8 using namespace std; 9 10 #define CTL_EVENT \ 11 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x830, METHOD_BUFFERED, FILE_ANY_ACCESS) 12 13 #define CTL_SET_EVENT \ 14 CTL_CODE(FILE_DEVICE_UNKNOWN,0x831,METHOD_BUFFERED,FILE_ANY_ACCESS) 15 16 #define DeviceLinkName L"\\\\.\\Ring0DeviceLinkName" 17 18 19 DWORD WINAPI ThreadProc(LPVOID ParameterData); 20 21 int main() 22 { 23 HANDLE DeviceHandle = CreateFile( 24 DeviceLinkName, 25 GENERIC_READ | GENERIC_WRITE, 26 FILE_SHARE_READ | FILE_SHARE_WRITE, 27 NULL, 28 OPEN_EXISTING, 29 FILE_ATTRIBUTE_NORMAL, 30 NULL); 31 32 33 if (DeviceHandle == INVALID_HANDLE_VALUE) 34 { 35 cout << "CreateFile FAIL " << GetLastError() << endl; 36 return 0; 37 } 38 39 HANDLE EventHandle[3]; 40 for (int i = 0; i < 3; i++) 41 { 42 //用户模式同步事件 43 EventHandle[i] = CreateEvent( 44 NULL, 45 FALSE, 46 FALSE, 47 NULL 48 ); 49 } 50 BOOL IsOK = FALSE; 51 52 DWORD ReturnLength = 0; 53 54 IsOK = DeviceIoControl( 55 DeviceHandle, 56 CTL_EVENT, 57 EventHandle, 58 sizeof(HANDLE)*2, 59 NULL, 60 0, 61 &ReturnLength, 62 NULL 63 ); 64 65 if (IsOK == FALSE) 66 { 67 goto Final; 68 } 69 //辅助线程 70 HANDLE ThreadHandle = CreateThread( 71 NULL, 72 0, 73 (LPTHREAD_START_ROUTINE)ThreadProc, 74 (LPVOID)EventHandle, 75 0, 76 NULL 77 ); 78 79 IsOK = DeviceIoControl( 80 DeviceHandle, 81 CTL_SET_EVENT, 82 NULL, 83 0, 84 NULL, 85 0, 86 &ReturnLength, 87 NULL); 88 89 if (IsOK == FALSE) 90 { 91 cout << "Send IoCode Error" << endl; 92 SetEvent(EventHandle[2]); 93 WaitForSingleObject(ThreadHandle, INFINITE); 94 goto Final; 95 } 96 97 98 WaitForSingleObject(ThreadHandle, INFINITE); 99 100 101 Final: 102 { 103 for (int i = 0; i < 3; i++) 104 { 105 if (EventHandle[i] != NULL) 106 { 107 CloseHandle(EventHandle[i]); 108 EventHandle[i] = NULL; 109 } 110 } 111 if (ThreadHandle != NULL) 112 { 113 CloseHandle(ThreadHandle); 114 ThreadHandle = NULL; 115 } 116 if (DeviceHandle != NULL) 117 { 118 CloseHandle(DeviceHandle); 119 DeviceHandle = NULL; 120 } 121 122 } 123 124 printf("先卸载驱动\r\n"); 125 printf("Input AnyKey To Exit\r\n"); 126 127 getchar(); 128 return 0; 129 } 130 131 DWORD WINAPI ThreadProc(LPVOID ParameterData) 132 { 133 cout << "Ring3 等啊等" << endl; 134 DWORD Index = WaitForMultipleObjects( 135 3, 136 (HANDLE*)ParameterData, 137 FALSE, 138 INFINITE 139 ); 140 141 if (Index == 2) 142 { 143 cout << "ThreadProc EXIT " << endl; 144 return 0; 145 } 146 cout << "Ring0触发Ring3" << endl; 147 148 cout << "put any key Ring3 触发Ring0" << endl; 149 150 getchar(); 151 getchar(); 152 153 154 SetEvent(((HANDLE*)ParameterData)[1]); 155 cout << "ThreadProc EXIT" << endl; 156 return 0; 157 158 159 160 161 }