【驱动学习】7- DRIVER_OBJECT 驱动对象

概述:驱动对象 DRIVER_OBJECT 结构体说明

相关参考

DRIVER_OBJECT 结构体

要了解驱动对象,那了解 DRIVER_OBJECT 结构体是必要的。一般来说驱动程序 DriverEntry 入口处都会存在这样一个驱动对象,如下所示:

1
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)

也就是 PDriver。该对象内所包含的就是当前所加载驱动自身的一些详细参数,例如驱动大小、驱动标志、驱动名、驱动节等等。每一个驱动程序都会存在这样的一个结构,先看一下微软对其的定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
typedef struct _DRIVER_OBJECT {
CSHORT Type; // 驱动类型
CSHORT Size; // 驱动大小
PDEVICE_OBJECT DeviceObject; // 驱动对象
ULONG Flags; // 驱动的标志
PVOID DriverStart; // 驱动的起始位置
ULONG DriverSize; // 驱动的大小
PVOID DriverSection; // 指向驱动程序文件的内存区对象
PDRIVER_EXTENSION DriverExtension; // 驱动的扩展空间
UNICODE_STRING DriverName; // 驱动名字
PUNICODE_STRING HardwareDatabase;
PVOID FastIoDispatch;
PDRIVER_INITIALIZE DriverInit;
PDRIVER_STARTIO DriverStartIo;
PDRIVER_UNLOAD DriverUnload; // 驱动对象的卸载地址
PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];
} DRIVER_OBJECT;
typedef struct _DRIVER_OBJECT *PDRIVER_OBJECT;

如果要获取当前驱动的一些基本信息,就可以通过 DRIVER_OBJECT 的参数来获取就行,相关代码如下所示,其中 IRP_MJ_* 这一系列则是微软的调用号,不同的 RIP 代表着不同的涵义,但一般驱动也就会用到如下这几种调用号。

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 <ntddk.h>

#include <ntifs.h>

NTSTATUS UnloadDriver(PDRIVER_OBJECT pDriver)
{
DbgPrint("Bye, Driver\n");

return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
DbgPrint("Hello World, Driver\n");
DbgPrint("PDRIVER_OBJECT-> [0x%08x]\n", pDriver);
DbgPrint("PUNICODE_STRING->[%ws]\n", pReg->Buffer);

pDriver->DriverUnload = UnloadDriver;

DbgPrint("[*] 驱动名:%wZ", pDriver->DriverName);

DbgPrint("[*] 驱动起始地址:%p, 大小:%x, 结束地址: %p", pDriver->DriverStart, pDriver->DriverSize, (ULONG64)pDriver->DriverStart+pDriver->DriverSize);

DbgPrint("[*] 卸载地址: %p", pDriver->DriverUnload);
DbgPrint("[*] IRP_MJ_READ: %p", pDriver->MajorFunction[IRP_MJ_READ]);
DbgPrint("[*] IRP_MJ_WRITE: %p", pDriver->MajorFunction[IRP_MJ_WRITE]);
DbgPrint("[*] IRP_MJ_CREATE: %p", pDriver->MajorFunction[IRP_MJ_CREATE]);
DbgPrint("[*] IRP_MJ_CLOSE: %p", pDriver->MajorFunction[IRP_MJ_CLOSE]);
DbgPrint("[*] IRP_MJ_DEVICE_CONTROL: %p", pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL]);

// 输出完整的调用号
for (auto i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
{
DbgPrint("IRP_MJ 调用号:%d, 函数地址:%p", i, pDriver->MajorFunction[i]);
}

return STATUS_SUCCESS;
}

输出:

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
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

遍历当前系统加载的所有驱动程序

DRIVER_OBJECT 对象中的 DriverSection 字段我们完全可以遍历输出当前系统下的所有的驱动程序的具体信息。DriverSection 结构指向了一个 _LDR_DATA_TABLE_ENTRY 结构体,相关定义如下所示:

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
//
// Loader Data Table Entry
//
typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT TlsIndex;
union
{
LIST_ENTRY HashLinks;
PVOID SectionPointer;
};
ULONG CheckSum;
union
{
ULONG TimeDateStamp;
PVOID LoadedImports;
};
PVOID EntryPointActivationContext;
PVOID PatchInformation;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

为了能够遍历出所有的系统驱动,我们需要得到 LDR_DATA_TABLE_ENTRY 指针,通过 PDRIVER_OBJECT->DriverSection 获取。获取到之后通过 pldrt


【驱动学习】7- DRIVER_OBJECT 驱动对象
https://hodlyounger.github.io/2025/01/26/A_OS/Windows/驱动/windows驱动开发教程/【驱动学习】7- DRIVER_OBJECT驱动对象/
作者
mingming
发布于
2025年1月26日
许可协议