0x00 函数
ObReferenceObjectByHandle //通过句柄获取内核资源
ObDereferenceObject //释放资源
0x01 代码
桌面程序
#include <windows.h>
#include <stdio.h>
#define IOCTL_CREATE_EVENT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x999, METHOD_BUFFERED , FILE_READ_DATA | FILE_WRITE_DATA)
HANDLE customEvent = NULL;
HANDLE handle = NULL;
DWORD WINAPI ThreadProc(_In_ LPVOID lpParameter)
{
for (int i = 0; i < 10; i++)
{
Sleep(1500);
printf("\nThreadProc %d", i);
SetEvent(customEvent);
}
printf("\nThreadProc end");
//Sleep(4000);
CloseHandle(customEvent);
CloseHandle(handle);
return 0;
}
int main(int argc, char* grav[])
{
HANDLE thread = NULL;
LPCWSTR eventNanme = L"CustomEvent";
DWORD BytesReturned = 0;
printf("CreateFile\n");
system("pause");
handle = CreateFile(L"\\\\.\\EventDriver", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (handle == INVALID_HANDLE_VALUE)
{
printf("handle INVALID_HANDLE_VALUE:%d\n", GetLastError());
system("pause");
return 0;
}
printf("CreateEvent\n");
customEvent = CreateEvent(NULL, FALSE, FALSE, eventNanme);
printf("main -> customEvent:%p \n", customEvent);
if (customEvent == INVALID_HANDLE_VALUE)
{
CloseHandle(handle);
printf("customEvent INVALID_HANDLE_VALUE\n");
system("pause");
return 0;
}
printf("DeviceIoControl\n");
system("pause");
if (DeviceIoControl(handle, IOCTL_CREATE_EVENT, &customEvent, sizeof(HANDLE), NULL, 0, &BytesReturned, NULL))
{
if (BytesReturned)
{
printf("DeviceIoControl -> CreateThread");
//创建线程
thread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
if (thread == INVALID_HANDLE_VALUE)
{
CloseHandle(handle);
CloseHandle(customEvent);
printf("CreateThread failed\n");
system("pause");
return 0;
}
printf("CreateThread success\n");
CloseHandle(thread);
}
else
{
printf("DeviceIoControl BytesReturned -> FALSE ");
}
}
else
{
printf("DeviceIoControl failed\n");
}
printf("main success\n");
system("pause");
return 0;
}
驱动程序
#include <Ntddk.h>
#include <wdm.h>
#define IOCTL_CREATE_EVENT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x999, METHOD_BUFFERED , FILE_READ_DATA | FILE_WRITE_DATA)
KSTART_ROUTINE KstartRoutine1;
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
if (DriverObject->DeviceObject)
{
DbgPrint("DriverUnload->IoDeleteDevice");
IoDeleteDevice(DriverObject->DeviceObject);
UNICODE_STRING SysmbolicLinkNmae = { 0 };
RtlInitUnicodeString(&SysmbolicLinkNmae, L"\\??\\EventDriver");
IoDeleteSymbolicLink(&SysmbolicLinkNmae);
}
DbgPrint("DriverUnload");
}
void KstartRoutine(PVOID StartContext)
{
PKEVENT pkEvent = (PKEVENT) StartContext;
LARGE_INTEGER Timeout = { 0 };
Timeout.QuadPart = -10 * 1000 * 1000 * 3; //5秒 -> 单位为100纳秒,*10 = 微秒,*10*1000 = 毫秒,*10*1000*1000 = 秒
NTSTATUS status = STATUS_SUCCESS;
int i = 0;
while(TRUE)
{
DbgPrint("pkEvent %p | KstartRoutine -> KeWaitForSingleObject Start", pkEvent);
status = KeWaitForSingleObject(pkEvent, Executive, KernelMode, FALSE, &Timeout); //等待
i++;
if (status != STATUS_SUCCESS)
{
DbgPrint("pkEvent %p | KstartRoutine -> KeWaitForSingleObject Timeout index:%d ", pkEvent,i);
break;
}
DbgPrint("pkEvent %p | KstartRoutine -> KeWaitForSingleObject End, index:%d ", pkEvent, i);
}
DbgPrint("pkEvent %p | KstartRoutine End", pkEvent);
ObDereferenceObject(pkEvent); //释放资源
PsTerminateSystemThread(0);
}
NTSTATUS MyDispatchControl(PDEVICE_OBJECT DeviceObjct, PIRP Irp)
{
NTSTATUS status = STATUS_SUCCESS;
HANDLE customEvent = NULL;
HANDLE thread = NULL;
PKEVENT pkEvent = NULL;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); //获取堆信息
DbgPrint("MyDispatchControl");
//IrpSp->Parameters.DeviceIoControl.IoControlCode -> 用户层传入的指定代码
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_CREATE_EVENT:
Irp->IoStatus.Information = TRUE; //返回给R3的附加信息
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(HANDLE))
{
Irp->IoStatus.Information = FALSE; //返回给R3的附加信息
break;
}
RtlCopyMemory(&customEvent, Irp->AssociatedIrp.SystemBuffer, sizeof(HANDLE)); //获取句柄
DbgPrint("MyDispatchControl -> customEvent : %p", customEvent);
status = ObReferenceObjectByHandle(customEvent, EVENT_MODIFY_STATE, *ExEventObjectType, KernelMode, &pkEvent, NULL); //根据句柄获取内核对象
if (!NT_SUCCESS(status))
{
DbgPrint("MyDispatchControl -> ObReferenceObjectByHandle failed: %x", status);
Irp->IoStatus.Information = FALSE; //返回给R3的附加信息
break;
}
DbgPrint("MyDispatchControl -> ObReferenceObjectByHandle ststus: %x pkEvent:%p ", status, pkEvent);
//创建线程
status = PsCreateSystemThread(&thread, GENERIC_ALL, NULL, NULL, NULL, KstartRoutine, pkEvent);
if (!NT_SUCCESS(status))
{
DbgPrint("MyDispatchControl -> PsCreateSystemThread failed");
Irp->IoStatus.Information = FALSE; //返回给R3的附加信息
break;
}
DbgPrint("MyDispatchControl -> PsCreateSystemThread %p", thread);
ZwClose(thread);
break;
default:
DbgPrint("MyDispatchControl::switch->default");
break;
}
Irp->IoStatus.Status = status; //irp完成状态
IofCompleteRequest(Irp, IO_NO_INCREMENT); //当驱动程序完成给定IRP的所有处理时调用,代表IRP处理完成
return status;
}
NTSTATUS MyDispatchCreate(PDEVICE_OBJECT DeviceObjct, PIRP Irp)
{
NTSTATUS status = STATUS_SUCCESS;
DbgPrint("MyDispatchCreate");
Irp->IoStatus.Information = 0; //返回给R3的附加信息
Irp->IoStatus.Status = status; //irp完成状态
IofCompleteRequest(Irp, IO_NO_INCREMENT); //当驱动程序完成给定IRP的所有处理时调用,代表IRP处理完成
return status;
}
NTSTATUS MyDispatchCleanUp(PDEVICE_OBJECT DeviceObjct, PIRP Irp)
{
NTSTATUS status = STATUS_SUCCESS;
DbgPrint("MyDispatchCleanUp");
Irp->IoStatus.Information = 0; //返回给R3的附加信息
Irp->IoStatus.Status = status; //irp完成状态
IofCompleteRequest(Irp, IO_NO_INCREMENT); //当驱动程序完成给定IRP的所有处理时调用,代表IRP处理完成
return status;
}
NTSTATUS MyDispatchClose(PDEVICE_OBJECT DeviceObjct, PIRP Irp)
{
NTSTATUS status = STATUS_SUCCESS;
DbgPrint("MyDispatchClose");
Irp->IoStatus.Information = 0; //返回给R3的附加信息
Irp->IoStatus.Status = status; //irp完成状态
IofCompleteRequest(Irp, IO_NO_INCREMENT); //当驱动程序完成给定IRP的所有处理时调用,代表IRP处理完成
return status;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_SUCCESS;
DbgPrint("DriverEntry");
//驱动卸载
DriverObject->DriverUnload = DriverUnload;
//创建设备
PDEVICE_OBJECT DeviceObjet = NULL;
UNICODE_STRING DeviceName = { 0 };
RtlInitUnicodeString(&DeviceName, L"\\Device\\EventDriver");
status = IoCreateDevice(DriverObject, 400, &DeviceName, FILE_DEVICE_UNKNOWN, 0, TRUE, &DeviceObjet);
if (!NT_SUCCESS(status))
{
DbgPrint("DriverEntry->IoCreateDevice failed");
return status;
}
DeviceObjet->Flags |= DO_BUFFERED_IO; //未设置此标志,Irp->AssociatedIrp.SystemBuffer为NULL,注意是|= 不要直接=,会消除其它标志位
//创建符号链接
UNICODE_STRING SysmbolicLinkNmae = { 0 };
RtlInitUnicodeString(&SysmbolicLinkNmae, L"\\??\\EventDriver");
status = IoCreateSymbolicLink(&SysmbolicLinkNmae, &DeviceName);
if (!NT_SUCCESS(status))
{
DbgPrint("DriverEntry->IoCreateSymbolicLink failed");
IoDeleteDevice(DeviceObjet);
return status;
}
DriverObject->MajorFunction[IRP_MJ_CREATE] = MyDispatchCreate; //CreateFile
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = MyDispatchCleanUp; //CloseHandle
DriverObject->MajorFunction[IRP_MJ_CLOSE] = MyDispatchClose; //CloseHandle
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyDispatchControl; //CustomCode
DbgPrint("DriverEntry Success");
return status;
}
0x02 分析
资源释放:
驱动程序通过ObDereferenceObject(pkEvent);释放资源
桌面程序通过CloseHandle(customEvent);释放资源
如果在驱动程序调用KeWaitForSingleObject(pkEvent, Executive, KernelMode, FALSE, &Timeout);前释放了pkEvent,并且桌面程序也是释放了customEvent则这个事件无人使用,系统会处理该资源,之后调用KeWaitForSingleObject() 由于事件已经被系统销毁,则参数1属于无效内容.此时操作系统会出现意想不到的问题.
切记要在句柄或内核资源使用结束后,再去释放,否则提前释放会导致问题.