WDK中定义的数据类型

数据类型

基本数据类型

WDK重定义了所有的基本数据类型

unsigned long 重定义为 ULONG
unsigned char 重定义为UCHAR
unsigned int 重定义为UINT

void重定义为 VOID

unsigned long 重定义为PULONG
unsigned char
重定义为PUCHAR
unsigned int 重定义为PUINT
void
重定义为PVOID
从x86到x64只有所有的指针类型从4个字节变为8个字节,其他数据类型无变化

返回状态

大多数的内核API的返回值都是一个返回状态,类型为NTSTATUS

字符串

驱动程序中,字符串用一个结构容纳

1
2
3
4
5
typedef struct _NUICODE_STRING{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING *PUNICODE_STRING;

字符串的字符为宽字符,双字节的
使用DbgPrint()直接打印字符串

1
DbgPrint("Hello\r\n");

也可以直接打印UNICODE_STRING

1
2
UNICODE_STRING str = RTL_CONSTANT_STRING(L"Hello\r\n");
DbgPrint("%wZ",&str);

重要数据结构

驱动对象(DRIVER_OBJECT)

一个驱动对象代表了一个驱动程序(内核模块)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//驱动对象的数据结构
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; //
PFAST_IO_DISPATCH FastIoDispatch; //快速I/O分发函数
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;

内核模块并不生成一个进程,只是填写一组回调函数让Windows内核来调用

设备对象(DEVICE_OBJECT)

DEVICE是接收内核消息(IRP—请求)的唯一对象
驱动捕获IRP,设备对象接收IRP

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
//设备对象的数据结构
typedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _DEVICE_OBJECT {
CSHORT Type; //结构类型
USHORT Size; //结构大小
LONG ReferenceCount; //引用计数
struct _DRIVER_OBJECT *DriverObject; //所在的驱动对象
struct _DEVICE_OBJECT *NextDevice; //指向下一个设备对象
struct _DEVICE_OBJECT *AttachedDevice;
struct _IRP *CurrentIrp;
PIO_TIMER Timer;
ULONG Flags;
ULONG Characteristics;
__volatile PVPB Vpb;
PVOID DeviceExtension;
DEVICE_TYPE DeviceType; //设备类型
CCHAR StackSize; //IRP栈大小
union {
LIST_ENTRY ListEntry;
WAIT_CONTEXT_BLOCK Wcb;
} Queue;
ULONG AlignmentRequirement;
KDEVICE_QUEUE DeviceQueue;
KDPC Dpc;

ULONG ActiveThreadCount;
PSECURITY_DESCRIPTOR SecurityDescriptor;
KEVENT DeviceLock;

USHORT SectorSize;
USHORT Spare1;

struct _DEVOBJ_EXTENSION *DeviceObjectExtension;
PVOID Reserved;
} DEVICE_OBJECT;

typedef struct _DEVICE_OBJECT *PDEVICE_OBJECT;

驱动对象生成多个设备对象
请求是被驱动对象的分发函数所捕获,内核向一个设备发送一个请求时,驱动对象的分发函数中的某一个会被调用

1
2
//分发函数原型
NTSTATUS MyDispatch(PDEVICE_OBJECT device,PIRP Irp);

请求

系统中软件对硬件的操作都会被I/O管理器翻译为IRP
IRP是一个非常复杂的数据结构,这个结构要表示无数种实际请求

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
typedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _IRP {
CSHORT Type; //类型
USHORT Size; //大小
PMDL MdlAddress; //内存描述符链表指针(描述一个缓冲区)
ULONG Flags;

union {
struct _IRP *MasterIrp;
__volatile LONG IrpCount;
PVOID SystemBuffer; //也表示缓冲区
} AssociatedIrp;

LIST_ENTRY ThreadListEntry;
IO_STATUS_BLOCK IoStatus; //I/O状态,存储返回值
KPROCESSOR_MODE RequestorMode;
BOOLEAN PendingReturned;
CHAR StackCount; //IRP栈空间大小
CHAR CurrentLocation; //IRP当前栈空间

BOOLEAN Cancel;

KIRQL CancelIrql;

CCHAR ApcEnvironment;

UCHAR AllocationFlags;
PIO_STATUS_BLOCK UserIosb;
PKEVENT UserEvent;

union {
struct {
union {
PIO_APC_ROUTINE UserApcRoutine;
PVOID IssuingProcess;
};
PVOID UserApcContext;
} AsynchronousParameters;
LARGE_INTEGER AllocationSize;
} Overlay;

__volatile PDRIVER_CANCEL CancelRoutine; //用来取消一个未决请求的函数

PVOID UserBuffer; //缓冲区(特性不同)

union {

struct {

union {
KDEVICE_QUEUE_ENTRY DeviceQueueEntry;
struct {
PVOID DriverContext[4];
} ;
} ;

PETHREAD Thread; //发出请求的线程
PCHAR AuxiliaryBuffer;
struct {
LIST_ENTRY ListEntry;
union {
struct _IO_STACK_LOCATION *CurrentStackLocation;//当前栈空间
ULONG PacketType;
};
};
PFILE_OBJECT OriginalFileObject;
} Overlay;
KAPC Apc;
PVOID CompletionKey;
} Tail;
} IRP;