刘收获

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

内核事件KEVENT(同步)

转载请您注明出处:http://www.cnblogs.com/lsh123/p/7358702.html

 

一.驱动程序与驱动程序的事件交互    IoCreateNotificationEvent ———> IoCreateNotificationEvent

  

  在内核驱动中可以通过给某个内核对象创建一个命名对象,然后在另一个驱动中通过名字来获取这个对象,然后操作它来实现两个驱动之间的内核对象的通讯,针对事件对象来说,要实现两个驱动交互事件对象,通过这样几步: 


1. 在驱动Server中调用IoCreateNotificationEvent或者IoCreateSynchronizationEvent来创建一个通知事件对象或者同步事件对象 
2. 在驱动Client中调用 IoCreateNotificationEvent或者IoCreateSynchronizationEvent获取已经有名字的内核对象的句柄 ,设置事件的激发状态
(3. 在驱动B中调用ObReferenceObjectByHandle根据上面两个函数返回的句柄来获取A中的事件对象,并操作它) 

 

源代码:

Server.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <ntifs.h>
#define EVENT_NAME  L"\\BaseNamedObjects\\ServerKernelEvent"
 
void ThreadProcedure(PVOID ParameterData);
VOID DriverUnload(PDRIVER_OBJECT DriverObject);
 
PKEVENT __Event;
HANDLE __EventHandle;
 
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegisterPath)
{
    NTSTATUS Status = STATUS_SUCCESS;
    UNICODE_STRING  EventName;
    PDEVICE_OBJECT  DeviceObject = NULL;
    HANDLE   ThreadHandle = NULL;
    CLIENT_ID       ClientID = { 0 };
 
 
 
    DriverObject->DriverUnload = DriverUnload;
     
 
    RtlInitUnicodeString(&EventName, EVENT_NAME);
    DriverObject->DriverUnload = DriverUnload;
 
 
    __Event = IoCreateNotificationEvent(
        &EventName,                    //自定义事件名
        &__EventHandle);               //返回的事件句柄
    KeResetEvent(__Event);
 
 
    Status = PsCreateSystemThread(&ThreadHandle, 0, NULL, NtCurrentProcess(), &ClientID,
        (PKSTART_ROUTINE)ThreadProcedure,NULL);
 
 
 
    return Status;
}
 
void ThreadProcedure(PVOID ParameterData)
{
    NTSTATUS Status;
    KeWaitForSingleObject(__Event, Executive, KernelMode, FALSE, NULL);
    DbgPrint("ThreadProcedure() Exit\r\n");
    PsTerminateSystemThread(STATUS_SUCCESS);
}
 
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
    DbgPrint("DriverUnload()\r\n");
    if (__EventHandle != NULL)
    {
        KeClearEvent(__Event);
 
        ZwClose(__EventHandle);
 
        __EventHandle = NULL;
        __Event = NULL;
    }
 
}

 

Client.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <ntifs.h>
 
#define EVENT_NAME  L"\\BaseNamedObjects\\ServerKernelEvent"
VOID DriverUnload(PDRIVER_OBJECT DriverObject);
 
PKEVENT __Event;
HANDLE __EventHandle;
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegisterPath)
{
    NTSTATUS Status = STATUS_SUCCESS;
    UNICODE_STRING  EventName;
    PDEVICE_OBJECT  DeviceObject = NULL;
    DriverObject->DriverUnload = DriverUnload;
    RtlInitUnicodeString(&EventName, EVENT_NAME);
    __Event = IoCreateNotificationEvent(&EventName, &__EventHandle);    //获取已经有名字的内核对象的句柄
    KeSetEvent(__Event, IO_NO_INCREMENT, FALSE);                        //设置激发态
    return Status;
}
 
 
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
    DbgPrint("DriverUnload()\r\n");
    if (__EventHandle != NULL)
    {
        KeClearEvent(__Event);
        ZwClose(__EventHandle);
        __EventHandle = NULL;
        __Event = NULL;
    }
 
}

  

二.驱动程序与应用程序的事件交互(驱动程序创建事件——>应用程序设置事件)IoCreateNotificationEvent ——> OpenEvent

  应用程序中创建的事件和在内核模式下创建的事件对象本质上是同一个东西。用户模式下,它用句柄代表,在内核模式下,它用KEVENT数据结构代表。
应用程序中,所有内核对象都不会被用户看到,用户看到的只是代表内核对象的对象句柄。

  __Event = IoCreateNotificationEvent(&EventName, &__EventHandle); //DriverEntry 进程回调通知


  EventHandle = OpenEvent(
    SYNCHRONIZE, //请求访问权限
    FALSE, // 不继承
    L"Global\\Ring0KernelEvent"); //事件对象名称

  1.驱动程序IoCreateNotificationEvent创建事件
  2.应用程序OpenEvent得到事件句柄

 

Ring3.cpp

 

  

Ring0.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <ntifs.h>
 
#define EVENT_NAME  L"\\BaseNamedObjects\\Ring0KernelEvent"
VOID DriverUnload(PDRIVER_OBJECT DriverObject);
 
PKEVENT __Event;
HANDLE __EventHandle;
 
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegisterPath)
{
    NTSTATUS Status = STATUS_SUCCESS;
    PDEVICE_OBJECT  DeviceObject = NULL;   
    UNICODE_STRING  EventName;
 
    RtlInitUnicodeString(&EventName, EVENT_NAME);
    DriverObject->DriverUnload = DriverUnload;
 
 
    __Event = IoCreateNotificationEvent(&EventName, &__EventHandle);    //DriverEntry     进程回调通知
 
    return Status;
}
 
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
    DbgPrint("DriverUnload()\r\n");
 
    if (__EventHandle != NULL)
    {
        KeClearEvent(__Event);
 
        ZwClose(__EventHandle);
 
        __EventHandle = NULL;
        __Event = NULL;
    }
 
}

  

 

三.应用程序与驱动程序的事件交互(应用程序创建事件——>驱动程序设置事件) DeviceIoControl ——> ObReferenceObjectByHandle

  要将用户模式下创建的事件传递给驱动程序,可以用DeviceIoControl API函数。DDK提供了内核函数将句柄转化为指针,该函数如下:
  NTSTATUS 
     ObReferenceObjectByHandle(
      IN HANDLE  Handle,
      IN ACCESS_MASK  DesiredAccess,
      IN POBJECT_TYPE  ObjectType  OPTIONAL,
      IN KPROCESSOR_MODE  AccessMode,
      OUT PVOID  *Object,
      OUT POBJECT_HANDLE_INFORMATION  HandleInformation  OPTIONAL
      );

  ObReferenceObjectByHandle函数在得到指针的同时,会为对象的指针维护一个计数。每次调用ObReferenceObjectByHandle函数时会使计数加1.因此为了计数平衡,在使用完 ObReferenceObjectByHandle函数后,需要调用如下函数:             
  VOID 
    ObDereferenceObject(
      IN PVOID  Object
      );
  ObDereferenceObject函数使计数减一。

  1.应用程序通过符号链接名CreateFile函数得到设备句柄

  HANDLE DeviceHandle = CreateFile(DeviceLinkName,
    GENERIC_READ | GENERIC_WRITE,
    FILE_SHARE_READ | FILE_SHARE_WRITE,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    NULL);
  2.应用程序CreateEvent创建事件

    //创建自动重置的,初始为未激发的事件对象
    EventHandle[i] = CreateEvent(NULL, FALSE, FALSE, NULL);

  3.应用程序通过DeviceIoControl 函数将用户模式下创建的事件传递给驱动程序

    //调用DeviceIoControl把事件句柄传进内核
    IsOk = DeviceIoControl(DeviceHandle, CTL_EVENT,
      EventHandle,
      sizeof(HANDLE) * 2,
      NULL,
      0,
      &ReturnLength,
      NULL);

    //调用DeviceIoControl,通知驱动程序设置事件激发状态
    IsOk = DeviceIoControl(DeviceHandle, CTL_SET_EVENT,
      NULL,
      0,
      NULL,
      0,
      &ReturnLength,
      NULL);

  4.驱动程序通过ObReferenceObjectByHandle句柄转化为PKEVENT指针

    /把句柄转化为KEvent结构
    Status = ObReferenceObjectByHandle(
      (HANDLE)EventHandle[i], //Irp->AssociatedIrp.SystemBuffer 句柄
      SYNCHRONIZE, //权限
      *ExEventObjectType, //对象类型,对象类型
      KernelMode, //访问模式分KernelMode
      &__KernelEvent[i], //指向映射句柄对象的指针
      NULL);

Ring3.cpp

  

Ring0.c

  

 

posted on   沉疴  阅读(4563)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示