内核空间与内核模块
前言:内核空间与内核模块的学习笔记
内核空间概念
interlX86下每个进程都有4GB的虚拟内存空间下,其中高2G是共享的内核空间,在低2G的私有内存也就是用户空间
内核模块概念
1、硬件种类繁多,不可能做一个兼容所有硬件的内核,所以,微软提供规定的接口格式,让硬件驱动人员安装规定的格式编写"驱动程序"。
2、这些驱动程序每一个都是一个模块,称为"内核模块",都可以加载到内核中,都遵守PE结构。但本质上讲,任意一个.sys文件与内核文件没有区别。
知识点:驱动程序和应用程序本质上讲其实没有区别,都是遵守了PE结构,.sys其实和.exe是一样的,唯一不同的就是后缀名和所在的运行空间还有入口函数
DRIVER_OBJECT结构体
每一个被加载的驱动模块sys都会有一个驱动对象DRIVER_OBJECT来描述当前驱动模块的信息,如下所示,这个值保存的是当前驱动模块对象DRIVER_OBJECT
通过windbg来进行查看对应的结构体,命令为dt _DRIVER_OBJECT
kd> dt _driver_object ntdll!_DRIVER_OBJECT +0x000 Type : Int2B +0x002 Size : Int2B +0x004 DeviceObject : Ptr32 _DEVICE_OBJECT +0x008 Flags : Uint4B +0x00c DriverStart : Ptr32 Void +0x010 DriverSize : Uint4B +0x014 DriverSection : Ptr32 Void +0x018 DriverExtension : Ptr32 _DRIVER_EXTENSION +0x01c DriverName : _UNICODE_STRING +0x024 HardwareDatabase : Ptr32 _UNICODE_STRING +0x028 FastIoDispatch : Ptr32 _FAST_IO_DISPATCH +0x02c DriverInit : Ptr32 long +0x030 DriverStartIo : Ptr32 void +0x034 DriverUnload : Ptr32 void +0x038 MajorFunction : [28] Ptr32 long
通过DRIVER_OBJECT找到当前模块信息:
DbgPrint("DRIVER_OBJECT对象地址:%x\n",driver); DbgPrint("驱动名称:%ws\n",driver->DriverName.Buffer); DbgPrint("模块基址:%x\n",driver->DriverStart); DbgPrint("模块大小:%x\n",driver->DriverSize);
结果如下图所示:
这里还可以查看已加载的驱动模块的结构体,通过dt _DRIVER_OBJECT 当前DRIVER_OBJECT的地址
,上面可以看到对应的驱动模块基址0x86b58ae8
dt _DRIVER_OBJECT 0x86b58ae8
,可以看到相关的驱动名称
+0x00c DriverStart : 0xf79b6000 Void
模块在高2G内存中的起始位置:+0x00c DriverStart : 0xf79b6000 Void
模块的大小:+0x010 DriverSize : 0x6000
模块的名称:+0x01c DriverName : _UNICODE_STRING "\Driver\WinDriverStudy01"
该模块DriverSection(偏移为0x014)实际上就是一个LDR_DATA_TABLE_ENTRY结构体,它跟三环下的PEB相关的LDR_DATA_TABLE_ENTRY结构体一样
dt _LDR_DATA_TABLE_ENTRY DriverSection的地址
这里还可以通过双向链表来进行遍历,如下图所示
练习1
遍历内核模块,输出模块名称,基址以及大小
#include <ntddk.h> typedef struct _PEB_LDR_DATA { ULONG Length; BOOLEAN Initialized; PVOID SsHandle; LIST_ENTRY InLoadOrderModuleList; //代表按加载顺序构成的模块列表 LIST_ENTRY InMemoryOrderModuleList; //代表按内存顺序构成的模块列表 LIST_ENTRY InInitializationOrderModuleList; //代表按初始化顺序构成的模块链表 }PEB_LDR_DATA, *PPEB_LDR_DATA; typedef struct _LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderModuleList; //代表按加载顺序构成的模块列表 LIST_ENTRY InMemoryOrderModuleList; //代表按内存顺序构成的模块列表 LIST_ENTRY InInitializeationOrderModuleList; //代表按初始化顺序构成的模块链表 PVOID DllBase; //该模块的基地址 PVOID EntryPoint; //该模块的入口 ULONG SizeOfImage; //该模块的影像大小 UNICODE_STRING FullDllName; //模块的完整路径 UNICODE_STRING BaseDllName; //模块名 ULONG Flags; SHORT LoadCount; SHORT TlsIndex; HANDLE SectionHandle; ULONG CheckSum; ULONG TimeDataStamp; }LDR_MODULE, *PLDR_MODULE; VOID UnDriver(PDRIVER_OBJECT driver) { DbgPrint(("Uninstall Driver Is OK \n")); } void getAllDriverModules(PDRIVER_OBJECT Driver) { __try{ // 遍历内核模块,输出模块名称,基址以及大小 LDR_MODULE* pLdrModule = NULL; pLdrModule = (LDR_MODULE*)(*(ULONG*)((CHAR*)Driver + 0x14)); while (pLdrModule->DllBase != NULL) { DbgPrint("DllName: %ws DllBase: 0x%x, SizeOfImage: 0x%x\n", pLdrModule->BaseDllName.Buffer, pLdrModule->DllBase, pLdrModule->SizeOfImage); pLdrModule = (LDR_MODULE*)pLdrModule->InLoadOrderModuleList.Blink; } } __except (EXCEPTION_EXECUTE_HANDLER) { DbgPrint("Exception Error..."); } } NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath) { DbgPrint(("hello zpchcbd \n")); getAllDriverModules(Driver); Driver->DriverUnload = UnDriver; return STATUS_SUCCESS; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY