• 通过PEB的Ldr枚举进程内所有已加载的模块


    一、几个重要的数据结构,可以通过windbg的dt命令查看其详细信息

    _PEB、_PEB_LDR_DATA、_LDR_DATA_TABLE_ENTRY

    二、技术原理

    1、通过fs:[30h]获取当前进程的_PEB结构

    2、通过_PEB的Ldr成员获取_PEB_LDR_DATA结构

    3、通过_PEB_LDR_DATA的InMemoryOrderModuleList成员获取_LIST_ENTRY结构

    4、通过_LIST_ENTRY的Flink成员获取_LDR_DATA_TABLE_ENTRY结构,注意:这里的Flink指向的是_LDR_DATA_TABLE_ENTRY结构中的InMemoryOrderLinks成员,因此需要计算真正的_LDR_DATA_TABLE_ENTRY起始地址,我们可以用CONTAINING_RECORD来计算。

    5、输出_LDR_DATA_TABLE_ENTRY的BaseDllName或FullDllName成员信息。

    三、代码实现(基于XP sp2 系统)

    //EnumInLoadModule.c  
    //compile:cl EnumInLoadModule.c  
    #include <windows.h>  
    
    #define CONTAINING_RECORD(address, type, field) ((type *)( /  
    (PCHAR)(address) - /  
    (ULONG_PTR)(&((type *)0)->field)))  
    
    typedef struct _UNICODE_STRING {  
        USHORT  Length;  
        USHORT  MaximumLength;  
        PWSTR  Buffer;  
    } UNICODE_STRING, *PUNICODE_STRING;  
    
    typedef struct _PEB_LDR_DATA  
    {  
        DWORD Length;  
        UCHAR Initialized;  
        PVOID SsHandle;  
        LIST_ENTRY InLoadOrderModuleList;  
        LIST_ENTRY InMemoryOrderModuleList;  
        LIST_ENTRY InInitializationOrderModuleList;  
        PVOID EntryInProgress;  
    }PEB_LDR_DATA,*PPEB_LDR_DATA;  
    
    typedef struct _LDR_DATA_TABLE_ENTRY  
    {  
        LIST_ENTRY InLoadOrderLinks;  
        LIST_ENTRY InMemoryOrderLinks;  
        LIST_ENTRY InInitializationOrderLinks;  
        PVOID DllBase;  
        PVOID EntryPoint;  
        DWORD SizeOfImage;  
        UNICODE_STRING FullDllName;  
        UNICODE_STRING BaseDllName;  
        DWORD Flags;  
        WORD LoadCount;  
        WORD TlsIndex;  
        LIST_ENTRY HashLinks;  
        PVOID SectionPointer;  
        DWORD CheckSum;  
        DWORD TimeDateStamp;  
        PVOID LoadedImports;  
        PVOID EntryPointActivationContext;  
        PVOID PatchInformation;  
    }LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;  
    
    typedef struct _PEB  
    {  
        UCHAR InheritedAddressSpace;  
        UCHAR ReadImageFileExecOptions;  
        UCHAR BeingDebugged;  
        UCHAR SpareBool;  
        PVOID Mutant;  
        PVOID ImageBaseAddress;  
        PPEB_LDR_DATA Ldr;  
    }PEB,*PPEB;  
    
    int main(void)  
    {  
        PLDR_DATA_TABLE_ENTRY pLdrDataEntry = NULL;  
        PLIST_ENTRY pListEntryStart = NULL,pListEntryEnd = NULL;  
        PPEB_LDR_DATA pPebLdrData = NULL;  
        PPEB pPeb = NULL;  
    
        //故意加载一些DLL,以便测试!  
        LoadLibrary("ResLibDemo");  
        __asm  
        {  
            //1、通过fs:[30h]获取当前进程的_PEB结构  
            mov eax,dword ptr fs:[30h];  
            mov pPeb,eax  
        }  
    
        //2、通过_PEB的Ldr成员获取_PEB_LDR_DATA结构  
        pPebLdrData = pPeb->Ldr;  
    
        //3、通过_PEB_LDR_DATA的InMemoryOrderModuleList成员获取_LIST_ENTRY结构  
        pListEntryStart = pListEntryEnd = pPebLdrData->InMemoryOrderModuleList.Flink;  
    
        //查找所有已载入到内存中的模块  
        do  
        {  
            //4、通过_LIST_ENTRY的Flink成员获取_LDR_DATA_TABLE_ENTRY结构  
            pLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)CONTAINING_RECORD(pListEntryStart,LDR_DATA_TABLE_ENTRY,InMemoryOrderLinks);  
    
            //5、输出_LDR_DATA_TABLE_ENTRY的BaseDllName或FullDllName成员信息  
            printf("%S/n",pLdrDataEntry->BaseDllName.Buffer);  
    
            pListEntryStart = pListEntryStart->Flink;  
    
        }while(pListEntryStart != pListEntryEnd);  
    }  
    
    /* 
    output: 
    EnumInLoadModule.exe 
    ntdll.dll 
    kernel32.dll 
    ResLibDemo.dll 
    ... 
    */
    

      

  • 相关阅读:
    Go语言学习之1 基本概念、环境搭建、第一个Go程序
    go环境搭建
    go 圣经阅读笔记之-入门
    RabbitMQ
    图片选择并使用base64展示
    关于c# hashtable的一个注意点
    js image to base64 摘录
    linq to sql 获取sql与参数添加到日志中
    时钟的实现
    无限级菜单的实现
  • 原文地址:https://www.cnblogs.com/shercy/p/6489621.html
Copyright © 2020-2023  润新知