当前位置: 首页 > 内核 > 正文

驱动调用驱动

假设我们现在有一个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退出。
二.异步调用

  1. DriverB的ZwReadFile创建IRP_MJ_READ,将其发送给DriverA。
  2. DriverA在收到后,使用IoMarkIrpPending将其挂起,并返回STATUS_PENDING。
  3. ZwReadFile由于使用的是异步创建的句柄,所以不等待IRP完成,立即返回。
  4. 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是通过名字得到对象指针,除了获得设备对象指针外,其还可以获取其他对象指针。

上面两个函数,重复使用都是增加对象引用计数

本文固定链接: https://www.socarates.online/index.php/2024/02/16/%e9%a9%b1%e5%8a%a8%e8%b0%83%e7%94%a8%e9%a9%b1%e5%8a%a8/ | 安全技术研究

avatar
该日志由 Socarates 于2024年02月16日发表在 内核 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: 驱动调用驱动 | 安全技术研究
关键字: ,
【上一篇】
【下一篇】

驱动调用驱动:等您坐沙发呢!

发表评论


快捷键:Ctrl+Enter