利用PsLoadModuleList 杖举驱动模块

本文详细解析了PsLoadedModuleList作为系统全局变量的功能及其与驱动加载过程的关系,深入探讨了DRIVER_OBJECT、LDR_DATA_TABLE_ENTRY等关键结构的作用,并提供了代码示例来演示如何遍历所有已加载驱动模块。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PsLoadedModuleList是系统的一个全局变量,它指向一个保存着所加载驱动信息的双向链表。通过它可以枚举系统中所有的驱动模块。

这个双向链表的结构如下:

kd> dt _LIST_ENTRY
nt!_LIST_ENTRY
   +0x000 Flink            : Ptr32 _LIST_ENTRY      //指向后一个链表
   +0x004 Blink            : Ptr32 _LIST_ENTRY      //指向前一个链表

每一个驱动对象都存在这样一个结构.我们先看_DRIVER_OBJECT的结构

kd> dt _DRIVER_OBJECT
nt!_DRIVER_OBJECT
   +0x000 Type             : Int2B
   +0x002 Size             : Int2B
   +0x004 DeviceObject     : Ptr32 _DEVICE_OBJECT            //设备对象
   +0x008 Flags            : Uint4B
   +0x00c DriverStart      : Ptr32 Void                        //驱动对象起始地址
   +0x010 DriverSize       : Uint4B                            //驱动对象的大小
   +0x014 DriverSection    : Ptr32 Void                        //**这个实际上是一个LDR_DATA_TABLE_ENTRY 指针
   +0x018 DriverExtension  : Ptr32 _DRIVER_EXTENSION
   +0x01c DriverName       : _UNICODE_STRING                //驱动对象的名字
   +0x024 HardwareDatabase : Ptr32 _UNICODE_STRING
   +0x028 FastIoDispatch   : Ptr32 _FAST_IO_DISPATCH
   +0x02c DriverInit       : Ptr32     long 
   +0x030 DriverStartIo    : Ptr32     void 
   +0x034 DriverUnload     : Ptr32     void 
   +0x038 MajorFunction    : [28] Ptr32     long 

LDT_DATA_TABLE_ENTRY结构中的第一项就是LIST_ENTRY结构.这个LIST_ENTRY结构就是加载的驱动模块的链表

kd> dt _LDR_DATA_TABLE_ENTRY
nt!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY                //驱动加载链表
   +0x008 InMemoryOrderLinks : _LIST_ENTRY
   +0x010 InInitializationOrderLinks : _LIST_ENTRY
   +0x018 DllBase          : Ptr32 Void
   +0x01c EntryPoint       : Ptr32 Void
   +0x020 SizeOfImage      : Uint4B
   +0x024 FullDllName      : _UNICODE_STRING
   +0x02c BaseDllName      : _UNICODE_STRING
   +0x034 Flags            : Uint4B
   +0x038 LoadCount        : Uint2B
   +0x03a TlsIndex         : Uint2B
   +0x03c HashLinks        : _LIST_ENTRY
   +0x03c SectionPointer   : Ptr32 Void
   +0x040 CheckSum         : Uint4B
   +0x044 TimeDateStamp    : Uint4B
   +0x044 LoadedImports    : Ptr32 Void
   +0x048 EntryPointActivationContext : Ptr32 Void
   +0x04c PatchInformation : Ptr32 Void

 

通过这三个结构的分析,我们就弄清楚了.

DRIVER_OBJECT +0x14  就得到了LIST_ENTRY 链表,通过对这个链表的遍历就能得到所有的驱动模块

 

//头文件
typedef struct
{
    LIST_ENTRY InLoadOrderLink;
    LIST_ENTRY InMemoryOrderLinks;
    LIST_ENTRY InInitializationOrderLinks;
    PVOID DllBase;
    PVOID EntryPoint;
    ULONG SizeOfImage;
    UNICODE_STRING FullDllName;
    UNICODE_STRING BaseDllName;
    ULONG Flags;
    USHORT LoadCount;
    USHORT TlsIndex;
    LIST_ENTRY HashLinks;
    PVOID SectionPointer;
    ULONG CheckSum;
    ULONG TimeDateStamp;
    PVOID LoadedImports;
    PVOID EntryPointActivationContext;
    PVOID PatchInformation;
}LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;

代码:

#include "ntddk.h"
#include "rootkit.h"

void OnUnload(PDRIVER_OBJECT pDriverObj)
{
    DbgPrint("Driver is Unload!\n");
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pRootkitObj,PUNICODE_STRING pRegistPath)
{
    
    PLDR_DATA_TABLE_ENTRY pDriverList;
    PLIST_ENTRY pCurrentList;


    pRootkitObj->DriverUnload=OnUnload;
    
    pDriverList=(PLDR_DATA_TABLE_ENTRY) (pRootkitObj->DriverSection);
    pCurrentList=(PLIST_ENTRY) pDriverList;

    while (((PLIST_ENTRY)pDriverList)->Blink!=pCurrentList)
    {

        DbgPrint("DriverBase=0x%08X        \tDriverSize 0x%08X      \tDriverName=%ws\n",
            pDriverList->DllBase,
            pDriverList->SizeOfImage,
            (pDriverList->BaseDllName).Buffer);
            

        pDriverList=((PLIST_ENTRY)pDriverList)->Blink;
    }
    return STATUS_SUCCESS;
}

 

转载于:https://www.cnblogs.com/ktr39/p/3494875.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值