Windows驱动开发学习记录-遍历内核已加载模块之一(使用DriverSection)
- 附另两种方法链接:
《Windows驱动开发学习记录-遍历内核已加载模块之二(使用ZwQuerySystemInformation)》
《Windows驱动开发学习记录-遍历内核已加载模块之三(使用 AuxKlib)》
1.关键结构体
_LDR_DATA_TABLE_ENTRY为所需要的结构体,具体说明和如何获取该结构体数据见《Windows驱动开发学习记录-驱动中获取当前驱动文件路径》
现在需要的是该结构体InLoadOrderLinks,这个链表为所有已加载的内核模块的_LDR_DATA_TABLE_ENTRY结构的指针,通过遍历这个链表就可以获取所有已加载的内核模块数据,再取该结构的FullDllName或者BaseDllName即为加载的内核模块的名称和全路径。
2.结构体_LDR_DATA_TABLE_ENTRY重要成员
0: kd> dt _LDR_DATA_TABLE_ENTRY
nt!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY
+0x010 InMemoryOrderLinks : _LIST_ENTRY
+0x020 InInitializationOrderLinks : _LIST_ENTRY
+0x030 DllBase : Ptr64 Void
+0x038 EntryPoint : Ptr64 Void
+0x040 SizeOfImage : Uint4B
+0x048 FullDllName : _UNICODE_STRING
+0x058 BaseDllName : _UNICODE_STRING
+0x068 FlagGroup : [4] UChar
......
具体详细结构见《Windows驱动开发学习记录-驱动中获取当前驱动文件路径 》
3.实现
代码如下,实测 XP 32位、Win7 64位以及Win10 64位都能Pass。
.h文件
1 //头文件 2 3 #if DBG 4 #define KDPRINT(projectName, format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, projectName "::【" __FUNCTION__ "】" ##format, ##__VA_ARGS__ ) 5 #else 6 #define KDPRINT(format, ...) 7 #endif 8 9 typedef enum 10 { 11 MmTagTypeDS = 'SD' //PrintAllLoadedMoudleByDriverSection 12 }MmTagType; 13 14 typedef struct _LDR_DATA_TABLE_ENTRY { 15 LIST_ENTRY InLoadOrderLinks; 16 LIST_ENTRY InMemoryOrderLinks; 17 LIST_ENTRY InInitializationOrderLinks; 18 PVOID DllBase; 19 PVOID EntryPoint; 20 ULONG SizeOfImage; 21 UNICODE_STRING FullDllName; 22 UNICODE_STRING BaseDllName; 23 union { 24 ULONG FlagGroup; 25 ULONG Flags; 26 }; 27 }LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
.cpp文件
1 //.cpp 2 NTSTATUS PrintAllLoadedMoudleByDriverSection(PDRIVER_OBJECT pDriverOjbect) 3 { 4 NTSTATUS ntStatus = STATUS_SUCCESS; 5 if ((pDriverOjbect) && (pDriverOjbect->DriverSection)) 6 { 7 ANSI_STRING asBaseDllName = { 0 }; 8 ANSI_STRING asFullDllName = { 0 }; 9 PCHAR pBaseDllNameBufer = NULL; 10 PCHAR pFullDllNameBufer = NULL; 11 do 12 { 13 pBaseDllNameBufer = (PCHAR)ExAllocatePoolWithTag(PagedPool, USHORT_MAX, MmTagTypeDS); 14 if (pBaseDllNameBufer == NULL) 15 { 16 KDPRINT("【PrintLoadedModule】", "pBaseDllNameBufer Allocate Memory Failed!\r\n"); 17 ntStatus = STATUS_INSUFFICIENT_RESOURCES; 18 break; 19 } 20 RtlZeroMemory(pBaseDllNameBufer, USHORT_MAX); 21 pFullDllNameBufer = (PCHAR)ExAllocatePoolWithTag(PagedPool, USHORT_MAX, MmTagTypeDS); 22 if (pFullDllNameBufer == NULL) 23 { 24 KDPRINT("【PrintLoadedModule】", "pFullDllNameBufer Allocate Memory Failed!\r\n"); 25 ntStatus = STATUS_INSUFFICIENT_RESOURCES; 26 break; 27 } 28 RtlZeroMemory(pFullDllNameBufer, USHORT_MAX); 29 RtlInitEmptyAnsiString(&asBaseDllName, pBaseDllNameBufer, USHORT_MAX); 30 RtlInitEmptyAnsiString(&asFullDllName, pFullDllNameBufer, USHORT_MAX); 31 PLDR_DATA_TABLE_ENTRY pldte = (PLDR_DATA_TABLE_ENTRY)pDriverOjbect->DriverSection; 32 if (pldte != NULL) 33 { 34 const PLIST_ENTRY pListHeaderInLoadOrder = pldte->InLoadOrderLinks.Flink; 35 if (pListHeaderInLoadOrder != NULL) 36 { 37 ULONG ulCount = 0; 38 PLIST_ENTRY pListTemp = pListHeaderInLoadOrder; 39 do 40 { 41 PLDR_DATA_TABLE_ENTRY pldteTemp = (PLDR_DATA_TABLE_ENTRY)CONTAINING_RECORD( 42 pListTemp, 43 LDR_DATA_TABLE_ENTRY64, 44 InLoadOrderLinks); 45 if ((pldteTemp != NULL) && 46 (pldteTemp->BaseDllName.Buffer != NULL) && 47 (pldteTemp->FullDllName.Buffer != NULL)) 48 { 49 //1.直接通过DbgPrintEx的 %wZ参数打印 BaseDllName和FullDllName时在XP系统下当时文件路径 50 // 中有中文的时候会截断,故先转化为ANSI类型再打印,如不需要打印则可将相关ANSI类型的定义 51 // 初始化以及转换去掉 52 //2.节点遍历过程中有一个空节点,其中字符串的Buffer为空,通过BaseDllName.Buffer以及 53 //FullDllName.Buffer为空来跳过 54 //KDPRINT("【PrintLoadedModule】","Name:%-30wZ Path:%wZ\r\n", 55 // &pldteTemp->BaseDllName, &pldteTemp->FullDllName); 56 RtlUnicodeStringToAnsiString(&asBaseDllName, &pldteTemp->BaseDllName, false); 57 RtlUnicodeStringToAnsiString(&asFullDllName, &pldteTemp->FullDllName, false); 58 KDPRINT("【PrintLoadedModule】", "Name:%-30Z Path:%-130Z Base:0x%p\r\n", 59 &asBaseDllName, &asFullDllName, pldteTemp->DllBase); 60 61 ulCount++; 62 } 63 pListTemp = pListTemp->Flink; 64 65 } while (pListTemp != pListHeaderInLoadOrder); 66 67 KDPRINT("【PrintLoadedModule】", "共计%d个内核模块!\r\n", ulCount); 68 } 69 } 70 } while (false); 71 if (pBaseDllNameBufer) 72 { 73 ExFreePoolWithTag(pBaseDllNameBufer, MmTagTypeDS); 74 pBaseDllNameBufer = NULL; 75 } 76 if (pFullDllNameBufer) 77 { 78 ExFreePoolWithTag(pFullDllNameBufer, MmTagTypeDS); 79 pFullDllNameBufer = NULL; 80 } 81 } 82 return ntStatus; 83 } 84 85 86 EXTERN_C NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, 87 PUNICODE_STRING pRegistryPath) 88 { 89 PrintAllLoadedMoudleByDriverSection(pDriverObject); 90 return STATUS_SUCCESS; 91 }
4.运行效果
xp 32位:
Win10 64位: