Windows驱动 - R3-R0事件交互

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.SystemBufferNULL,注意是|= 不要直接=,会消除其它标志位

 

    //创建符号链接

 

    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属于无效内容.此时操作系统会出现意想不到的问题.

切记要在句柄或内核资源使用结束后,再去释放,否则提前释放会导致问题.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值