Ring3创建事件Ring0设置事件

Posted 生如逆旅 一苇以航

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }

 

以上是关于Ring3创建事件Ring0设置事件的主要内容,如果未能解决你的问题,请参考以下文章

ring0和ring3的区别

Ring3 和Ring0 解释

全虚拟化和半虚拟化的区别 cpu的ring0~ring3又是什么概念?

ring0

杀毒软件运行在ring0下还是ring3下?

跟踪 Ring3 - Ring0 的运行流程