内核空间与内核模块

前言:内核空间与内核模块的学习笔记

内核空间概念

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;
}

posted @   zpchcbd  阅读(224)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示