概述:驱动对象
DRIVER_OBJECT结构体说明
DRIVER_OBJECT 结构体
要了解驱动对象,那了解 DRIVER_OBJECT 结构体是必要的。一般来说驱动程序 DriverEntry 入口处都会存在这样一个驱动对象,如下所示:
1 | NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg) |
也就是 PDriver。该对象内所包含的就是当前所加载驱动自身的一些详细参数,例如驱动大小、驱动标志、驱动名、驱动节等等。每一个驱动程序都会存在这样的一个结构,先看一下微软对其的定义:
1 | typedef struct _DRIVER_OBJECT { |
如果要获取当前驱动的一些基本信息,就可以通过 DRIVER_OBJECT 的参数来获取就行,相关代码如下所示,其中 IRP_MJ_* 这一系列则是微软的调用号,不同的 RIP 代表着不同的涵义,但一般驱动也就会用到如下这几种调用号。
1 | // #include <ntddk.h> |
输出:
Hello World, Driver
PDRIVER_OBJECT-> [0x0dd35e30]
PUNICODE_STRING->[\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services\KmdfDriverObject]
[*] 驱动名:\Driver\KmdfDriverObject
[*] 驱动起始地址:FFFFF80292650000, 大小:7000, 结束地址: FFFFF80292657000
[*] 卸载地址: FFFFF802926511B0
[*] IRP_MJ_READ: FFFFF8025ED1A030
[*] IRP_MJ_WRITE: FFFFF8025ED1A030
[*] IRP_MJ_CREATE: FFFFF8025ED1A030
[*] IRP_MJ_CLOSE: FFFFF8025ED1A030
[*] IRP_MJ_DEVICE_CONTROL: FFFFF8025ED1A030
IRP_MJ 调用号:0, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:1, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:2, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:3, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:4, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:5, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:6, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:7, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:8, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:9, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:10, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:11, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:12, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:13, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:14, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:15, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:16, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:17, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:18, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:19, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:20, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:21, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:22, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:23, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:24, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:25, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:26, 函数地址:FFFFF8025ED1A030
Bye, Driver
PDRIVER_OBJECT-> [0x0dd35e30]
PUNICODE_STRING->[\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services\KmdfDriverObject]
[*] 驱动名:\Driver\KmdfDriverObject
[*] 驱动起始地址:FFFFF80292650000, 大小:7000, 结束地址: FFFFF80292657000
[*] 卸载地址: FFFFF802926511B0
[*] IRP_MJ_READ: FFFFF8025ED1A030
[*] IRP_MJ_WRITE: FFFFF8025ED1A030
[*] IRP_MJ_CREATE: FFFFF8025ED1A030
[*] IRP_MJ_CLOSE: FFFFF8025ED1A030
[*] IRP_MJ_DEVICE_CONTROL: FFFFF8025ED1A030
IRP_MJ 调用号:0, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:1, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:2, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:3, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:4, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:5, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:6, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:7, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:8, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:9, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:10, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:11, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:12, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:13, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:14, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:15, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:16, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:17, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:18, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:19, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:20, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:21, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:22, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:23, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:24, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:25, 函数地址:FFFFF8025ED1A030
IRP_MJ 调用号:26, 函数地址:FFFFF8025ED1A030
Bye, Driver
遍历当前系统加载的所有驱动程序
DRIVER_OBJECT 对象中的 DriverSection 字段我们完全可以遍历输出当前系统下的所有的驱动程序的具体信息。DriverSection 结构指向了一个 _LDR_DATA_TABLE_ENTRY 结构体,相关定义如下所示:
1 | // |
为了能够遍历出所有的系统驱动,我们需要得到 LDR_DATA_TABLE_ENTRY 指针,通过 PDRIVER_OBJECT->DriverSection 获取。获取到之后通过 pldr->InLoadLinks.Flink 来获取驱动的入口地址,而每一次调用 Flink 都将获取驱动链表中的下一个驱动独享,这里可以通过 CONTATNING_RECORE 解析,即可输出当前系统内所有驱动的详细信息,相关代码如下所示:
1 |
|