遍历系统所有加载的驱动
遍历系统中的驱动可以采用两种方式:
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;
}