应用程序中创建的事件和在内核中创建的事件对象,本质上是同一个东西,在用户模式中,他用句柄表示,在内核模式下,他用KEVENT表示数据结构表示。在应用程序中,所有的内核对象都不会被用户看到,用户看到的知识代表内核对象的对象句柄。
这个代码就是要在Ring3与RIng0之间用一个事件对象。解决的第一个问题就是如何将Ring3创建的事件传递给驱动:使用DeviceIoControl,在Ring3中创建一个同步事件,然后用DeviceIoControl将事件句柄传递给驱动程序。需要指出的是句柄和进程是相关的,也就是说一个进程的句柄只有在这个进程中有效。句柄相当于事件对象在进程中的索引,通过这个索引操作系统就可以得到事件对象的指针:ObReferenceObjectByHandle,函数返回一个状态值,表示是否成功获得指针这个函数在得到指针的同时,会为对象的指针维护一个计数,没记调用的时候会使计数+1。因此为了计数平衡,在使用玩ObReferenceObjectByHandle之后要调用ObDereferenceObject函数,它使计数-1
Ring0(设置事件).h
1 #include2 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 NULL154 );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 #include6 #include 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 INFINITE139 );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 }