方法是基於PsLoadModuleList方式
驅動中遍歷模塊
一丶簡介
簡介:
進入內核了.遍歷內核中使用的模塊該怎么辦. 其實在驅動中.我們的DriverEntry入口位置.
提供了兩個參數. 一個是DrIverObject另一個則是注冊表路徑.
其實遍歷模塊的技巧就在這個DriverObject中.
眾所周知在Ring3下遍歷模塊可以通過TEB PEB遍歷. 我們會接觸一個結構體叫做LDR_DATA_TABLE_ENTRY的結構體.
內核中也會使用這個結構體. 看下DriverObject對象所代表的含義.
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結構體.
里面存放着我們的所有模塊.
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)結構.
二丶代碼以及演示.
#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;
}
}
