首先是同步问题,通过Ring3创建事件,并将该事件传递给Ring0,同时Ring3创建监控线程,等待Ring0发起事件。
监控到事件(通知)
Ring0(监控)----------------------------------------------------------------> Ring3
应用层得到事件通知后,向驱动层发起数据获取请求。由Ring3主动发起,Ring0被动接受。
询问(CTL_CODE)
Ring3 ---------------------------------------------------------------- > Ring0
回答(通过OUT参数)
Ring3 <---------------------------------------------------------------- Ring0
具体实现:
应用层:
HANDLE hDevice = CreateFile("\\\\.\\PRMonitor", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, NULL); //打开设备 if(hDevice==INVALID_HANDLE_VALUE) { printf("Failed to obtain device with error code: %d\n",GetLastError()); getchar(); return; } DWORD dwOutput; char* OutputBuffer[256]; HANDLE m_hEvent = CreateEvent(NULL,FALSE,FALSE,NULL); //创建事件 DeviceIoControl(hDevice,IOCTL_STARTHOOK,&m_hEvent,sizeof(HANDLE),NULL,0,&dwOutput,NULL); //发事件给ring0 printf("IoControl code sent\n"); while(true) { WaitForSingleObject(m_hEvent,INFINITE); //等待ring0事件通知 DeviceIoControl(hDevice,IOCTL_GETINFO,NULL,0,&OutputBuffer,256,&dwOutput,NULL); //获取数据 printf("%s\n",OutputBuffer); ResetEvent(m_hEvent); //重置事件 }
驱动层:
PRKEVENT gpEventObject;
POBJECT_HANDLE_INFORMATION objHandleInfo;
NTSTATUS DevDispatch(PDEVICE_OBJECT DeviceObject,PIRP Irp) { PVOID pInBuffer; ULONG pInbufferSize; PVOID pOutBuffer; ULONG pOutbufferSize; NTSTATUS status; PIO_STACK_LOCATION ps = IoGetCurrentIrpStackLocation(Irp); switch(ps->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_STARTHOOK: //传送事件 if(!bProcMon) { ……
pInBuffer = Irp->AssociatedIrp.SystemBuffer; pInbufferSize = ps->Parameters.DeviceIoControl.InputBufferLength; if(pInBuffer == NULL || pInbufferSize < sizeof(HANDLE)) { KdPrint(("Set Event Error\n")); status = STATUS_INVALID_BUFFER_SIZE; break; } hEvent = *(HANDLE*)pInBuffer; status = ObReferenceObjectByHandle(hEvent, GENERIC_ALL, NULL, KernelMode, &gpEventObject, &objHandleInfo); KdPrint(("gpEventObject: %x\n",gpEventObject)); } break; case IOCTL_GETINFO: //传送数据 pOutBuffer = Irp->AssociatedIrp.SystemBuffer; pOutbufferSize = ps->Parameters.DeviceIoControl.OutputBufferLength; RtlCopyMemory(pOutBuffer,output,sizeof(output)); Irp->IoStatus.Information = pOutbufferSize; break; } ////////////////////////////////////////////////////////////////////////// Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp,IO_NO_INCREMENT); return STATUS_SUCCESS; }
在需要通知应用层事件的地方(比如监控到某一事件时)加上这一句
KeSetEvent(gpEventObject,0,FALSE);
这时应用层程序就会通过DeviceIoControl向驱动层请求数据。