Search code examples
cwinapiportable-executable

PEB (Process Environment Block) invalid DllBase address


I trying to get my own PEB and get my own module address. i wrote a simple code like this:

PLIST_ENTRY myModule = (PLIST_ENTRY)pebLdr->InMemoryOrderModuleList.Flink;

PLDR_DATA_TABLE_ENTRY myImageBase = (PLDR_DATA_TABLE_ENTRY)myModule;

PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)myImageBase->DllBase;

But i dont see a proper PE header in dosHeader. This is what i see in the MSVC debugger in dosHeader variable : e_magic=???,e_cblp=??? . Why cant i get my own header? I checked everything, im doing everything as documented, and i can see my exe name in a pData->FullDllName, everything seem to be correct, and the DllBase makes sense its not null or anything like ffffff. Is there any specific thing need to bee done, maybe address calculation?


Solution

  • You can't do

    PLDR_DATA_TABLE_ENTRY myImageBase = (PLDR_DATA_TABLE_ENTRY)myModule;
    

    since InMemoryOrderLinks is not the first field in LDR_DATA_TABLE_ENTRY. Instead you should involve CONTAINING_RECORD() macro:

    PLIST_ENTRY le = (PLIST_ENTRY)pebLdr->InMemoryOrderModuleList.Flink;
    PLDR_DATA_TABLE_ENTRY mainModule = CONTAINING_RECORD(le, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
    PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)mainModule->DllBase;
    

    To top it off: you can freely iterate through doubly-linked circular list of LIST_ENTRY'es and to obtain actual node data you should use CONTAINING_RECORD(). Note, that node which resides in PEB_LDR_DATA is dedicated and has no associated data. You should use it only as sign that you have walked through whole list.