前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >驱动中遍历模块,以及获取ntoskrnl.exe基址

驱动中遍历模块,以及获取ntoskrnl.exe基址

作者头像
IBinary
发布2019-10-21 15:05:53
1.2K0
发布2019-10-21 15:05:53
举报
文章被收录于专栏:逆向技术逆向技术

方法是基于PsLoadModuleList方式

驱动中遍历模块

一丶简介

简介:

进入内核了.遍历内核中使用的模块该怎么办. 其实在驱动中.我们的DriverEntry入口位置. 提供了两个参数. 一个是DrIverObject另一个则是注册表路径.

其实遍历模块的技巧就在这个DriverObject中.

众所周知在Ring3下遍历模块可以通过TEB PEB遍历. 我们会接触一个结构体叫做LDR_DATA_TABLE_ENTRY的结构体. 内核中也会使用这个结构体. 看下DriverObject对象所代表的含义.

代码语言:javascript
复制
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结构体. 里面存放着我们的所有模块.

代码语言:javascript
复制
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)结构.

二丶代码以及演示.

代码语言:javascript
复制
#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;
}

结果.

代码简单改一下.还可以获得指定的模块的基址以及结束地址.

代码如下

代码语言:javascript
复制
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;
    }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-10-17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 驱动中遍历模块
    • 一丶简介
      • 二丶代码以及演示.
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档