PEB_LDR_DATA结构具有不同的成员和大小

时间:2017-08-29 05:39:10

标签: winapi

PEB结构包含进程信息,PEB_LDR_DATA结构的指针包含有关该进程的已加载模块的信息,是PEB成员之一。

从MSDN,PEB结构语法如下:

typedef struct _PEB {
    BYTE                          Reserved1[2];
    BYTE                          BeingDebugged;
    BYTE                          Reserved2[1];
    PVOID                         Reserved3[2];
    PPEB_LDR_DATA                 Ldr;                 <-- I'm curious about this one.
    PRTL_USER_PROCESS_PARAMETERS  ProcessParameters;
    BYTE                          Reserved4[104];
    PVOID                         Reserved5[52];
    PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
    BYTE                          Reserved6[128];
    PVOID                         Reserved7[1];
    ULONG                         SessionId;
} PEB, *PPEB;

在搜索结构后,我发现有各种各样的形式,它们让我感到困惑:

// Form #1: this is described in MSDN
typedef struct _PEB_LDR_DATA {    // 28 bytes
    BYTE       Reserved1[8];
    PVOID      Reserved2[3];
    LIST_ENTRY InMemoryOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;

// Form #2
typedef struct _PEB_LDR_DATA {    // 40 bytes
    DWORD      dwLength;
    DWORD      dwInitialized;
    LPVOID     lpSsHandle;
    LIST_ENTRY InLoadOrderModuleList;
    LIST_ENTRY InMemoryOrderModuleList;
    LIST_ENTRY InInitializationOrderModuleList;
    LPVOID     lpEntryInProgress;
} PEB_LDR_DATA, *PPEB_LDR_DATA;

// Form #3
typedef struct _PEB_LDR_DATA {    // 36 bytes
    ULONG      Length;
    BOOLEAN    Initialized;
    PVOID      SsHandle;
    LIST_ENTRY InLoadOrderModuleList;
    LIST_ENTRY InMemoryOrderModuleList;
    LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;

他们怎么会有不同的会员和规模?

1 个答案:

答案 0 :(得分:1)

这些基本上是内部未记录的数据结构,可以在版本甚至Service Pack之间进行更改。在开始时,只有TEB / TIB的前几个字段是semi-documented,因为编译器使用它们来实现SEH和TLS。

随着时间的推移,人们想出了其他一些领域,并开始使用它们,这实际上迫使微软记录它们。所有其他成员都保留了名称,因为Microsoft不希望您使用它们,因为可能存在已记录的API,或者将来可能会更改。

在32位Windows 8上,PEB_LDR_DATA结构如下所示:

0x000 Length           : Uint4B
0x004 Initialized      : UChar
0x008 SsHandle         : Ptr32 Void
0x00c InLoadOrderModuleList : _LIST_ENTRY
0x014 InMemoryOrderModuleList : _LIST_ENTRY
0x01c InInitializationOrderModuleList : _LIST_ENTRY
0x024 EntryInProgress  : Ptr32 Void
0x028 ShutdownInProgress : UChar
0x02c ShutdownThreadId : Ptr32 Void

符号并非始终100%正确,但在处理这些类型的结构时,它通常是最佳来源。这与您发布的结构的内存布局相匹配(表单#2除了错误地为BOOLEAN使用DWORD)。在检查长度成员(或Windows版本)之后,必须访问LIST_ENTRY之外的任何内容,因为它们在旧版本中不存在。

大小可能不同,因为随着时间的推移添加了新字段。成员可以是不同的,因为该字段实际上随着时间的推移而变化,但更可能是一个错误,因为有人只是为字段使用了不同的名称/类型。

如果您的目标是列出已加载的模块,那么您可以使用记录在案的ToolHelp API而不是......