首先是同步问题,通过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向驱动层请求数据。