• Windows PE/COFF


    Windows PE/COFF

    Windows的二进制文件格式PE/COFF

    在32位Windows平台下,微软引入了一种叫PE(Portable Executable)的可执行格式。作为Win32平台的标准可执行文件格式,PE有着跟ELF一样良好的平台扩展性和灵活性。PE文件格式事实上与ELF同根同源,他们都是由COFF(Common Object File Format)格式发展而来的,更加具体地讲是来源于当时著名的DEC(Digital Equipment Corporation)的VAX/VMS上的COFF文件格式。因为当微软开始开发Windows NT的时候,最初的成员都是来自于DEC公司的VAX/VMS小组,所以他们很自然就将原来系统上熟悉的工具和文件格式都搬了过来,并且在此基础上做重新设计和改动。

    请注意,上面在讲到PE文件格式的时候,只是说Windows平台下的可执行文件采用该格式。事实上,在Windows平台,VISUAL C++编译器产生的目标文件仍然使用COFF格式。由于PE是COFF的一种扩展,所以它们的结构在很大程度上相同,甚至跟ELF文件的基本结构也相同,都是基于段的结构。所以我们下面在讨论Windows平台上的文件结构时,目标文件默认为COFF格式,而可执行文件为PE格式。但很多时候我们可以将它们统称为PE/COFF文件。

    随着64位Windows的发布,微软对64位Windows平台上的PE文件结构稍微做了一些修改,这个新的文件格式叫做PE32+。新的PE32+并没有添加任何结构,最大的变化就是把那些原来32位的字段变成了64位,比如文件头中与地址相关的字段。

    PE的前身——COFF

    COFF文件结构

    几乎跟ELF文件一样,COFF也是由文件头及后面的若干个段组成,再加上文件末尾的符号表、调试信息的内容就构成了COFF文件的基本结构,我们在COFF文件中几乎都可以找到与ELF文件结构相对应的地方。COFF文件的文件头部包括了两部分,一个是描述文件总体结构和属性的映像头(Image Header),另外一个是描述该文件中包含的段属性的段表(Section Table)。文件头后面紧跟着的就是文件的段,包括代码段、数据段等,最后还有符号表等。

    // 文件头
    typedef struct _IMAGE_FILE_HEADER {
        WORD Machine;
        WORD NumberOfSections;
        DWORD TimeDateStamp;
        DWORD PointerToSymbolTable;
        DWORD NumberOfSymbols;
        WORD SizeOfOptionalHeader;
        WORD Characteristics;
    } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
    
    // 段头
    typedef struct _IMAGE_SECTION_HEADER {
        BYTE Name[8];
        union {
            DWORD PhysicalAddress;
        	DWORD VirtualSize;
        } Misc;
        DWORD VirtualAddress;
        DWORD SizeOfRawData;
        DWORD PointerToRawData;
        DWORD PointerToRelocations;
        DWORD PointerToLinenumbers;
        WORD NumberOfRelocations;
        WORD NumberOfLinenumbers;
        DWORD Characteristics;
    } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
    

    链接指示信息

    ".drectve"段的内容是编译器传递给链接器的指令(Derective),即编译器希望告诉链接器应该怎样链接这个目标文件。段名后面就是段的属性,包括地址、长度、位置等,最后一个属性是标志位“flags”,即IMAGE_SECTION_HEADER里面的Characteristics成员。".drectve"段的标志位为“0x100A00”,它是表中的标志位的组合。

    标志位 宏定义 意义
    0x00100000 IMAGE_SCN_ALIGN_1BYTES 1个字节对齐。相当于不对齐
    0x00000800 IMAGE_SCN_LNK_REMOVE 最终链接成映像文件时抛弃该段
    0x00000200 IMAGE_SCN_LNK_INFO 该段包含的是注释或其他信息

    调试信息

    COFF文件中所有以“.debug”开始的段都包含着调试信息。比如".debug(S"表示包含的是符号相关的调试信息段;".debug)P"表示包含的是预编译头文件相关的调试信息段;".debug$T"表示包含的是类型相关的调试信息段。调试信息段的具体格式被定义在PE格式文件标准中。

    大家都有符号表

    最后部分是COFF符号表,内容几乎跟ELF文件的符号表一样,主要就是符号名、符号的类型、所在的位置。

    Windows下的ELF——PE

    PE文件是基于COFF的扩展,它比COFF文件多 几个结构。最主要的变化有两个:第一个是文件最开始的部分不是COFF文件头,而是DOS MZ 可执行文件格式的文件头和桩代码(DOS MZ File Header and Stub);第二个变化是原来的COFF文件头中的“IMAGE_FILE_HEADER”部分扩展成了PE文件文件头结构,这个结构包括了原来的“Image Header”及新增的PE扩展头部结构(PE Optional Header)

    DOS下的可执行文件的扩展名与Windows下的可执行文件扩展名一样,都是“.exe”,但是DOS下的可执行文件格式是“MZ”格式,与Windows下的PE格式完全不同,虽然它们使用相同的扩展名。在Windows发展的早期,那时候DOS系统还如日中天,而且早期的Windows版本还不能脱离DOS环境独立运行,所以为了照顾DOS系统,那些为Windows编写的程序必须尽量兼容原有的DOS系统,所以PE文件在设计之初就背负着历史的累赘。PE文件中“Image DOS Header”和“DOS Stub”这两个结构就是为了兼容DOS系统而设计的,其中“Image DOS Header”结构跟DOS的“MZ”可执行结构的头部完全一样,其结构中有前两个字节是e_magic结构,它是里面包含了MZ两个字母的ASCII码;e_cs和e_ip两个成员指向程序的入口地址。然而PE文件中这两个成员却是指向“DOS Stub”,它是一段可以在DOS下运行的一小段代码,向终端输出一行字:“This program cannot be run in DOS”。

    // PE真正的文件头
    typedef struct _IMAGE_NT_HEADERS {
        DWORD Signature; // 标记,对应"PE"的ASCII码
        IMAGE_FILE_HEADER FileHeader;
        IMAGE_OPTIONAL_HEADER OptionalHeader; //很多成员,有些部分跟PE文件的装载与运行相关
    } IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;
    
    
    

    PE数据目录

    在Windows系统装载PE可执行文件时,往往需要很快的找到一些装载所需要的数据结构,比如导入表、导出表、资源、重定位表等。这些常用的数据的位置和长度都被保存在了一个叫数据目录(Data Directory)的结构里面,其实它就是前面“IMAGE_OPTIONAL_HEADER”结构里面的DataDirectory成员。

    typedef struct _IMAGE_DATA_DIRECTORY {
        DWORD VirtualAddress;
        DWORD Size;
    } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
    
    #define IMAGE_DATA_DIRECTORY_ENTRIES 16
    
  • 相关阅读:
    Python 模块 itertools
    Python 字符串的encode与decode
    python 模块 hashlib(提供多个不同的加密算法)
    暴力尝试安卓gesture.key
    hdu 1300 Pearls(DP)
    hdu 1232 畅通工程(并查集)
    hdu 1856 More is better(并查集)
    hdu 1198 Farm Irrigation(并查集)
    hdu 3635 Dragon Balls(并查集)
    hdu 3038 How Many Answers Are Wrong(并查集)
  • 原文地址:https://www.cnblogs.com/fr-ruiyang/p/10877330.html
Copyright © 2020-2023  润新知