5.1.2
直接看PAGE_SIZE的大小就可以知道当前分页的大小
// // Define the page size // #define PAGE_SIZE 0x2000
5.1.4
驱动程序的不同函数运行在不同的进程中,DriverEntry和AddDevice函数是运行在系统进程中的(system)
3: kd> !process sysmtem PROCESS 8a52a830 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000 DirBase: 0aac0020 ObjectTable: e1003e00 HandleCount: 265.PsGetCurrentProcess可以获得当前线程所在的进程指针(指向EPROCESS)
可以用windbg查看这个:偏移量为0x174
+0x174 ImageFileName : [16] "System"所以可以这样获取:
#pragma PAGEDCODE VOID DisplayItsProcessName() { PEPROCESS pEProcess = PsGetCurrentProcess(); PTSTR ProcessName = (PTSTR)((ULONG)pEProcess + 0x174); KdPrint(("%s ",ProcessName)); }
5.1.5
当程序的中断请求级在DISPATCH_LEVEL上(包括),程序只能使用非分页内存,否则将蓝屏
堆中申请内存函数:
PVOID ExAllocatePool( IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes );对应释放内存函数:
VOID ExFreePool( IN PVOID P );
双向链表结构中,都需要包含LIST_ENTRY,但不一定在结构的首位,所以DDK提供了一个宏
整个结构体的首地址=LIST_ENTRY的地址-LIST_ENTRY在整个结构体中的相对偏移
#define CONTAINING_RECORD(address, type, field) ((type *)( (PCHAR)(address) - (ULONG_PTR)(&((type *)0)->field)))
// 从尾部删除一个元素 typedef struct _MYDATASTRUCT { ULONG number; LIST_ENTRY ListEntry1; } MYDATASTRUCT, *PMYDATASTRUCT; PLIST_ENTRY pEntry = RemoveTailList(&linkListHead); pData = CONTAINING_RECORD(pEntry, MYDATASTRUCT, ListEntry1);为了简明示例,特别把LIST_ENTRY的元素名叫个ListEntry1
5.3 Lookaside结构
如果驱动需要频繁从内存中申请,回收固定大小的内存,DDK提供了Lookaside对象来解决这个问题
5.4内存系列函数
内存复制(非重叠)
VOID RtlCopyMemory( IN VOID UNALIGNED *Destination, IN CONST VOID UNALIGNED *Source, IN SIZE_T Length );
内存复制(可重叠),函数内部对两个内存是否重叠进行了判断,这种判断牺牲了速度
void RtlMoveMemory( __in PVOID Destination, __in const VOID* Source, __in SIZE_T Length );
void RtlFillMemory( [out] PVOID Destination, [in] SIZE_T Length, [in] BYTE Fill );
内存置0
VOID RtlZeroMemory( IN VOID UNALIGNED *Destination, IN SIZE_T Length );
内存比较
ULONG RtlEqualMemory( CONST VOID *Source1, CONST VOID *Source2, SIZE_T Length );
DDK提供的标准的运行时函数名都是RtlXX形式,其中,大部分是以宏的形式给出,来自wdm.h:
#define RtlEqualMemory(Destination,Source,Length) (!memcmp((Destination),(Source),(Length))) #define RtlMoveMemory(Destination,Source,Length) memmove((Destination),(Source),(Length)) #define RtlCopyMemory(Destination,Source,Length) memcpy((Destination),(Source),(Length)) #define RtlFillMemory(Destination,Length,Fill) memset((Destination),(Fill),(Length)) #define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length))
5.6数据类型
DDK提供了一种新的64位整数的表示方式即
typedef union _LARGE_INTEGER { struct { ULONG LowPart; LONG HighPart; } DUMMYSTRUCTNAME; struct { ULONG LowPart; LONG HighPart; } u; #endif //MIDL_PASS LONGLONG QuadPart; } LARGE_INTEGER;需要注意的是他是一个联合体,可以认为是LARGE_INTEGER的三个定义
5.6.3.
检测内存是否可读可写,在ring3用的是
IsBadReadPtr
IsBadWritePtr
在ring0用的是ProbeForRead和ProbeForWrite