C++ Объясните мне peb

Эксперт
Эксперт
Статус
Оффлайн
Регистрация
29 Мар 2021
Сообщения
1,626
Реакции
625
при гулянии по PEB, могу ли я имея dllbase каждого загруженного модуля попросту сделать:
C++:
Expand Collapse Copy
auto parsed_pe_module = pe::module(dllbase, size);
? по адресу dllbase лежит дос хедер, отсюда и вопрос - лежит ли там весь PE файл.
 
при гулянии по PEB, могу ли я имея dllbase каждого загруженного модуля попросту сделать:
C++:
Expand Collapse Copy
auto parsed_pe_module = pe::module(dllbase, size);
? по адресу dllbase лежит дос хедер, отсюда и вопрос - лежит ли там весь PE файл.

Не совсем понятен вопрос. У тебя в peb лежит указатель на peb_ldr_data_t где и хранятся все модули, внутри ldr_data_table_entry лежит dllbase.

Ты можешь и не имея изначально базового адреса модуля, получить его.По поводу если лежит дос хедер, там лежит весь pe файл ( в контексте peb->peb_ldr_data_t->ldr_data_table_entry ) , в любом другом случае никто не мешает оставить хедер, just for fun.

Очень плохо сформулировал вопрос, внеси коррективы.

По крайней мере я потерялся :seemsgood:
 
Последнее редактирование:
могу ли я гуляя по пебу получить "копии" всех загружаемых модулей?

Да, конечно.



C++:
Expand Collapse Copy
{
    auto peb = peb( );

    if ( !peb ) return;

    if ( !peb->Ldr->InMemoryOrderModuleList.Flink ) return;

    auto* list = &peb->Ldr->InMemoryOrderModuleList;

    for ( auto i = list->Flink; i != list; i = i->Flink )
    {
        auto entry = CONTAINING_RECORD( i,  LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks );

        // entry на этом этапе это LDR_DATA_TABLE_ENTRY
    }
}


// сама структура

struct LDR_DATA_TABLE_ENTRY_T
{
    LIST_ENTRY_T InLoadOrderLinks;
    LIST_ENTRY_T InMemoryOrderLinks;
    LIST_ENTRY_T InInitializationOrderLinks;
    const char*  DllBase;
    const char*  EntryPoint;
    union {
        unsigned long SizeOfImage;
        const char*   _dummy;
    };
    UNICODE_STRING_T FullDllName;
    UNICODE_STRING_T BaseDllName;
};

// структура указатель на которую хранится в peb'e

struct PEB_LDR_DATA
{
        uint32_t        Length;
        uint8_t            Initialized;
        uintptr_t        SsHandle;
        LIST_ENTRY        InLoadOrderModuleList;
        LIST_ENTRY        InMemoryOrderModuleList;
        LIST_ENTRY        InInitializationOrderModuleList;
        uintptr_t        EntryInProgress;
        uint8_t            ShutdownInProgress;
        uintptr_t        ShutdownThreadId;
};


//

struct LIST_ENTRY_T
{
    const char* Flink;
    const char* Blink;
};


UPD: На этапе где у тебя entry имеется, ты имеешь всю информацию про модуль, дальше делай с ним че хочешь )
 
Последнее редактирование:
Да, конечно.



C++:
Expand Collapse Copy
{
    auto peb = peb( );

    if ( !peb ) return;

    if ( !peb->Ldr->InMemoryOrderModuleList.Flink ) return;

    auto* list = &peb->Ldr->InMemoryOrderModuleList;

    for ( auto i = list->Flink; i != list; i = i->Flink )
    {
        auto entry = CONTAINING_RECORD( i, native::LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks );

        // entry на этом этапе это LDR_DATA_TABLE_ENTRY
    }
}


// сама структура

struct LDR_DATA_TABLE_ENTRY_T
{
    LIST_ENTRY_T InLoadOrderLinks;
    LIST_ENTRY_T InMemoryOrderLinks;
    LIST_ENTRY_T InInitializationOrderLinks;
    const char*  DllBase;
    const char*  EntryPoint;
    union {
        unsigned long SizeOfImage;
        const char*   _dummy;
    };
    UNICODE_STRING_T FullDllName;
    UNICODE_STRING_T BaseDllName;
};

// структура указатель на которую хранится в peb'e

struct PEB_LDR_DATA_T
{
    unsigned long Length;
    unsigned long Initialized;
    const char*   SsHandle;
    LIST_ENTRY_T  InLoadOrderModuleList; // двусвязный список ( ниже прилагается )
};


//

struct LIST_ENTRY_T
{
    const char* Flink;
    const char* Blink;
};
под копией я подразумевал сам бинарь, но навряд ли в пебе будет лежать "this program cannot be run in dos mode" со всеми другими приколами на каждый загруженный модуль, так что вопрос закрыт, пожалуй.

думаю можно имея FullDllName заресолвленный виндой загрузить файл в память при желании используя std::filesystem если очень уж хочется
 
под копией я подразумевал сам бинарь, но навряд ли в пебе будет лежать "this program cannot be run in dos mode" со всеми другими приколами на каждый загруженный модуль, так что вопрос закрыт, пожалуй.

думаю можно имея FullDllName заресолвленный виндой загрузить файл в память при желании используя std::filesystem если очень уж хочется


Что значит в пебе лежать? В пебе у тебя всего лишь информация про загруженные модули, ты можешь получить базовый адрес модуля ( dllbase ) , этот же dllbase является указателем на начало памяти в котором хранятся все хедеры. Как итог ты можешь получить всё что хочешь.
 
ты можешь получить базовый адрес модуля ( dllbase ) , этот же dllbase является указателем на начало памяти в котором хранятся все хедеры.

Код:
Expand Collapse Copy
const auto dos_stub = (const char*)(entry->BaseAddress + 0x40); // baseaddr + dos stub offset

не должно же работать, верно?
 
Код:
Expand Collapse Copy
const auto dos_stub = (const char*)(entry->BaseAddress + 0x40); // baseaddr + dos stub offset

не должно же работать, верно?

Очень даже должно и будет.



1709110265117.png

1709110312265.png
 

У тебя виндовый лоадер который грузит модули априори не может грузить без хедера, соответсвенно любой модуль загруженный виндовым лоадером будет иметь фулл хедер, а дальше по шаблону -> dllbase + оффсеты = получаешь нужный хедер
 
Код:
Expand Collapse Copy
const auto dos_stub = (const char*)(entry->BaseAddress + 0x40); // baseaddr + dos stub offset

не должно же работать, верно?
C++:
Expand Collapse Copy
    uint64_t get_module_handle( const wchar_t* module_name, size_t* size ) {
        auto peb = reinterpret_cast< nt::peb* >( __readgsqword( 0x60 ) );
        auto head = peb->Ldr->InMemoryOrderModuleList;

        for ( auto current = head; current.Flink != &peb->Ldr->InMemoryOrderModuleList; current = *current.Flink ) {
            auto entry = reinterpret_cast< nt::ldr_data_table_entry* >( contains_record( current.Flink, nt::ldr_data_table_entry, InMemoryOrderLinks ) );

            if ( entry->BaseDllName.Buffer ) {
                if ( module_name != reinterpret_cast< const wchar_t* >( 0 ) ) {
                    if ( crt::wcsicmp_insensitive( entry->BaseDllName.Buffer, module_name ) ) {
                        *size = entry->SizeOfImage;
                        return reinterpret_cast< uint64_t >( entry->DllBase );
                    }
                }
                else {
                    *size = entry->SizeOfImage;
                    return reinterpret_cast< uint64_t >( entry->DllBase );
                }
            }
        }

        return 0;
    }
дальше просто rpm зная базу и сайз, лол
 
Назад
Сверху Снизу