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

Эксперт
Статус
Оффлайн
Регистрация
29 Мар 2021
Сообщения
1,605
Реакции[?]
607
Поинты[?]
48K
при гулянии по PEB, могу ли я имея dllbase каждого загруженного модуля попросту сделать:
C++:
auto parsed_pe_module = pe::module(dllbase, size);
? по адресу dllbase лежит дос хедер, отсюда и вопрос - лежит ли там весь PE файл.
 
Участник
Статус
Оффлайн
Регистрация
23 Апр 2022
Сообщения
695
Реакции[?]
326
Поинты[?]
12K
при гулянии по PEB, могу ли я имея dllbase каждого загруженного модуля попросту сделать:
C++:
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:
 
Последнее редактирование:
Участник
Статус
Оффлайн
Регистрация
23 Апр 2022
Сообщения
695
Реакции[?]
326
Поинты[?]
12K
могу ли я гуляя по пебу получить "копии" всех загружаемых модулей?
Да, конечно.



C++:
{
    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 имеется, ты имеешь всю информацию про модуль, дальше делай с ним че хочешь )
 
Последнее редактирование:
Эксперт
Статус
Оффлайн
Регистрация
29 Мар 2021
Сообщения
1,605
Реакции[?]
607
Поинты[?]
48K
Да, конечно.



C++:
{
    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 если очень уж хочется
 
Участник
Статус
Оффлайн
Регистрация
23 Апр 2022
Сообщения
695
Реакции[?]
326
Поинты[?]
12K
под копией я подразумевал сам бинарь, но навряд ли в пебе будет лежать "this program cannot be run in dos mode" со всеми другими приколами на каждый загруженный модуль, так что вопрос закрыт, пожалуй.

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

Что значит в пебе лежать? В пебе у тебя всего лишь информация про загруженные модули, ты можешь получить базовый адрес модуля ( dllbase ) , этот же dllbase является указателем на начало памяти в котором хранятся все хедеры. Как итог ты можешь получить всё что хочешь.
 
Эксперт
Статус
Оффлайн
Регистрация
29 Мар 2021
Сообщения
1,605
Реакции[?]
607
Поинты[?]
48K
ты можешь получить базовый адрес модуля ( dllbase ) , этот же dllbase является указателем на начало памяти в котором хранятся все хедеры.
Код:
const auto dos_stub = (const char*)(entry->BaseAddress + 0x40); // baseaddr + dos stub offset
не должно же работать, верно?
 
Участник
Статус
Оффлайн
Регистрация
23 Апр 2022
Сообщения
695
Реакции[?]
326
Поинты[?]
12K
Участник
Статус
Оффлайн
Регистрация
23 Апр 2022
Сообщения
695
Реакции[?]
326
Поинты[?]
12K
У тебя виндовый лоадер который грузит модули априори не может грузить без хедера, соответсвенно любой модуль загруженный виндовым лоадером будет иметь фулл хедер, а дальше по шаблону -> dllbase + оффсеты = получаешь нужный хедер
 
Пользователь
Статус
Оффлайн
Регистрация
25 Окт 2023
Сообщения
76
Реакции[?]
28
Поинты[?]
25K
Код:
const auto dos_stub = (const char*)(entry->BaseAddress + 0x40); // baseaddr + dos stub offset
не должно же работать, верно?
C++:
    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 зная базу и сайз, лол
 
Сверху Снизу