PE文件格式学习与总结(待续)

一个有效的PE文件,总是以一个DOS头结构开始的。
这个DOS头结构就是IMAGE_DOS_HEADER,具体定义见winnt.h文件,这里给复制了过来,如下:


typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
    WORD   e_magic;                     // Magic number
    WORD   e_cblp;                      // Bytes on last page of file
    WORD   e_cp;                        // Pages in file
    WORD   e_crlc;                      // Relocations
    WORD   e_cparhdr;                   // Size of header in paragraphs
    WORD   e_minalloc;                  // Minimum extra paragraphs needed
    WORD   e_maxalloc;                  // Maximum extra paragraphs needed
    WORD   e_ss;                        // Initial (relative) SS value
    WORD   e_sp;                        // Initial SP value
    WORD   e_csum;                      // Checksum
    WORD   e_ip;                        // Initial IP value
    WORD   e_cs;                        // Initial (relative) CS value
    WORD   e_lfarlc;                    // File address of relocation table
    WORD   e_ovno;                      // Overlay number
    WORD   e_res[4];                    // Reserved words
    WORD   e_oemid;                     // OEM identifier (for e_oeminfo)
    WORD   e_oeminfo;                   // OEM information; e_oemid specific
    WORD   e_res2[10];                  // Reserved words
    LONG   e_lfanew;                    // File address of new exe header
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

对于有效的PE程序而言,其有效也是必须设置的2个成员就是(首尾):
1、WORD   e_magic;
  DOS可执行文件的标记,其值是固定的0x5A4D,即字符“MZ”,
2、 LONG   e_lfanew;
  这个成员指定了IMAGE_NT_HEADERS结构的位置,其重要性也就不言而喻了!

注:[color=#FF0000]Microsoft文档中曾说过,如果MS-DOS首部的偏移地址0x18处的值为0x40或者更大,则表明该程序为Win32程序,且领衔地址0x3C处的值为Windows首部的偏移量,即下面即将说到的IMAGE_NT_HEADERS结构的偏移![/color]

我写一个简单的16位程序-Hello.exe(见附件),大家可以比较一下:

但实际上,这一点完全可以忽略过去,并非必要。
同样的,IMAGE_NT_HEADERS结构也是定义在winnt.h文件中的,其他实际的格式有两种:
IMAGES_NT_HEADERS32和IMAGE_NT_HEADERS64


typedef struct _IMAGE_NT_HEADERS64 {
    DWORD Signature;
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;

typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

当然,这些不用我们操心,我们在调用时,只需要用IMAGES_NT_HEADERS就OK了,通过条件编译会自行指定:


#ifdef _WIN64
  typedef IMAGE_OPTIONAL_HEADER64             IMAGE_OPTIONAL_HEADER;
  typedef PIMAGE_OPTIONAL_HEADER64            PIMAGE_OPTIONAL_HEADER;
#else
  typedef IMAGE_OPTIONAL_HEADER32             IMAGE_OPTIONAL_HEADER;
  typedef PIMAGE_OPTIONAL_HEADER32            PIMAGE_OPTIONAL_HEADER;
#endif

待续……

hello.rar

发表评论