方法是基于PsLoadModuleList方式spa
#驱动中遍历模块3d
##一丶简介code
简介:对象
进入内核了.遍历内核中使用的模块该怎么办. 其实在驱动中.咱们的DriverEntry入口位置. 提供了两个参数. 一个是DrIverObject另外一个则是注册表路径.blog
其实遍历模块的技巧就在这个DriverObject中.内存
众所周知在Ring3下遍历模块能够经过TEB PEB遍历. 咱们会接触一个结构体叫作LDR_DATA_TABLE_ENTRY的结构体. 内核中也会使用这个结构体. 看下DriverObject对象所表明的含义.it
typedef struct _DRIVER_OBJECT { CSHORT Type; CSHORT Size; PDEVICE_OBJECT DeviceObject; //驱动对象 ULONG Flags; //驱动的标志 PVOID DriverStart; //驱动的起始位置 ULONG DriverSize; //驱动的大小 PVOID DriverSection; //指向驱动程序映像的内存区对象 PDRIVER_EXTENSION DriverExtension; //驱动的扩展空间 UNICODE_STRING DriverName; //驱动名字 PUNICODE_STRING HardwareDatabase; PFAST_IO_DISPATCH FastIoDispatch; PDRIVER_INITIALIZE DriverInit; PDRIVER_STARTIO DriverStartIo; PDRIVER_UNLOAD DriverUnload; PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; } DRIVER_OBJECT; typedef struct _DRIVER_OBJECT *PDRIVER_OBJECT;
在这里主要使用 DriverSection这个成员 这个成员则能够解释为LDR_DATA_TABLE_ENTRY结构体. 里面存放着咱们的全部模块.io
typedef struct _LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderLinks; //链表存储,指向下一个LDR_DATA_TABLE_ENTRY结构 LIST_ENTRY InMemoryOrderLinks; LIST_ENTRY InInitializationOrderLinks; PVOID DllBase; //基址 PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; //存放着驱动模块名 ULONG Flags; USHORT LoadCount; USHORT TlsIndex; union { LIST_ENTRY HashLinks; struct { PVOID SectionPointer; ULONG CheckSum; }; }; union { struct { ULONG TimeDateStamp; }; struct { PVOID LoadedImports; }; }; }LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
因此代码就很简单了.直接遍历自身结构体的 DriverSection成员便可.解释为(LDR_DATA_TABLE_ENTRY)结构.ast
##二丶代码以及演示.class
#include "Driver.h" //这个替换为本身的. 包含Ntddk.h便可. #include <wdm.h> //KLDR_DATA_TABLE_ENTRY 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; ULONG Flags; USHORT LoadCount; USHORT TlsIndex; union { LIST_ENTRY HashLinks; struct { PVOID SectionPointer; ULONG CheckSum; }; }; union { struct { ULONG TimeDateStamp; }; struct { PVOID LoadedImports; }; }; }LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath) { ULONG iCount = 0; NTSTATUS ntStatus; pDriverObj->DriverUnload = DriverUnLoad; KdBreakPoint(); /* 主要是遍历DriverObject中的 DriverSection 它能够解释为LDR_DATA_TABLE_ENTRY结构体 */ PLDR_DATA_TABLE_ENTRY pLdr = NULL; PLIST_ENTRY pListEntry = NULL; PLIST_ENTRY pCurrentListEntry = NULL; PLDR_DATA_TABLE_ENTRY pCurrentModule = NULL; pLdr = (PLDR_DATA_TABLE_ENTRY)pDriverObj->DriverSection; pListEntry = pLdr->InLoadOrderLinks.Flink; pCurrentListEntry = pListEntry->Flink; while (pCurrentListEntry != pListEntry) //先后不相等 { //获取LDR_DATA_TABLE_ENTRY结构 pCurrentModule = CONTAINING_RECORD(pCurrentListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); if (pCurrentModule->BaseDllName.Buffer != 0) { DbgPrint("ModuleName = %wZ ModuleBase = %p \r\n", pCurrentModule->BaseDllName, pCurrentModule->DllBase); } pCurrentListEntry = pCurrentListEntry->Flink; } return STATUS_SUCCESS; }
结果.
代码简单改一下.还能够得到指定的模块的基址以及结束地址.
代码以下
VOID GetModuleBaseByName(PDRIVER_OBJECT pDriverObj,UNICODE_STRING ModuleName) { PLDR_DATA_TABLE_ENTRY pLdr = NULL; PLIST_ENTRY pListEntry = NULL; PLIST_ENTRY pCurrentListEntry = NULL; PLDR_DATA_TABLE_ENTRY pCurrentModule = NULL; pLdr = (PLDR_DATA_TABLE_ENTRY)pDriverObj->DriverSection; pListEntry = pLdr->InLoadOrderLinks.Flink; pCurrentListEntry = pListEntry->Flink; while (pCurrentListEntry != pListEntry) //先后不相等 { //获取LDR_DATA_TABLE_ENTRY结构 pCurrentModule = CONTAINING_RECORD(pCurrentListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); if (pCurrentModule->BaseDllName.Buffer != 0) { if (RtlCompareUnicodeString(&pCurrentModule->BaseDllName, &ModuleName, TRUE) == 0) { DbgPrint("ModuleName = %wZ ModuleBase = %p ModuleEndBase = %p\r\n", pCurrentModule->BaseDllName, pCurrentModule->DllBase, (LONGLONG)pCurrentModule->DllBase + pCurrentModule->SizeOfImage); } } pCurrentListEntry = pCurrentListEntry->Flink; } }