Как получить доступ к заголовкам PE NT из заголовков DOS?

#c #binaryfiles #portable-executable

#c #двоичные файлы #портативный-исполняемый

Вопрос:

Я пытаюсь прочитать файл .exe PE в память и получить доступ к заголовкам NT. Я уже могу получить доступ к заголовкам DOS, но не могу разрешить заголовки NT из него.

Вот что у меня есть до сих пор:

 static constexpr uint16_t DOS_HDR_MAGIC =           0x5A4D;            // "MZ"
static constexpr uint32_t NT_HDR_MAGIC =            0x00004550;        // "PEx0x0"

struct nt_headers_t
{
    uint32_t                    signature;
    file_header_t               file_header;
    optional_header_x64_t       optional_header;
};

struct dos_header_t
{
    uint16_t                    e_magic;
    uint16_t                    e_cblp;
    uint16_t                    e_cp;
    uint16_t                    e_crlc;
    uint16_t                    e_cparhdr;
    uint16_t                    e_minalloc;
    uint16_t                    e_maxalloc;
    uint16_t                    e_ss;
    uint16_t                    e_sp;
    uint16_t                    e_csum;
    uint16_t                    e_ip;
    uint16_t                    e_cs;
    uint16_t                    e_lfarlc;
    uint16_t                    e_ovno;
    uint16_t                    e_res[ 4 ];
    uint16_t                    e_oemid;
    uint16_t                    e_oeminfo;
    uint16_t                    e_res2[ 10 ];
    uint32_t                    e_lfanew;
};

int main(void) {
    std::ifstream input("./stuff.exe", std::ios::in | std::ios::binary );
    input.seekg(0, std::ios::end);
    int file_size = input.tellg();
    input.seekg(0, std::ios::beg);
    std::byte *file = new std::byte[file_size];
    input.read((char *)file, file_size);

    struct dos_header_t *dos_header = (struct dos_header_t *)file;

    assert(dos_header->e_magic == DOS_HDR_MAGIC);

    struct nt_headers_t *nt_headers = (struct nt_headers_t *)file   dos_header->e_lfanew;

    assert(nt_headers->signature == NT_HDR_MAGIC);
}
 

структура

e_lfanew должен содержать адрес начала заголовков NT. Я просто добавляю это значение в начало файла: (struct nt_headers_t *)file dos_header->e_lfanew;

Я делаю это неправильно? Прикрепленное изображение говорит, что e_lfanew содержит смещение заголовков NT в обратном порядке. Как я должен это изменить?

Ответ №1:

Я просто добавляю это значение в начало файла: (struct nt_headers_t *)file dos_header->e_lfanew; я делаю это неправильно?

Да, но по «скучной причине», которая не имеет ничего общего с заголовками PE: поскольку вы выполнили приведение перед добавлением, смещение масштабируется на размер nt_headers_t . Смещение должно быть добавлено без изменения масштаба, поэтому сначала добавьте его, а затем приведите.

На прикрепленном изображении указано, что e_lfanew содержит смещение заголовков NT в обратном порядке. Как я должен это изменить?

Он находится в порядке байтов младшего порядка, вы, вероятно, запускаете код на компьютере младшего порядка (это большинство из них в настоящее время), поэтому вам ничего не нужно делать, просто прочитав значение, вы его правильно интерпретируете.