遍历系统所有加载的驱动

c++

Posted by YiMiTuMi on March 28, 2021

遍历系统所有加载的驱动

遍历系统中的驱动可以采用两种方式:

1)每个驱动都有一个 _DRIVE_OBJECT 成员,这个成员,用 WinDbg 打印出来是这样的:

kd> dt _DRIVER_OBJECT 85696180
ntdll!_DRIVER_OBJECT
   +0x000 Type             : 0n4
   +0x002 Size             : 0n168
   +0x004 DeviceObject     : (null) 
   +0x008 Flags            : 0x12
   +0x00c DriverStart      : 0x92528000 Void
   +0x010 DriverSize       : 0x6000
   +0x014 DriverSection    : 0x8566b460 Void
   +0x018 DriverExtension  : 0x85696228 _DRIVER_EXTENSION
   +0x01c DriverName       : _UNICODE_STRING "\Driver\FirstDrive"
   +0x024 HardwareDatabase : 0x841a8250 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"
   +0x028 FastIoDispatch   : (null) 
   +0x02c DriverInit       : 0x92529140     long  FirstDrive!FxDriverEntry+0
   +0x030 DriverStartIo    : (null) 
   +0x034 DriverUnload     : 0x925292f0     void  FirstDrive!DriverUpLoad+0
   +0x038 MajorFunction    : [28] 0x83ef1da3     long  nt!IopInvalidDeviceRequest+0

其中所有的驱动的前两个字节是一样的 ,所以我们可以通过遍历所有内存将驱动找出来,这样即使是将驱动模块断链后依旧可检测的到,要躲避这种查找,可以通过修改前两个字节来实现。

2)在 _DRIVE_OBJECT 结构中 DriverSection 指一个结构体 _LDR_DATA_TABL_ENTRY,同时这个 地址也是链表的 LIST_ENTRY 的一个成员,这个成员把系统所有加载(可能是停止没被卸载)已经读取到内存,我们关系第一个,我们要遍历链表 (双链表) 不管中间哪个节点都可以遍历整个链表,本驱动的驱动对象就是一个节点。

_LDR_DATA_TABL_ENTRY

kd> dt _LDR_DATA_TABLE_ENTRY 8566b460
ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x855f4cd0 - 0x86731cf8 ]
   +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0xffffffff - 0xffffffff ]
   +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x630069 - 0x0 ]
   +0x018 DllBase          : 0x92528000 Void
   +0x01c EntryPoint       : 0x92529140 Void
   +0x020 SizeOfImage      : 0x6000
   +0x024 FullDllName      : _UNICODE_STRING "\??\C:\Users\windows7-32-windbg\Desktop\FirstDrive.sys"
   +0x02c BaseDllName      : _UNICODE_STRING "FirstDrive.sys"
   +0x034 Flags            : 0x49104000
   +0x038 LoadCount        : 1
   +0x03a TlsIndex         : 0x69
   +0x03c HashLinks        : _LIST_ENTRY [ 0x0 - 0x79ef ]
   +0x03c SectionPointer   : (null) 
   +0x040 CheckSum         : 0x79ef
   +0x044 TimeDateStamp    : 0x5c0073
   +0x044 LoadedImports    : 0x005c0073 Void
   +0x048 EntryPointActivationContext : (null) 
   +0x04c PatchInformation : 0xa07424d8 Void
   +0x050 ForwarderLinks   : _LIST_ENTRY [ 0x0 - 0x6000 ]
   +0x058 ServiceTagLinks  : _LIST_ENTRY [ 0x605ef844 - 0x690046 ]
   +0x060 StaticLinks      : _LIST_ENTRY [ 0x730072 - 0x440074 ]
   +0x068 ContextInformation : 0x00690072 Void
   +0x06c OriginalBase     : 0x650076
   +0x070 LoadTime         : _LARGE_INTEGER 0x00730079`0073002e

用方法二遍历链表:

#include <ntddk.h>

typedef struct _LDR_DATA_TABLE_ENTRY
{
	LIST_ENTRY InLoadOrderLinks; //这个成员把系统所有加载(可能是停止没被卸载)已经读取到内存中 我们关系第一个  我们要遍历链表 双链表 不管中间哪个节点都可以遍历整个链表 本驱动的驱动对象就是一个节点
	LIST_ENTRY InMemoryOrderLinks; //系统已经启动 没有被初始化 没有调用DriverEntry这个历程的时候 通过这个链表进程串接起来
	LIST_ENTRY InInitializationOrderLinks; //已经调用DriverEntry这个函数的所有驱动程序
	PVOID DllBase;
	PVOID EntryPoint; //驱动的进入点 DriverEntry
	ULONG SizeOfImage;
	UNICODE_STRING FullDllName;  //驱动的满路径
	UNICODE_STRING BaseDllName;  //不带路径的驱动名字
	ULONG Flags; 
	USHORT LoadCount;
	USHORT TlsIndex;
	union
	{
		LIST_ENTRY HashLinks;
		struct
		{
			PVOID SectionPointer;
			ULONG CheckSum;
		};
	};
	union
	{
		ULONG TimeDateStamp;
		PVOID LoadedImports;
	};
	PVOID EntryPointActivationContext;   //暂时不知道 这个上下文结构体
	PVOID PatchInformation;
	LIST_ENTRY ForwarderLinks;
	LIST_ENTRY ServiceTagLinks;
	LIST_ENTRY StaticLinks;
} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;

//卸载
VOID DriverUpLoad(PDRIVER_OBJECT pdriver)
{
	DbgPrint("卸载了\n");
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pdriver, PUNICODE_STRING pReg) //返回一个地址、返回驱动被注册到注册表的某个地方
{
	DbgPrint("pdriver = %wZ, , %x\n", pReg, pdriver);

	PLDR_DATA_TABLE_ENTRY pData = (PLDR_DATA_TABLE_ENTRY)pdriver->DriverSection;

	if (pData == NULL)
	{
		DbgPrint("PLDR_DATA_TABLE_ENTRY 为空!");
	}
	else
	{
		DbgPrint("PLDR_DATA_TABLE_ENTRY = %x\n", pData);
		//DbgPrint("%wZ\n", &(pData->FullDllName));
	}

	//PLIST_ENTRY pStartLIST = &(pData->InLoadOrderLinks);
	PLIST_ENTRY pListEntry = &(pData->InLoadOrderLinks);
	SHORT Start = FALSE;

	while (pListEntry != NULL)
	{
		if ((PLIST_ENTRY)pData == pListEntry && Start)
		{
			break;
		}

		Start = TRUE;

		DbgPrint("pListEntry = %x\n", pListEntry);

		DbgPrint("%wZ\n", &(((PLDR_DATA_TABLE_ENTRY)pListEntry)->FullDllName));
		pListEntry = ((PLDR_DATA_TABLE_ENTRY)pListEntry)->InLoadOrderLinks.Flink;
	}

	/*
	//断链,将自己的下一个节点复制给上一个 
	((PLIST_ENTRY)(pData->InLoadOrderLinks.Flink))->Blink = pData->InLoadOrderLinks.Blink;
	*/

	pdriver->DriverUnload = DriverUpLoad;
	return STATUS_SUCCESS;
}

野百合花语 – 永远幸福