通过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 
... 
*/

  

posted @ 2017-03-02 11:23  SenberHu  阅读(365)  评论(0编辑  收藏  举报