驱动调用驱动
假设我们现在有一个DriverA,我们要编写一个DriverB来对DriverA进行调用。
那么有下列几种方法:
一.同步调用
1.在DriverB中调用ZwReadFile读取DriverA的设备对象,ZwReadFile会创建IRP_MJ_READ,随后将此IRP发送给DriverA。
2.DriverA在收到IRP_MJ_READ后,调用Read类型的派遣函数,函数内部将IRP进行挂起或者完成。
2.1 如果是挂起,需要在某时刻对IRP进行完成。使用定时器或者在CLEANUP派遣函数中完成都可以。
3.IRP_MJ_READ完成,IRP内部的事件对象被设置。DriverB中的ZwReadFile退出。
二.异步调用
- DriverB的ZwReadFile创建IRP_MJ_READ,将其发送给DriverA。
- DriverA在收到后,使用IoMarkIrpPending将其挂起,并返回STATUS_PENDING。
- ZwReadFile由于使用的是异步创建的句柄,所以不等待IRP完成,立即返回。
- tips:什么时候知道IRP完成?可以在ZwReadFile调用的时候,提供一个完成例程,在完成例程中设置事件激发
注:决定异步还是同步是由ZwCreateFile调用时决定的。

三. 异步调用2
前置知识:每打开一个设备,都会存在一个文件对象。利用ObReferenceObjectByHandle可以获得与设备相关的文件对象指针,当IRP_MJ_READ结束,文件对象的子域Event会被设置,可以利用其作为通知。
代码与二相同,只不过通知方式不一样。
四. 通过符号链接打开设备
如果我们只知道符号链接,可以使用ZwOpenSymbolicLinkObject获得链接句柄,使用ZwQuerySymbolicLinkObject获得设备名。
五. 创建IRP进行调用
5.1 IoBuildSynchronousFsdRequest
5.1.1 使用IoGetDeviceObjectPointer获取设备对象指针
5.1.2 初始化事件并使用IoBuildSynchronousFsdRequrest传递event,创建同步IRP,并设置下一层IRP的内容
5.1.3 IoCallDriver传递IRP
5.1.4 对事件进行等待
5.2 IoBuildAsynchronousFsdRequest
5.2.1 使用IoGetDeviceObjectPointer获取设备对象指针
5.2.2 使用IoBuildAsynchonousFsdRequest创建异步IRP,并设置下一层IRP的内容
5.2.3 设置IRP->UserEvent,此事件会在DriverA中由IoCompleteRequest进行设置
5.2.4 调用IoCallDriver传递IRP
5.2.5 等待event
5.3 IoAllocateIrp
5.3.1 使用IoGetDeviceObjectPointer获取设备对象
5.3.2 使用IoAllocateIrp创建IRP,并设置IRP内容,其中最重要的是设置Irp->UserEvent。使用IoGetNextIrpStackLocation获取下一层IRP堆栈指针,设置下一层IRP堆栈内容
5.3.3 IoCallDriver
5.3.4 等待事件
注:可以使用IoGetDeviceObjectPointer和ObReferenceObjectByName获得设备对象指针。IoGetDeviceObjectPointer只能获得设备对象指针,其第一次打开设备对象的时候,相当于CreateFile,在内部发送了一个IRP_MJ_CREATE,而ObDereferenceObJect相当于CloseFile。
ObReferenceObjectByName是通过名字得到对象指针,除了获得设备对象指针外,其还可以获取其他对象指针。
上面两个函数,重复使用都是增加对象引用计数
驱动调用驱动:等您坐沙发呢!
发表评论
