2011-12-28 5 views
3

Интересно, что лучше всего определить, где заканчивается часть MZ EXE-файла, и запускается прилагаемый расширенный исполняемый файл (может быть PE/LE/LX/NE/COFF и т. Д.).Определите, где заканчивается MZ exe, и начинается LE/LX/PE

Я нашел этот сайт: http://www.delorie.com/djgpp/doc/exe/, который пытается объяснить это, но я никогда не получаю ожидаемого результата. Я всегда получаю смещение за пределы фактического смещения начала PE или LX.

// LXInfo.cpp : Defines the entry point for the console application. 
// 

#include "stdafx.h" 

struct EXE { 
    unsigned short signature; /* == 0x5a4D */ 
    unsigned short bytes_in_last_block; 
    unsigned short blocks_in_file; 
    unsigned short num_relocs; 
    unsigned short header_paragraphs; 
    unsigned short min_extra_paragraphs; 
    unsigned short max_extra_paragraphs; 
    unsigned short ss; 
    unsigned short sp; 
    unsigned short checksum; 
    unsigned short ip; 
    unsigned short cs; 
    unsigned short reloc_table_offset; 
    unsigned short overlay_number; 
}; 

struct EXE_RELOC { 
    unsigned short offset; 
    unsigned short segment; 
}; 


int _tmain(int argc, _TCHAR* argv[]) 
{ 
    struct EXE header1; 
    char sFile[]="c:\\register.dll"; 
    unsigned int extra_data_start; 
    char test; 
    FILE *fp; 
    fp = fopen(sFile, "rb"); 
    fread(&header1,sizeof(struct EXE),1,fp); 

    //read the header 
    printf("EXE Signature: %x \n", header1.signature); 
    printf("Bytes in last block: %08x \n", header1.bytes_in_last_block); 
    printf("Blocks in file: %08x \n", header1.blocks_in_file); 
    printf("Number of relocations: %08x \n", header1.num_relocs); 
    printf("Header paragraphs: %08x \n", header1.header_paragraphs); 
    printf("Min. extra paragraphs: %08x \n", header1.min_extra_paragraphs); 
    printf("Max. extra paragraphs: %08x \n", header1.max_extra_paragraphs); 
    printf("Initial SS value: %08x \n", header1.ss); 
    printf("Initial SP value: %08x \n", header1.sp); 
    printf("Checksum value: %08x \n", header1.checksum); 
    printf("Initial CS value: %08x \n", header1.cs); 
    printf("Initial IP value: %08x \n", header1.ip); 
    printf("Relocation table offset: %08x \n", header1.reloc_table_offset); 
    printf("Overlay number: %x \n", header1.overlay_number); 
    printf("\n"); 
    printf("Start of EXE data: %08x \n", header1.header_paragraphs * 16L); 

    //calculate end of MZ EXE, according to Delorie 
    extra_data_start = header1.blocks_in_file * 512L; 
    if (header1.bytes_in_last_block) 
     extra_data_start -= (512 - header1.bytes_in_last_block); 

    printf("End of EXE data: %08x \n", extra_data_start); 

    // let's read the first two bytes after the MZ EXE data. This should give us a P and E on windows, or L and X on OS/2... 
    fseek(fp,extra_data_start,SEEK_SET); 
    fread(&test,1,1,fp); 
    printf("test char: %c \n", test); 
    fread(&test,1,1,fp); 
    printf("test char: %c \n", test); 

    fclose(fp); 
    getch(); 
    return 0; 
} 

ответ

3

Прочитайте следующую статью: An In-Depth Look into the Win32 Portable Executable File Format.
Вы также должны прочитать на The Portable Executable File Format

Например, чтобы получить смещение из IMAGE_NT_HEADERS вы могли бы сделать так:

IMAGE_DOS_HEADER* pdos = (IMAGE_DOS_HEADER*)peBuffer; 
IMAGE_NT_HEADERS* pnt = (IMAGE_NT_HEADERS*)((DWORD)pdos + pdos->e_lfanew); 
+0

Спасибо, кажется, есть e_lfanew поле, которое определяет смещение PE исполняемый файл. Знаете ли вы, когда это поле было введено в спецификацию MZ? Будет ли это работать для исполняемых файлов OS/2 LX и исполняемых файлов LE DOS4GW? –

+0

@JeroenJacobs - Я не уверен в этом, но чтобы добраться до 'IMAGE_NT_HEADERS', я бы сделал что-то вроде: IMAGE_DOS_HEADER * pdos = (IMAGE_DOS_HEADER *) peBuffer; IMAGE_NT_HEADERS * pnt = (IMAGE_NT_HEADERS *) ((DWORD) pdos + pdos-> e_lfanew); ', вы также можете проверить следующую ссылку: http://www.csn.ul.ie/~caolan/pub/winresdump/ winresdump/док/pefile.html – Cyclonecode