方法是基於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; } }