数据类型
基本数据类型
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
5typedef struct _NUICODE_STRING{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING *PUNICODE_STRING;
字符串的字符为宽字符,双字节的
使用DbgPrint()直接打印字符串1
DbgPrint("Hello\r\n");
也可以直接打印UNICODE_STRING1
2UNICODE_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,设备对象接收IRP1
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
70typedef 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;