PE文件格式详解(3)

2016-02-19 20:19 37 1 收藏

想要天天向上,就要懂得享受学习。图老师为大家推荐PE文件格式详解(3),精彩的内容需要你们用心的阅读。还在等什么快点来看看吧!

【 tulaoshi.com - 编程语言 】

PE可选头部  PE可执行文件中接下来的224个字节组成了PE可选头部。虽然它的名字是“可选头部”,但是请确信:这个头部并非“可选”,而是“必需”的。
  
    OPTHDROFFSET宏可以获得指向可选头部的指针:
   !-- frame contents -- !-- /frame contents --   PEFILE.H
    #define OPTHDROFFSET(a) ((LPVOID)((BYTE *)a +
                          ((PIMAGE_DOS_HEADER)a)-e_lfanew +
                          SIZE_OF_NT_SIGNATURE +
                          sizeof(IMAGE_FILE_HEADER)))
  可选头部包含了很多关于可执行映像的重要信息,例如初始的堆栈大小、程序入口点的位置、首选基地址、操作系统版本、段对齐的信息等等。
  
    IMAGE_OPTIONAL_HEADER结构如下:
    WINNT.H
    typedef strUCt _IMAGE_OPTIONAL_HEADER {
    //
    // 标准域
    //
    USHORT Magic;
    UCHAR MajorLinkerVersion;
    UCHAR MinorLinkerVersion;
    ULONG SizeOfCode;
    ULONG SizeOfInitializedData;
    ULONG SizeOfUninitializedData;
    ULONG AddressOfEntryPoint;
    ULONG BaseOfCode;
    ULONG BaseOfData;
    //
    // NT附加域
    //
    ULONG ImageBase;
    ULONG SectionAlignment;
    ULONG FileAlignment;
    USHORT MajorOperatingSystemVersion;
    USHORT MinorOperatingSystemVersion;
    USHORT MajorImageVersion;
    USHORT MinorImageVersion;
    USHORT MajorSubsystemVersion;
    USHORT MinorSubsystemVersion;
    ULONG Reserved1;
    ULONG SizeOfImage;
    ULONG SizeOfHeaders;
    ULONG CheckSum;
  
  
    USHORT Subsystem;
    USHORT DllCharacteristics;
    ULONG SizeOfStackReserve;
    ULONG SizeOfStackCommit;
    ULONG SizeOfHeapReserve;
    ULONG SizeOfHeapCommit;
    ULONG LoaderFlags;
   !-- frame contents -- !-- /frame contents --   ULONG NumberOfRvaAndSizes;
  
     IMAGE_DATA_DirectorY DataDirectory   [IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
    } IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
  
  如你所见,这个结构中所列出的域实在是冗长得过分。为了不让你对所有这些域感到厌烦,我会仅仅讨论有用的——就是说,对于探究PE文件格式而言有用的。  标准域  首先,请注重这个结构被划分为“标准域”和“NT附加域”。所谓标准域,就是和UNIX可执行文件的COFF格式所公共的部分。虽然标准域保留了COFF中定义的名字,但是Windows NT仍然将它们用作了不同的目的——尽管换个名字更好一些。
  
  ·Magic。我不知道这个域是干什么的,对于示例程序EXEVIEW.EXE示例程序而言,这个值是0x010B或267(译注:0x010B为.EXE,0x0107为ROM映像,这个信息我是从eXeScope上得来的)。
  
  ·MajorLinkerVersion、MinorLinkerVersion。表示链接此映像的链接器版本。随Window NT build 438配套的Windows NT SDK包含的链接器版本是2.39(十六进制为2.27)。
  
  ·SizeOfCode。可执行代码尺寸。
  ·SizeOfInitializedData。已初始化的数据尺寸。
  ·SizeOfUninitializedData。未初始化的数据尺寸。
  ·AddressOfEntryPoint。在标准域中,AddressOfEntryPoint域是对PE文件格式来说最为有趣的了。这个域表示应用程序入口点的位置。并且,对于系统黑客来说,这个位置就是导入地址表(IAT)的末尾。以下的函数示范了如何从可选头部获得Windows NT可执行映像的入口点。
  
    PEFILE.C
    LPVOID WINAPI GetModuleEntryPoint(LPVOID lpFile)
    {
    PIMAGE_OPTIONAL_HEADER poh;
    poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET(lpFile);
    if (poh != NULL)
      return (LPVOID)poh-AddressOfEntryPoint;
    else
      return NULL;
    }
  ·BaseOfCode。已载入映像的代码(“.text”段)的相对偏移量。
  ·BaseOfData。已载入映像的未初始化数据(“.bss”段)的相对偏移量。   Windows NT附加域 !-- frame contents -- !-- /frame contents --   添加到Windows NT PE文件格式中的附加域为Windows NT特定的进程行为提供了装载器的支持,以下为这些域的概述。
  
  ·ImageBase。进程映像地址空间中的首选基地址。Windows NT的Microsoft Win32 SDK链接器将这个值默认设为0x00400000,但是你可以使用-BASE:linker开关改变这个值。
  
  ·SectionAlignment。从ImageBase开始,每个段都被相继的装入进程的地址空间中。SectionAlignment则规定了装载时段能够占据的最小空间数量——就是说,段是关于SectionAlignment对齐的。
  
  Windows NT虚拟内存治理器规定,段对齐不能少于页尺寸(当前的x86平台是4096字节),并且必须是成倍的页尺寸。4096字节是x86链接器的默认值,但是它可以通过-ALIGN: linker开关来设置。
  
  ·FileAlignment。映像文件首先装载的最小的信息块间隔。例如,链接器将一个段实体(段的原始数据)加零扩展为文件中最接近的FileAlignment边界。早先提及的2.39版链接器将映像文件以0x200字节的边界对齐,这个值可以被强制改为512到65535这么多。
  
  ·MajorOperatingSystemVersion。表示Windows NT操作系统的主版本号;通常对Windows NT 1.0而言,这个值被设为1。
  
  ·MinorOperatingSystemVersion。表示Windows NT操作系统的次版本号;通常对Windows NT 1.0而言,这个值被设为0。
  
  ·MajorImageVersion。用来表示应用程序的主版本号;对于Microsoft Excel 4.0而言,这个值是4。
  
  ·MinorImageVersion。用来表示应用程序的次版本号;对于Microsoft Excel 4.0而言,这个值是0。
  
  
  ·MajorSubsystemVersion。表示Windows NT Win32子系统的主版本号;通常对于Windows NT 3.10而言,这个值被设为3。
  
  ·MinorSubsystemVersion。表示Windows NT Win32子系统的次版本号;通常对于Windows NT 3.10而言,这个值被设为10。
  
  ·Reserved1。未知目的,通常不被系统使用,并被链接器设为0。
  
  ·SizeOfImage。表示载入的可执行映像的地址空间中要保留的地址空间大小,这个数字很大程度上受SectionAlignment的影响。   例如,考虑一个拥有固定页尺寸4096字节的系统,假如你有一个11个段的可执行文件,它的每个段都少于4096字节,并且关于65536字节边界对齐,那么SizeOfImage域将会被设为11 * 65536 = 720896(176页)。
  
   !-- frame contents -- !-- /frame contents --   而假如一个相同的文件关于4096字节对齐的话,那么SizeOfImage域的结果将是11 * 4096 = 45056(11页)。这只是个简单的例子,它说明每个段需要少于一个页面的内存。在现实中,链接器通过个别地计算每个段的方法来决定SizeOfImage确切的值。它首先决定每个段需要多少字节,并且最后将页面总数向上取整至最接近的SectionAlignment边界,然后总数就是每个段个别需求之和了。
  
  ·SizeOfHeaders。这个域表示文件中有多少空间用来保存所有的文件头部,包括MS-DOS头部、PE文件头部、PE可选头部以及PE段头部。文件中所有的段实体就开始于这个位置。
  
  ·CheckSum。校验和是用来在装载时验证可执行文件的,它是由链接器设置并检验的。由于创建这些校验和的算法是私有信息,所以在此不进行讨论。
  
  ·Subsystem。用于标识该可执行文件目标子系统的域。每个可能的子系统取值列于WINNT.H的IMAGE_OPTIONAL_HEADER结构之后。
  
  ·DllCharacteristics。用来表示一个DLL映像是否为进程和线程的初始化及终止包含入口点的标记。
  
  ·SizeOfStackReserve、SizeOfStackCommit、SizeOfHeapReserve、SizeOfHeapCommit。这些域控制要保留的地址空间数量,并且负责栈和默认堆的申请。在默认情况下,栈和堆都拥有1个页面的申请值以及16个页面的保留值。这些值可以使用链接器开关-STACKSIZE:与-HEAPSIZE:来设置。
  
  ·LoaderFlags。告知装载器是否在装载时中止和调试,或者默认地正常运行。
  
  ·NumberOfRvaAndSizes。这个域标识了接下来的DataDirectory数组。请注重它被用来标识这个数组,而不是数组中的各个入口数字,这一点非常重要。
  
  ·DataDirectory。数据目录表示文件中其它可执行信息重要组成部分的位置。它事实上就是一个IMAGE_DATA_DIRECTORY结构的数组,位于可选头部结构的末尾。当前的PE文件格式定义了16种可能的数据目录,这之中的11种现在在使用中。   数据目录  WINNT.H之中所定义的数据目录为:
  
    WINNT.H
    // 目录入口
    // 导出目录
    #define IMAGE_DIRECTORY_ENTRY_EXPORT 0
    // 导入目录
   !-- frame contents -- !-- /frame contents --   #define IMAGE_DIRECTORY_ENTRY_IMPORT 1
    // 资源目录
    #define IMAGE_DIRECTORY_ENTRY_RESOURCE 2
    // 异常目录
    #define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
    // 安全目录
    #define IMAGE_DIRECTORY_ENTRY_SECURITY 4
    // 重定位基本表
    #define IMAGE_DIRECTORY_ENTRY_BASERELOC 5
    // 调试目录
    #define IMAGE_DIRECTORY_ENTRY_DEBUG 6
  
     // 描述字串
    #define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7
    // 机器值(MIPS GP)
    #define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8
    // TLS目录
    #define IMAGE_DIRECTORY_ENTRY_TLS 9
    // 载入配置目录
    #define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
  
  基本上,每个数据目录都是一个被定义为IMAGE_DATA_DIRECTORY的结构。虽然数据目录入口本身是相同的,但是每个特定的目录种类却是完全唯一的。每个数据目录的定义在本文的以后部分被描述为“预定义段”。
  
    WINNT.H
    typedef struct _IMAGE_DATA_DIRECTORY {
    ULONG VirtualAddress;
    ULONG Size;
    } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
  
  每个数据目录入口指定了该目录的尺寸和相对虚拟地址。假如你要定义一个特定的目录的话,就需要从可选头部中的数据目录数组中决定相对的地址,然后使用虚拟地址来决定该目录位于哪个段中。一旦你决定了哪个段包含了该目录,该段的段头部就会被用于查找数据目录的精确文件偏移量位置。
  
  所以要获得一个数据目录的话,那么首先你需要了解段的概念。我在下面会对其进行描述,这个讨论之后还有一个有关如何定位数据目录的示例。(未完待续)

来源:https://www.tulaoshi.com/n/20160219/1623365.html

延伸阅读
标签: 电脑入门
JPS即JPEG Stereo,是一种3d图像格式。JPS文件格式其实就是JPEG文件格式,只是它同时存储了左眼看到的图(在右边)及右眼看到的图(在左边)。 为形成立体视觉,左右差异不会很大。
标签: 电脑入门
CAJ全文浏览器是中国期刊网的专用全文格式阅读器,它支持中国期刊网的CAJ、NH、KDH和PDF格式文件。它可以在线阅读中国期刊网的原文,也可以阅读下载到本地硬盘的中国期刊网全文。它的打印效果可以达到与原版显示一致的程度。
标签: 电脑入门
XTF格式(eXtended Triton Format)用来存储多种类型的设备数据,包括声纳、导航、遥测及测深信息。这种数据格式保留了原有设备的数据格式,更方便将来数据的扩展。 XTF文件由许多数据包组成,每个数据包前面都有关于数据类型和大小的说明。如果处理软件读取时,不需要或不能读取某个数据包,则根据数量大小直接跳过去即可。 所有XTF文件都是由...
标签: 电脑入门
PFL文件格式是一种视频动画文件格式。PFL格式文件可以通过MusicFriend软件来制作。它最高支持15帧/秒的视频采样。 PFL格式文件是PhotoFiltre studio(一款功能强大、容易上手的图像编辑软件)的插件文件,类似滤镜的特效,在滤镜菜单中可以找到。
标签: 电脑入门
ico是Icon file的缩写,是Windows的图标文件格式的一种,可以存储单个图案、多尺寸、多色板的图标文件。图标是具有明确指代含义的计算机图形。其中桌面图标是软件标识,界面中的图标是功能标识。图标有一套标准的大小和属性格式,且通常是小尺寸的。每个图标都含有多张相同显示内容的图片,每一张图片具有不同的尺寸和发色数。一个图标就是一套...

经验教程

493

收藏

91
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部