PE 文件格式 详解 一

内容引用自:看雪《逆向工程原理》,http://www.blogfshare.com/pe-header-one.html 。 如有错误,欢迎留言。

1、  PE文件是windows操作系统下使用的可执行文件格式。

  PE文件指的是32位的可执行文件。   64位的可执行文件成为PE+ 或者 PE32+。

2、  PE文件格式为  

  DOS头(DOS Header)  +  DOS存根(DOS Stub) + PE 头(PE Header)

    + 节表(区块表 section table) + 节(区块 sections)

  各个部分的定义其实都是一个结构体变量

    DOS Header 对应 IMAGE_DOS_HEADER

    PE Header 对应 IMAGE_NT_HEADER

3、  DOS Header 是由 IMAGE_DOS_HEADER 定义,DOS Header固定为40h个字节,

  其中e_magic 和 e_lfanew 是需要关注的,其他可忽略。

              typedef struct _IMAGE_DOS_HEADER {

      +00h WORD e_magic  // Magic DOS signature MZ(4Dh 5Ah)   DOS可执行文件标记 ,固定为 “MZ”

      +02h  WORD e_cblp   // Bytes on last page of file  

      +04h WORD e_cp   // Pages in file

      +06h WORD e_crlc   // Relocations

      +08h WORD e_cparhdr   // Size of header in paragraphs

      +0ah WORD e_minalloc   // Minimun extra paragraphs needs

      +0ch WORD e_maxalloc  // Maximun extra paragraphs needs

      +0eh WORD e_ss   // intial(relative)SS value   DOS代码的初始化堆栈SS 

      +10h WORD e_sp   // intial SP value   DOS代码的初始化堆栈指针SP 

      +12h WORD e_csum   // Checksum 

      +14h WORD e_ip   //  intial IP value   DOS代码的初始化指令入口[指针IP] 

      +16h WORD e_cs   // intial(relative)CS value   DOS代码的初始堆栈入口 CS

      +18h WORD e_lfarlc   // File Address of relocation table 

      +1ah WORD e_ovno  //  Overlay number 

      +1ch WORD e_res[4]  // Reserved words 

      +24h WORD e_oemid   //  OEM identifier(for e_oeminfo) 

      +26h WORD e_oeminfo  //  OEM information;e_oemid specific  

      +29h WORD e_res2[10]  //  Reserved words 

      +3ch LONG  e_lfanew  // Offset to start of PE header  

        指向PE文件头(IMAGE_NT_HEADER)的偏移地址,也就是真正PE文件头在文件中的位置。

    } IMAGE_DOS_HEADER

4、DOS Stub

   在DOS Header 下方,是可选项,大小不固定,即使没有DOS Stub ,文件也可以正常运行。

5、PE Header 由 IMAGE_NT_HEADER32 定义, IMAGE_NT_HEADER32 固定为 F8h个字节

    typedef struct _IMAGE_NT_HEADER {

      +0h DWORD Signature                    PE文件标识 , 固定为 50 45 00 00 (“PE00”)

      +4h   IMAGE_FILE_HEADER  FileHeader

      +18h IMAGE_OPTIONAL_HEADER32 OptionalHeader  

    } IMAGE_NT_HEADER32

 

    typedef  struct _IMAGE_FILE_HEADER {      # 固定大小为14h个字节

      +04h    WORD          Machine;   // 运行平台
      +06h      WORD          NumberOfSections; // 文件的区块数目
      +08h    DWORD         TimeDateStamp;  // 文件创建日期和时间
      +0Ch      DWORD       PointerToSymbolTable; // 指向符号表(主要用于调试)  

                COFF符号表的文件偏移位置 常为00 00 00 00
      +10h     DWORD         NumberOfSymbols;  // 符号表中符号个数(同上)  常为00 00 00 00
      +14h      WORD          SizeOfOptionalHeader;  // IMAGE_OPTIONAL_HEADER32 结构大小
      +16h      WORD          Characteristics;  // 文件属性

    } IMAGE_FILE_HEADER

    需要注意的点:

      Machine 定义可执行文件的目标CPU类型,常见的值如下:

      

      NumberOfSections 定义区块的数目

      TimeDateStamp 定义文件创建时间,自1970年1月1日以来计算的秒数

      SizeOfOptionalHeader 定义IMAGE_OPTION_HEADER32的大小,

          对于32位PE文件通常为 00 E0,64位 PE+文件 通常为00 F0

      Characteristics 定义文件的属性,以bit OR形式组合起来,各个位定义属性如下:

      

    typedef struct _IMAGE_DATA_DIRECTORY {

      DWORD VirtualAddress;

      DWORD Size;

    } IMAGE_DATA_DIRECTORY

    #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16

    typedef struct _IMAGE_OPTIONAL_HEADER {

      +18h    WORD    Magic;         // 标志字, ROM 映像(0107h),普通可执行文件(010Bh)
      +1Ah    BYTE      MajorLinkerVersion;     // 链接程序的主版本号
      +1Bh    BYTE      MinorLinkerVersion;     // 链接程序的次版本号
      +1Ch    DWORD   SizeOfCode;     // 所有含代码的节的总大小
      +20h    DWORD   SizeOfInitializedData;    // 所有含已初始化数据的节的总大小
      +24h    DWORD   SizeOfUninitializedData; // 所有含未初始化数据的节的大小
      +28h    DWORD   AddressOfEntryPoint;    // 程序执行入口RVA
      +2Ch    DWORD   BaseOfCode;      // 代码的区块的起始RVA
      +30h    DWORD   BaseOfData;      // 数据的区块的起始RVA
      +34h    DWORD   ImageBase;      // 程序的首选装载地址
      +38h    DWORD   SectionAlignment;      // 内存中的区块的对齐大小
      +3Ch    DWORD   FileAlignment;      // 文件中的区块的对齐大小
      +40h    WORD    MajorOperatingSystemVersion;  // 要求操作系统最低版本号的主版本号
      +42h    WORD    MinorOperatingSystemVersion;  // 要求操作系统最低版本号的副版本号
      +44h    WORD    MajorImageVersion;       // 可运行于操作系统的主版本号
      +46h    WORD    MinorImageVersion;       // 可运行于操作系统的次版本号
      +48h    WORD    MajorSubsystemVersion;  // 要求最低子系统版本的主版本号
      +4Ah    WORD    MinorSubsystemVersion;  // 要求最低子系统版本的次版本号
      +4Ch    DWORD   Win32VersionValue;       // 莫须有字段,不被病毒利用的话一般为0
      +50h    DWORD   SizeOfImage;       // 映像装入内存后的总尺寸
      +54h    DWORD   SizeOfHeaders;       // 所有头 + 区块表的尺寸大小
      +58h    DWORD   CheckSum;       // 映像的校检和
      +5Ch    WORD    Subsystem;       // 可执行文件期望的子系统
      +5Eh    WORD    DllCharacteristics;       // DllMain()函数何时被调用,默认为 0
      +60h    DWORD   SizeOfStackReserve;       // 初始化时的栈大小
      +64h    DWORD   SizeOfStackCommit;       // 初始化时实际提交的栈大小
      +68h    DWORD   SizeOfHeapReserve;        // 初始化时保留的堆大小
      +6Ch    DWORD   SizeOfHeapCommit;        // 初始化时实际提交的堆大小
      +70h    DWORD   LoaderFlags;        // 与调试有关,默认为 0 
      +74h    DWORD   NumberOfRvaAndSizes;  // 下边数据目录的项数,这个字段自Windows NT 发布以来一直是16
      +78h    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];  // 数据目录表

    } IMAGE_OPTIONAL_HEADER32

     需要注意的点:

      Magic 逆向工程核心原理此处有错误, 普通可执行文件的值为 01 0Bh

      AddressOfEntryPoint 指向入口地址  RVA地址

      ImageBase 指出文件的优先装入地址。 进程虚拟内存空间为0-FFFFFFFF(32位系统),

        EXE、DLL文件被装入内存的0-7FFFFFFF中,SYS文件被装入内存的80000000-FFFFFFFF中。

        对于EXE文件,由于每个文件都使用独立的虚拟地址空间,优先装入地址不会被占用,所以总是可以依照该地址装入,

        EXE文件也不需要重定位信息,一般EXE文件对应的该值为00400000h。

        DLL文件的优先装入地址可能被占用,因此DLL文件必须包含重定位信息,一般DLL文件对应的该值为10000000h

      SectionAlignment  指定了节被装入内存后的对齐单位

      FileAlignment    指定了节存储在磁盘文件中的对齐单位

      SizeOfImage 指定了 当PE文件被加载进内存后在虚拟内存占用的空间大小

      SizeOfHeader  指定了 所有头 + 区块表 的大小

      SubSystem  指定使用界面的子系统,  该字段决定系统如何为程序建立初始的界面,取值如下:

      

      NumberOfRvaAndSizes 指定 DataDirectory 数组长度   目前为止固定为 00 00 00 10h

      DataDirectory  最重要的字段之一,由16个IMAGE_DATA_DIRECTORY结构组成。

        虽然PE文件中的数据是按照装入内存后的页属性归类而被放在不同的节中的,但是这些

        处于各个节中的数据按照用途可以被分为导出表、导入表、资源、重定位表等数据块,

        这16个IMAGE_DATA_DIRECTORY结构就是用来定义多种不同用途的数据块的。

       数据目录列表(DataDirectory) 包含以下结构:  比较重要的是 导出表  导入表  资源表 重定位表 TLS Directory(thread local storage)

      

 

      

posted @ 2017-10-31 21:58  lwhat  阅读(582)  评论(0编辑  收藏  举报