附另两种方法链接:
Windows驱动开发学习记录-遍历内核已加载模块之二(使用ZwQuerySystemInformation)
Windows驱动开发学习记录-遍历内核已加载模块之三(使用 AuxKlib)
_LDR_DATA_TABLE_ENTRY为所需要的结构体,具体说明和如何获取该结构体数据见<
现在需要的是该结构体InLoadOrderLinks,这个链表为所有已加载的内核模块的_LDR_DATA_TABLE_ENTRY结构的指针,通过遍历这个链表就可以获取所有已加载的内核模块数据,再取该结构的FullDllName或者BaseDllName即为加载的内核模块的名称和全路径。
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
......
具体详细结构见<
代码如下,实测 XP 32位、Win7 64位以及Win10 64位都能Pass:
//头文件
typedef enum
{
MmTagTypeDS = 'SD' //PrintAllLoadedMoudleByDriverSection
}MmTagType;
typedef struct _LDR_DATA_TABLE_ENTRY {
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
union {
ULONG FlagGroup;
ULONG Flags;
};
}LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
#include
NTSTATUS PrintAllLoadedMoudleByDriverSection(PDRIVER_OBJECT pDriverOjbect)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
if ((pDriverOjbect) && (pDriverOjbect->DriverSection))
{
ANSI_STRING asBaseDllName = { 0 };
ANSI_STRING asFullDllName = { 0 };
PCHAR pBaseDllNameBufer = NULL;
PCHAR pFullDllNameBufer = NULL;
do
{
pBaseDllNameBufer = (PCHAR)ExAllocatePoolWithTag (PagedPool, USHORT_MAX, MmTagTypeDS);
if (pBaseDllNameBufer == NULL)
{
KDPRINT("【PrintLoadedModule】::【PrintAllLoadedMoudleByDriverSection】pBaseDllNameBufer Allocate Memory Failed!\r\n");
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
break;
}
RtlZeroMemory(pBaseDllNameBufer, USHORT_MAX);
pFullDllNameBufer = (PCHAR)ExAllocatePoolWithTag(PagedPool, USHORT_MAX, MmTagTypeDS);
if (pFullDllNameBufer == NULL)
{
KDPRINT("【PrintLoadedModule】::【PrintAllLoadedMoudleByDriverSection】pFullDllNameBufer Allocate Memory Failed!\r\n");
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
break;
}
RtlZeroMemory(pFullDllNameBufer, USHORT_MAX);
RtlInitEmptyAnsiString(&asBaseDllName, pBaseDllNameBufer, USHORT_MAX);
RtlInitEmptyAnsiString(&asFullDllName, pFullDllNameBufer, USHORT_MAX);
PLDR_DATA_TABLE_ENTRY pldte = (PLDR_DATA_TABLE_ENTRY)pDriverOjbect->DriverSection;
if (pldte != NULL)
{
const PLIST_ENTRY pListHeaderInLoadOrder = pldte->InLoadOrderLinks.Flink;
if (pListHeaderInLoadOrder != NULL)
{
ULONG ulCount = 0;
PLIST_ENTRY pListTemp = pListHeaderInLoadOrder;
do
{
PLDR_DATA_TABLE_ENTRY pldteTemp = (PLDR_DATA_TABLE_ENTRY)CONTAINING_RECORD(
pListTemp,
LDR_DATA_TABLE_ENTRY64,
InLoadOrderLinks);
if ((pldteTemp != NULL) &&
(pldteTemp->BaseDllName.Buffer != NULL) &&
(pldteTemp->FullDllName.Buffer != NULL))
{
//1.直接通过DbgPrintEx的 %wZ参数打印 BaseDllName和FullDllName时在XP系统下当时文件路径
// 中有中文的时候会截断,故先转化为ANSI类型再打印,如不需要打印则可将相关ANSI类型的定义
// 初始化以及转换去掉
//2.节点遍历过程中有一个空节点,其中字符串的Buffer为空,通过BaseDllName.Buffer以及
//FullDllName.Buffer为空来跳过
//KDPRINT("【PrintLoadedModule】::【PrintAllLoadedMoudleByDriverSection】Name:%-30wZ Path:%wZ\r\n",
// &pldteTemp->BaseDllName, &pldteTemp->FullDllName);
RtlUnicodeStringToAnsiString(&asBaseDllName, &pldteTemp->BaseDllName, false);
RtlUnicodeStringToAnsiString(&asFullDllName, &pldteTemp->FullDllName, false);
KDPRINT("【PrintLoadedModule】::【PrintAllLoadedMoudleByDriverSection】Name:%-30Z Path:%-130Z Base:0x%p\r\n",
&asBaseDllName, &asFullDllName, pldteTemp->DllBase);
ulCount++;
}
pListTemp = pListTemp->Flink;
} while (pListTemp != pListHeaderInLoadOrder);
KDPRINT("【PrintLoadedModule】::【PrintAllLoadedMoudleByDriverSection】共计%d个内核模块!\r\n", ulCount);
}
}
} while (false);
if (pBaseDllNameBufer)
{
ExFreePoolWithTag(pBaseDllNameBufer, MmTagTypeDS);
pBaseDllNameBufer = NULL;
}
if (pFullDllNameBufer)
{
ExFreePoolWithTag(pFullDllNameBufer, MmTagTypeDS);
pFullDllNameBufer = NULL;
}
}
return ntStatus;
}
EXTERN_C NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,
PUNICODE_STRING pRegistryPath)
{
PrintAllLoadedMoudleByDriverSection(pDriverObject);
return STATUS_SUCCESS;
}
运行结果:
XP 32位:
Win10 64位: