【旧文章搬运】从PEB获取内存中模块列表

原文发表于百度空间,2008-7-25
==========================================================================

PEB中的Ldr部分包含有当前进程所加载的模块信息.
lkd> dt _peb
ntdll!_PEB
   +0x000 InheritedAddressSpace : UChar
   +0x001 ReadImageFileExecOptions : UChar
   +0x002 BeingDebugged    : UChar
   +0x003 SpareBool        : UChar
   +0x004 Mutant           : Ptr32 Void
   +0x008 ImageBaseAddress : Ptr32 Void
   +0x00c Ldr              : Ptr32 _PEB_LDR_DATA
.....
其结构定义如下:

typedef struct _PEB_LDR_DATA
{
ULONG Length;
BOOLEAN Initialized;
PVOID SsHandle; 
LIST_ENTRY InLoadOrderModuleList; //按加载顺序
LIST_ENTRY InMemoryOrderModuleList; //按内存顺序
LIST_ENTRY InInitializationOrderModuleList; //按初始化顺序
} PEB_LDR_DATA,*PPEB_LDR_DATA;

另一个重要结构就是存储每个模块信息的LDR_MODULE部分,其定义如下:

typedef struct _LDR_MODULE
{
LIST_ENTRY          InLoadOrderModuleList;
LIST_ENTRY          InMemoryOrderModuleList; 
LIST_ENTRY          InInitializationOrderModuleList; 
void*               BaseAddress; 
void*               EntryPoint;   
ULONG               SizeOfImage;
UNICODE_STRING      FullDllName;
UNICODE_STRING      BaseDllName;
ULONG               Flags;
SHORT               LoadCount;
SHORT               TlsIndex;
HANDLE              SectionHandle;
ULONG               CheckSum;
ULONG               TimeDateStamp;
} LDR_MODULE, *PLDR_MODULE;

这两者的关系呢,引用别人的两张图来说明一下吧,看了图应该一目了然.

第二张图太大了,放个缩略图吧.
结构搞清楚之后,要遍历就很简单了,主要就是遍历一个双向环状链表.

PEB_LDR_DATA *pPEBLDR;
LDR_MODULE *pLdrMod;
LIST_ENTRY *pListEntry,*pStart;
void *p,*BaseAddress,*FullDllName;
_asm
{
   mov eax,fs:[0x30] //TEB->PEB
   mov eax,[eax+0xC] //PEB->Ldr
   mov pPEBLDR,eax
}
printf("PEB_LDR_DATA:0x%08x
",pPEBLDR);
printf("LDR->Length:0x%08x
",pPEBLDR->Length);
printf("LDR->InLoadOrderModuleList:		0x%08x
",pPEBLDR->InLoadOrderModuleList);
printf("LDR->InMemoryOrderModuleList:		0x%08x
",pPEBLDR->InMemoryOrderModuleList);
printf("LDR->InInitializationOrderModuleList:	0x%08x
",pPEBLDR->InInitializationOrderModuleList);
//遍历双链表
pListEntry=(LIST_ENTRY*)(PUCHAR)&(pPEBLDR->InLoadOrderModuleList);
pStart=pListEntry;
printf("BaseAddress		FullDllName
====================================
");
do 
{
   pListEntry=pListEntry->Flink;
   pLdrMod=(LDR_MODULE*)pListEntry;
   printf("0x%08x		",pLdrMod->BaseAddress);
   wprintf(L"%s
",pLdrMod->FullDllName.Buffer);
  
} while(pListEntry!=pStart);

效果图:

原文地址:https://www.cnblogs.com/achillis/p/10179607.html