内核空间与内核模块
内核空间
进程A,B两个不同进程,低2G内存空间(ring 3)所对应的物理页几乎是不一样的,而高2G的内存空间对应的物理页却几乎是一样的.
不是每一个进程都有自己的内核空间,而是所有的进程共享一个内核空间
可以做个实验
驱动环境:win7 x64
//定义一个变量,输出变量线性地址
#include<ntddk.h>
VOID DriverUnload(PDRIVER_OBJECT driver)
{
DbgPrint("EXIT!");
}
ULONG x = 0x12345678;
extern"C"
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
DbgPrint("Welcome Driver,\r\n");
DbgPrint("addr64 = %llx\n", &x);
driver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
拿到线性地址
0xfffff88003173000 很明显这是高2G的内存地址空间
然后利用windbg切换到另一个进程,并查看那个进程的0xfffff88003173000地址内容
可以看到不同进程的高2G内存都是通用的!
内核模块
模块为硬件和操作系统之间的交互做桥梁
- 硬件种类繁多,不可能做一个兼容所有硬件的内核,所以,微软提供规定的接口格式,让硬件驱动人员安装规定的格式编写"驱动程序"
- 这些驱动程序每一个都是一个模块,称为"内核模块",都可以加载到内核中,像之前的ntoskrnl.exe也是模块,和现在自己编写的驱动程序两者没有什么差别.
DRIVER_OBJECT
既然给了你写模块的权利,那就需要一些约束,比如模块们都有相同的入口点DriverEntry一样,这样才好管理.
就像我们即将说的DRIVER_OBJECT 这是一个结构体,这个结构体约束了你想要称为模块而要做出的规范,你的驱动需要按照该结构体来做.每一个模块都需要这个结构体来描述重要信息
1: kd> dt _DRIVER_OBJECT
ntdll!_DRIVER_OBJECT
+0x000 Type : Int2B
+0x002 Size : Int2B
+0x008 DeviceObject : Ptr64 _DEVICE_OBJECT
+0x010 Flags : Uint4B
+0x018 DriverStart : Ptr64 Void//驱动模块所处位置
+0x020 DriverSize : Uint4B//大小
+0x028 DriverSection : Ptr64 Void//对应一个指针,指向的是LDR_DATA_TABLE_ENTRY,这样的一个链表把所有的内核模块全部圈在了一起.
+0x030 DriverExtension : Ptr64 _DRIVER_EXTENSION
+0x038 DriverName : _UNICODE_STRING//名称
+0x048 HardwareDatabase : Ptr64 _UNICODE_STRING
+0x050 FastIoDispatch : Ptr64 _FAST_IO_DISPATCH
+0x058 DriverInit : Ptr64 long
+0x060 DriverStartIo : Ptr64 void
+0x068 DriverUnload : Ptr64 void
+0x070 MajorFunction : [28] Ptr64 long
实验:
#include<ntddk.h>
VOID DriverUnload(PDRIVER_OBJECT driver)
{
DbgPrint("EXIT!");
}
ULONG x = 0x12345678;
extern "C"
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
DbgPrint("Welcome Driver,\r\n");
DbgPrint("addr64 = %llx\n", driver);//读取指向当前驱动程序模块的结构体地址
driver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
拿到结构体地址,用windbg 查看
便可以看到当前驱动模块的信息:
上面结构体还有比较重要的一个
+0x028 DriverSection : Ptr64 Void//对应一个指针,指向的是LDR_DATA_TABLE_ENTRY,这样的一个链表把所有的内核模块全部圈在了一起.
kd> dt _LDR_DATA_TABLE_ENTRY 0xfffffa80`02b8f030
在DriverSection的值的地方查看该结构体:
找到这里 你会发现这张图覆盖了模块的所有细节
并且可以顺着这条链 一直找到所有模块,注意链表有些节点内容是空的,但是不影响可以继续往下找!