zoukankan      html  css  js  c++  java
  • PE文件结构

    由于一些原因,需要学习安全方面的一些知识,所以学习了PE文件的结构,这篇随笔是学习的一些心得,作为复习。希望对各位有所帮助,如果行文中有什么错误,还请各位指正。


    Microsoft Windows Portable Executable是微软可迁移可执行软件的全称,简称PE文件。对PE文件结构的学习虽然并不是程序员必须学的,但是学习对PE文件结构的学习过程中能够提升我们的个人编程能力,从中学到很多东西。而对PE文件的详细学习对我们在安全、病毒检测的工作有很大的帮助。

    PE 文件结构

    PE文件的结构如下表所示

      +-------------------+
      | DOS MZ header     |
      +-------------------+
      | DOS-stub          |
      +-------------------+
      | file-header       |
      +-------------------+
      | optional header   |
      |- - - - - - - - - -|
      |                   |
      | data directories  |
      |                   |
      +-------------------+
      |                   |
      | section headers   |
      |                   |
      +-------------------+
      |                   |
      | section 1         |
      |                   |
      +-------------------+
      |                   |
      | section 2         |
      |                   |
      +-------------------+
      |                   |
      | ...               |
      |                   |
      +-------------------+
      |                   |
      | section n         |
      |                   |
      +-------------------+
    

    DOS-header & DOS-stub

    所有的PE文件都是由一个简单DOS MZ header头开始,后面紧跟着一个DOS-stub。这么做的目的是为了向后兼容性。当全世界在从DOS到Win32转变时
    为了DOS的向后兼容性,引入了这两个区域在PE文件的开头。DOS MZ headerDOS-stub是用来兼容DOS运行环境的。当DOS看到这个头时,便知道这是一个可执行文件,接着DOS便会紧接着运行DOS-stub的内容,DOS-stub实际上就是一个EXE文件。在那个时候,有一些程序将DOS版本和Win32版本整合到一个PE文件中,具体的做法就是在DOS-stub中存放DOS版本的程序。现在的DOS-stub中的内容仅仅只是一句话 "This program cannot run in DOS mode",现在DOS-stub这个块的内容已经很少被关注。为并且有一些工作试图将DOS-stub块删除。下图显示的是分析rufus程序的DOS-headerDOS-stub截图

    其中在DOS-header的最后一个字给出了PE-header的偏移量(0x00000080)。根据这个就能够找到PE-header。即PE文件中最重要的部分。

    PE-header

    PE-header是PE文件中最重要的内容,PE-header中包含了PE加载程序需要的许多字段。PE-header实际上是一个名为IMAGE_NT_HEADERS的结构体。结构体的定义如下:

    IMAGE_NT_HEADERS STRUCT 
       Signature dd ? 
       FileHeader IMAGE_FILE_HEADER <> 
       OptionalHeader IMAGE_OPTIONAL_HEADER32 <> 
    IMAGE_NT_HEADERS ENDS
    

    字段:

    • Signature:PE-header的签名是一个魔数(0x00004550),转换成文本就是"PE"。该成员是PE签名,因此我们将使用它来验证给定文件是否是有效的PE文件。
    • FileHeader:FileHeader包含的是PE的物理布局信息(physical layout)例如Section的数量,PE文件所针对的机器等。
    • OptionalHeader:虽然说这个头部是可选的(Optional),但是在所有的PE文件中都有出现。

    微软定义了几个常量用来作为MZ头和PE头的签名,其中IMAGE_DOS_SIGNATURE是DOS头签名,IMAGE_NT_SIGNATURE是PE头签名
    IMAGE_DOS_SIGNATURE equ 5A4Dh
    IMAGE_OS2_SIGNATURE equ 454Eh
    IMAGE_OS2_SIGNATURE_LE equ 454Ch
    IMAGE_VXD_SIGNATURE equ 454Ch
    IMAGE_NT_SIGNATURE equ 4550h

    所以,为了验证一个PE文件是否是有效的,只需要知道PE-header前两个字节是不是等于0x4550就能够知道是不是合法的PE文件。验证一个文件是不是合法的PE文件,步骤如下所示:

    1. 比较一个给定的文件是否有MZ头。
    2. 如果包含了MZ头,使用MZ头的e_lfanew成员,查找PE-header的位置,e_lfanew0x3C地址上。
    3. 将PE-header的第一第二个字节和IMAGE_NT_SIGNATURE进行对比,如果相等,则证明是有效的PE文件。

    FileHeader

    FileHeader是PE-header 中的一个结构体,虽然我们最感兴趣的部分在于OptionalHeader中,但是FileHeader也包含了一些重要的字段,对FileHeader的定义如下

    IMAGE_FILE_HEADER STRUCT 
        Machine WORD ? 
        NumberOfSections WORD ? 
        TimeDateStamp dd ? 
        PointerToSymbolTable dd ? 
        NumberOfSymbols dd ? 
        SizeOfOptionalHeader WORD ? 
        Characteristics WORD ? 
    IMAGE_FILE_HEADER ENDS
    

    下表将表示各个字段的意思

    字段名 意义
    Machine PE文件所针对的CPU平台。
    NumberOfSections PE文件中Section的数量
    TimeDateStamp PE文件创建的时间,基本没什么用
    PointerToSymbolTable DEBUG 用途
    NumberOfSymbols DEBUG 用途
    SizeOfOptionalHeader OptionalHeader的大小
    Characteristics 包含文件的标识,例如这个文件是dll还是exe

    Optional Header

    虽说Optional Header 名称中含有Optional字样,但是却是PE header中最大、最重要的一个部分。Optional HeaderIMAGE_NT_HEADERS结构体中的最后一个元素,包含了PE文件的逻辑内容。在OptionalHeader中有31个字段,其中某些字段对我们十分有用。在Optional Header中存储的位置,都是RVA。关于RVA的详细内容,参考这篇笔记
    下面列举在Optional Header中对我们比较有用的字段:

    字段名 意义
    AddressOfEntryPoint 这个字段存储的是PE文件加载到内存后第一个执行命令的RVA。如果想要从开始就改变PE文件的执行顺序,就可以修改这一个字段。
    ImageBase PE文件加载的首选的RVA。假如这个值是0x400000h那么PE-loader将在该虚拟地址没有被占用的情况下,将映像文件加载到0x400000h地址上。
    SizeOfImage PE映像在内存中的大小。

    还有其他的字段信息,可以查看这个教程

    Section Table

    Section Table是一个跟在PE header后的数组。该数组的长度由IMAGE_FILE_HEADER中的NumberOfSection决定。Section Table包含了这些有用的信息

    字段 意义
    Name1 实际上这个字段应该称为"name",但是由于"name"是MSAM关键字,所以这个字段就成为Name1。这个字段中包含的是Section的名称,并且最大的长度是8个字节。可以使用任何名称,甚至将这个字段留为空。
    VirtualAddress Section的RVA,所以如果这个字段的值是1000h,而PE文件中FileHeader中ImageBase字段是400000h的话,这个Section将会加载到内存为401000h的地址上。
    SizeOfRawData 见名知意
    PointerToRawData 见名知意
    Characteristics 包含了一些标志,这些标志说明了Section中是否包含可执行代码/初始化数据/未初始化数据,以及可读性。

    Import Table

    Import Table内容比较多,重新开一个笔记来记录

  • 相关阅读:
    安装VMtools vim编辑器的使用 压缩包命令 Linux下的用户管理 (第三天)
    VM虚拟机安装 常用Linux命令 网卡配置 (第二天)
    数据库的交互模式 常用的dos命令 (第一天)
    Validate US Telephone Numbers FreeCodeCamp
    Arguments Optional FreeCodeCamp
    Everything Be True FreeCodeCamp
    Binary Agents FreeCodeCamp
    Steamroller FreeCodeCamp
    Drop it FreeCodeCamp
    Smallest Common Multiple FreeCodeCamp
  • 原文地址:https://www.cnblogs.com/pluviophile/p/pe-file-structure.html
Copyright © 2011-2022 走看看