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;
为了能够遍历出所有的系统驱动,我们需要得到pLdr
结构,该结构可通过Driver->DriverSection
的方式获取到,获取到之后通过pLdr->InLoadOrderLinks.Flink
得到当前驱动的入口地址,而每一次调用pListEntry->Flink
都将会指向下一个驱动对象,通过不断地循环CONTAINING_RECORD
解析,即可输出当前系统内所有驱动的详细信息。这段程序的写法可以如下所示;
// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com
#include <ntifs.h>
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;
VOID UnDriver(PDRIVER_OBJECT driver)
{
DbgPrint(("Uninstall Driver Is OK \n"));
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
DbgPrint("hello lyshark \n");
Driver->DriverUnload = UnDriver;
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)Driver->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("模块名 = %wZ | 模块基址 = %p | 模块入口 = %p | 模块时间戳 = %d \n",
pCurrentModule->BaseDllName,
pCurrentModule->DllBase,
pCurrentModule->EntryPoint,
pCurrentModule->TimeDateStamp);
}
pCurrentListEntry = pCurrentListEntry->Flink;
}
Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}
编译这段程序,签名并运行,我们即可看到如下输出信息,此时当前自身驱动的详细参数都可以被输出;
通过使用上一篇文章《驱动开发:内核字符串拷贝与比较》
中所介绍的的RtlCompareUnicodeString
函数,还可用于对比与过滤特定结果,以此来实现通过驱动名返回驱动基址的功能。
LONGLONG 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)
{
return (LON