用户态使用事件对象event与内核态交互
在用户态创建一个事件,得到句柄,传入到驱动中,驱动中发生某件事情时触发此事件。
下面代码中在用户创建一个事件句柄,将句柄值通过DeviceIoControl传入驱动中,在驱动中调用ObReferenceObjectByHandle回去句柄对象的指针,然后创建一个系统线程,触发此对象。
用户态返回后等待此事件对象是可以成功的,说明内核态中触发事件对象成功了。在内核态任意线程触发此事件指针都可以,记住不再使用事件对象时需要使用ObReferenceObjectByHandle递减驱动中的事件指针计数。
运行截图如下:

内核调试器打印如下:

用户态函数如下:
#define CTL_SYSSendEvent \
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x850, METHOD_BUFFERED, FILE_WRITE_ACCESS)
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, L"");
printf("hEvent:%x\n", hEvent);
HANDLE hSys = CreateFile(L"\\\\.\\SysSetEvent", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
printf("hSys:%x\n", hSys);
DWORD dRetLength = 0;
if (DeviceIoControl(hSys, CTL_SYSSendEvent, &hEvent, sizeof(HANDLE), NULL, 0, &dRetLength, 0))
{
printf("CTL_SYSSendEvent success");
getchar();
DWORD dWait = WaitForSingleObject(hEvent, INFINITE);
if (WAIT_OBJECT_0 == dWait)
{
printf("WAIT_OBJECT_0 success");
}
}
else
printf("CTL_SYSSendEvent error:%d", GetLastError());
getchar();
return 0;
}
内核态代码如下:
#include <ntddk.h>
PDEVICE_OBJECT gloDevice = NULL;
#define CTL_SYSSendEvent \
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x850, METHOD_BUFFERED, FILE_WRITE_ACCESS)
VOID threadProc(_In_ PVOID StartContext)
{
PVOID object = StartContext;
KeSetEvent(object, IO_NO_INCREMENT, FALSE);
DbgPrint("threadProc ThreadId:%d irql:%d\r\n", PsGetCurrentThreadId(), KeGetCurrentIrql());
ObDereferenceObject(object);
object = NULL;
PsTerminateSystemThread(STATUS_SUCCESS);
}
NTSTATUS driverDispatch(PDEVICE_OBJECT device, PIRP irp)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(irp);
if (IRP_MJ_DEVICE_CONTROL == irpsp->MajorFunction)
{
PVOID buffer = irp->AssociatedIrp.SystemBuffer;
ULONG inlen = irpsp->Parameters.DeviceIoControl.InputBufferLength;
switch (irpsp->Parameters.DeviceIoControl.IoControlCode)
{
case CTL_SYSSendEvent:
{
DbgPrint("CTL_SYSSendEvent ThreadId:%d irql:%d\r\n", PsGetCurrentThreadId(), KeGetCurrentIrql());
if (buffer == NULL || inlen != sizeof(HANDLE))
{
status = STATUS_INVALID_PARAMETER;
break;
}
HANDLE hEvent = *(HANDLE*)buffer;
PVOID object = NULL;
status = ObReferenceObjectByHandle(hEvent, EVENT_MODIFY_STATE,
*ExEventObjectType, UserMode, &object, NULL);
if (NT_SUCCESS(status))
{
HANDLE thread = NULL;
status = PsCreateSystemThread(&thread, 0, NULL, NULL, NULL, threadProc, object);
if (NT_SUCCESS(status))
{
ZwClose(thread);
}
else
{
ObDereferenceObject(object);
object = NULL;
}
}
break;
}
default:
break;
}
}
irp->IoStatus.Information = 0;
irp->IoStatus.Status = status;
IoCompleteRequest(irp, IO_NO_INCREMENT);
return status;
}
void DriverUnload(PDRIVER_OBJECT pDriver)
{
UNREFERENCED_PARAMETER(pDriver);
if (NULL != gloDevice)
{
IoDeleteDevice(gloDevice);
gloDevice = NULL;
UNICODE_STRING name_sym = RTL_CONSTANT_STRING(L"\\??\\SysSetEvent");
IoDeleteSymbolicLink(&name_sym);
}
return;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pRegisterPath)
{
NTSTATUS status = STATUS_SUCCESS;
if (pDriver)
{
//创建一个设备
UNICODE_STRING name_Device = RTL_CONSTANT_STRING(L"\\Device\\SysSetEvent");
PDEVICE_OBJECT device = NULL;
status = IoCreateDevice(pDriver, //创建的设备任意用户都可以打开 不安全
0,
&name_Device,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&gloDevice);
UNICODE_STRING name_sym = RTL_CONSTANT_STRING(L"\\??\\SysSetEvent");
IoCreateSymbolicLink(&name_sym, &name_Device);
for (size_t i = 0; i<IRP_MJ_MAXIMUM_FUNCTION; i++)
{
pDriver->MajorFunction[i] = driverDispatch;
}
pDriver->DriverUnload = DriverUnload;
}
return status;
}

浙公网安备 33010602011771号