应用程序中创建的事件和在内核中创建的事件对象,本质上是同一个东西,在用户模式中,他用句柄表示,在内核模式下,他用KEVENT表示数据结构表示。在应用程序中,所有的内核对象都不会被用户看到,用户看到的知识代表内核对象的对象句柄。
这个代码就是要在Ring3与RIng0之间用一个事件对象。
解决的第一个问题就是如何将Ring3创建的事件传递给驱动:
使用DeviceIoControl,在Ring3中创建一个同步事件,然后用DeviceIoControl将事件句柄传递给驱动程序。需要指出的是句柄和进程是相关的,也就是说一个进程的句柄只有在这个进程中有效。句柄相当于事件对象在进程中的索引,通过这个索引操作系统就可以得到事件对象的指针:ObReferenceObjectByHandle,函数返回一个状态值,表示是否成功获得指针
这个函数在得到指针的同时,会为对象的指针维护一个计数,没记调用的时候会使计数+1。因此为了计数平衡,在使用玩ObReferenceObjectByHandle之后要调用ObDereferenceObject函数,它使计数-1

Ring0(设置事件).h

 #include <ntifs.h>

 #define CTL_EVENT \
CTL_CODE(FILE_DEVICE_UNKNOWN,0x830,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define CTL_SET_EVENT \
CTL_CODE(FILE_DEVICE_UNKNOWN,0x831,METHOD_BUFFERED,FILE_ANY_ACCESS) #define DEVICE_OBJECT_NAME L"\\Device\\Ring0DeviceObjectName" #define DEVICE_LINK_NAME L"\\DosDevices\\Ring0DeviceLinkName" NTSTATUS PassThroughDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp); NTSTATUS ControlThroughDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp); NTSTATUS Ring3EventHandleToRing0KernelEvent(HANDLE* EventHandle, ULONG_PTR EventHandleCount); VOID DriverUnload(PDRIVER_OBJECT DriverObject);

Ring0(设置事件).c

 #include "Ring0(设置事件).h"

 PKEVENT  __KernelEvent[] = {  };
ULONG_PTR __KernelEventCount = ; extern
POBJECT_TYPE* ExEventObjectType; NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegisterPath)
{
NTSTATUS Status = STATUS_SUCCESS;
PDEVICE_OBJECT DeviceObject = NULL;
UNICODE_STRING DeviceObjectName;
UNICODE_STRING DeviceLinkName; DbgPrint("DriverEntry()\r\n");
DriverObject->DriverUnload = DriverUnload; RtlInitUnicodeString(&DeviceObjectName, DEVICE_OBJECT_NAME); Status = IoCreateDevice(
DriverObject,
NULL,
&DeviceObjectName,
FILE_DEVICE_UNKNOWN,
,
FALSE,
&DeviceObject
);
if (!NT_SUCCESS(Status))
{
return Status;
} //创建设备连接名称
RtlInitUnicodeString(&DeviceLinkName, DEVICE_LINK_NAME); //将设备连接名称与设备名称关联
Status = IoCreateSymbolicLink(&DeviceLinkName, &DeviceObjectName);
if (!NT_SUCCESS(Status))
{
IoDeleteDevice(DeviceObject);
return Status;
} //我们要的派遣函数
for (int i = ; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
{
DriverObject->MajorFunction[i] = PassThroughDispatch;
}
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ControlThroughDispatch; return Status;
} NTSTATUS ControlThroughDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
ULONG_PTR Information = ;
PVOID InputData = NULL;
ULONG InputDataLength = ;
PVOID OutputData = NULL;
ULONG OutputDataLength = ;
ULONG IoControlCode = ;
PEPROCESS EProcess = NULL;
PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp); //Irp堆栈
IoControlCode = IoStackLocation->Parameters.DeviceIoControl.IoControlCode;
InputData = Irp->AssociatedIrp.SystemBuffer;
OutputData = Irp->AssociatedIrp.SystemBuffer;
InputDataLength = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
OutputDataLength = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength;
switch (IoControlCode)
{
case CTL_EVENT:
{ if (InputData != NULL&&InputDataLength == sizeof(HANDLE) * )
{ Status = Ring3EventHandleToRing0KernelEvent((HANDLE*)InputData, InputDataLength / sizeof(HANDLE)); } Information = ; break; } case CTL_SET_EVENT:
{ DbgPrint("Ring0触发Ring3\r\n");
KeSetEvent(__KernelEvent[], IO_NO_INCREMENT, FALSE); DbgPrint("Ring0等待\r\n");
Status = KeWaitForSingleObject(__KernelEvent[],
Executive, KernelMode, FALSE, NULL); //注意这里的最后一个参数NULL 是永久等待 DbgPrint("Ring3触发Ring0\r\n"); Information = ;
break; } default:
{ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = ; break;
}
} Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = Information;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
} NTSTATUS Ring3EventHandleToRing0KernelEvent(HANDLE* EventHandle, ULONG_PTR EventHandleCount)
{
NTSTATUS Status = STATUS_SUCCESS;
PULONG_PTR HandleArray = NULL;
ULONG i = ; if (EventHandle == NULL)
{
return STATUS_UNSUCCESSFUL;
}
__KernelEventCount = EventHandleCount; for (i = ; i < EventHandleCount; i++)
{
Status = ObReferenceObjectByHandle((HANDLE)EventHandle[i],
SYNCHRONIZE,
*ExEventObjectType,
KernelMode,
&__KernelEvent[i],
NULL
);
if (!NT_SUCCESS(Status))
{
break;
}
} if (Status != STATUS_SUCCESS)
{
for (i = ; i < EventHandleCount; i++)
{
if (__KernelEvent[i] != NULL)
{
ObDereferenceObject(__KernelEvent[i]); __KernelEvent[i] = NULL;
}
}
}
return Status;
} VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{ DbgPrint("DriverUnload()\r\n");
} NTSTATUS PassThroughDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS; //LastError()
Irp->IoStatus.Information = ; //ReturnLength
IoCompleteRequest(Irp, IO_NO_INCREMENT); //将Irp返回给Io管理器
return STATUS_SUCCESS;
}

Ring3(创建事件).cpp

 // Ring3(创建事件).cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <windows.h>
#include <iostream> using namespace std; #define CTL_EVENT \
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x830, METHOD_BUFFERED, FILE_ANY_ACCESS) #define CTL_SET_EVENT \
CTL_CODE(FILE_DEVICE_UNKNOWN,0x831,METHOD_BUFFERED,FILE_ANY_ACCESS) #define DeviceLinkName L"\\\\.\\Ring0DeviceLinkName" DWORD WINAPI ThreadProc(LPVOID ParameterData); int main()
{
HANDLE DeviceHandle = CreateFile(
DeviceLinkName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL); if (DeviceHandle == INVALID_HANDLE_VALUE)
{
cout << "CreateFile FAIL " << GetLastError() << endl;
return ;
} HANDLE EventHandle[];
for (int i = ; i < ; i++)
{
//用户模式同步事件
EventHandle[i] = CreateEvent(
NULL,
FALSE,
FALSE,
NULL
);
}
BOOL IsOK = FALSE; DWORD ReturnLength = ; IsOK = DeviceIoControl(
DeviceHandle,
CTL_EVENT,
EventHandle,
sizeof(HANDLE)*,
NULL,
,
&ReturnLength,
NULL
); if (IsOK == FALSE)
{
goto Final;
}
//辅助线程
HANDLE ThreadHandle = CreateThread(
NULL,
,
(LPTHREAD_START_ROUTINE)ThreadProc,
(LPVOID)EventHandle,
,
NULL
); IsOK = DeviceIoControl(
DeviceHandle,
CTL_SET_EVENT,
NULL,
,
NULL,
,
&ReturnLength,
NULL); if (IsOK == FALSE)
{
cout << "Send IoCode Error" << endl;
SetEvent(EventHandle[]);
WaitForSingleObject(ThreadHandle, INFINITE);
goto Final;
} WaitForSingleObject(ThreadHandle, INFINITE); Final:
{
for (int i = ; i < ; i++)
{
if (EventHandle[i] != NULL)
{
CloseHandle(EventHandle[i]);
EventHandle[i] = NULL;
}
}
if (ThreadHandle != NULL)
{
CloseHandle(ThreadHandle);
ThreadHandle = NULL;
}
if (DeviceHandle != NULL)
{
CloseHandle(DeviceHandle);
DeviceHandle = NULL;
} } printf("先卸载驱动\r\n");
printf("Input AnyKey To Exit\r\n"); getchar();
return ;
} DWORD WINAPI ThreadProc(LPVOID ParameterData)
{
cout << "Ring3 等啊等" << endl;
DWORD Index = WaitForMultipleObjects(
,
(HANDLE*)ParameterData,
FALSE,
INFINITE
); if (Index == )
{
cout << "ThreadProc EXIT " << endl;
return ;
}
cout << "Ring0触发Ring3" << endl; cout << "put any key Ring3 触发Ring0" << endl; getchar();
getchar(); SetEvent(((HANDLE*)ParameterData)[]);
cout << "ThreadProc EXIT" << endl;
return ; }

Ring3创建事件Ring0设置事件的更多相关文章

  1. Ring0创建事件Ring3设置事件

    同步事件(synchronizationEvent)当事件对象为激发时,如遇到KeWaitForXX等内核函数,事件对象则自动变回未激发态通知事件(NotificationEvent)当事件对象为激发 ...

  2. asp.net 微信企业号办公系统-流程设计--流程步骤设置-事件设置

    事件设置是设置当前步骤在提交前后或退回前后要执行的一些操作(该事件为服务器事件). 事件格式为:dll名称.命名空间名称.类名.方法名,这里不需要写括号和参数,处理时会自动带上当前流程实例的相关参数. ...

  3. 给js动态创建的对象绑定事件

    1.使用原生JS动态为动态创建的对象绑定事件 1-1.创建一个function,用来兼容IE8以下浏览器添加事件 function addEvent(el, type, fn) {  if(el.ad ...

  4. 在js文件中通过jquery定位到某个dom时候设置事件时候 相当于直接在dom里面添加事件

    在js文件中通过jquery定位到某个dom时候设置事件时候 相当于直接在dom里面添加事件  当触发事件时候 会把当前的dom传给该方法

  5. WPF 创建自定义控件及自定义事件

    1 创建自定义控件及自定义事件 /// <summary> /// 演示用的自定义控件 /// </summary> public class ExtButton : Butt ...

  6. .NET开源工作流RoadFlow-流程设计-流程步骤设置-事件设置

    事件设置是设置当前步骤在提交前后或退回前后要执行的一些操作(该事件为服务器事件). 事件格式为:dll名称.命名空间名称.类名.方法名,这里不需要写括号和参数,处理时会自动带上当前流程实例的相关参数. ...

  7. JS事件 什么是事件?JavaScript 创建动态页面。事件是可以被 JavaScript 侦测到的行为。 网页中的每个元素都可以产生某些可以触发 JavaScript 函数或程序的事件。

    什么是事件 JavaScript 创建动态页面.事件是可以被 JavaScript 侦测到的行为. 网页中的每个元素都可以产生某些可以触发 JavaScript 函数或程序的事件. 比如说,当用户单击 ...

  8. carsim2016事件如何设置

    #carsim2016事件设置# 完成以下功能:车速低于60km/h时,加速,设置节气门开度为0.8,制动主斜体样式缸压力设为0:车速高于120km/h时,制动,设置节气门开度为0,制动主缸压力设置为 ...

  9. js原生创建模拟事件和自定义事件的方法

    让我万万没想到的是,原来<JavaScript高级程序设计(第3版)>里面提到的方法已经是过时的了.后来我查看了MDN,才找到了最新的方法. 模拟鼠标事件MDN上已经说得很清楚,尽管为了保 ...

随机推荐

  1. mongodb添加验证用户 删除用户

    1.创建用户 db.createUser( { user:<name_string>,                   #字符串 pwd:<password_string> ...

  2. protobuf GetExtension

    get extention values from  proto file value, err := proto.GetExtension(imp, openrtb.E_Imp) if err != ...

  3. Calendar类的使用——闰年的计算

    1.Calendar类: 是一个抽象类,需要导入java.util.Calendar包. Calendar c = Calendar.getInstance(); getInstance直接返回的是子 ...

  4. Connecting Elixir Nodes with libcluster, locally and on Kubernetes

    转自:https://www.poeticoding.com/connecting-elixir-nodes-with-libcluster-locally-and-on-kubernetes/ Tr ...

  5. Singer 学习十一 配置以及状态管理

    配置和状态文件通过提供身份验证信息,开始时间和有关以前调用的信息,帮助为Taps和Targets提供上下文 配置文件 配置文件包含tap 运行需要的信息,通常包含API,以及数据源的凭据 特殊字段 s ...

  6. jquery禁用form表单中的文本框

    //禁用form表单中所有的input[文本框.复选框.单选框],select[下拉选],多行文本框[textarea] function disableForm(formId, isDisabled ...

  7. vsphere和vmware快照的不足之处

    当快照创建时虚拟机执行一个读操作,hypervisor会检查快照VMDK,查看是否有被读取的区块存在.如果有,则从快照中为虚拟机提供这个区块,如果没有,虚拟机还需要去读取基础VMDK.如果只有一个快照 ...

  8. 著名软件工程师与作家、极限编程的创始者、JUnit作者之Kent Beck

    Kent Beck,1961年出生,中文名肯特贝克,美国著名软件工程师与作家,在软件工程方面有很大的贡献.他是Smalltalk软件的开发者,设计模式的先驱,测试驱动开发的支持者,也是极限编程的创始者 ...

  9. P2P Downloader

    P2P Downloader , 当然就是 P2P 下载器了 , 就是和 比特精灵 差不多的那种 .  ^ ^ 不过这个项目没有代码 , 懒得写代码了 , 就文字描述一下吧 .   ^ ^ P2P 下 ...

  10. arttemplate记录

    1,传到前端显示数据,最好用一个包装类,否则不知道怎么拿值 这样是忽略类名,直接从data属性入手,然后用点操作符 如果data是个list,可以用这个形式