PE文件格式详解(4)

2016-02-19 20:23 2 1 收藏

下面图老师小编跟大家分享一个简单易学的PE文件格式详解(4)教程,get新技能是需要行动的,喜欢的朋友赶紧收藏起来学习下吧!

【 tulaoshi.com - 编程语言 】

  PE文件段 !-- frame contents -- !-- /frame contents --   PE文件规范由目前为止定义的那些头部以及一个名为“段”的一般对象组成。段包含了文件的内容,包括代码、数据、资源以及其它可执行信息,每个段都有一个头部和一个实体(原始数据)。我将在下面描述段头部的有关信息,但是段实体则缺少一个严格的文件结构。因此,它们几乎可以被链接器按任何的方法组织,只要它的头部填充了足够能够解释数据的信息。   段头部   PE文件格式中,所有的段头部位于可选头部之后。每个段头部为40个字节长,并且没有任何的填充信息。段头部被定义为以下的结构:
  
    WINNT.H
    #define IMAGE_SIZEOF_SHORT_NAME 8
    typedef strUCt _IMAGE_SECTION_HEADER {
    UCHAR Name[IMAGE_SIZEOF_SHORT_NAME];
    union {
      ULONG PhysicalAddress;
      ULONG VirtualSize;
    } Misc;
    ULONG VirtualAddress;
    ULONG SizeOfRawData;
    ULONG PointerToRawData;
    ULONG PointerToRelocations;
    ULONG PointerToLinenumbers;
    USHORT NumberOfRelocations;
    USHORT NumberOfLinenumbers;
    ULONG Characteristics;
    } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
  
  你如何才能获得一个特定段的段头部信息?既然段头部是被连续的组织起来的,而且没有一个特定的顺序,那么段头部必须由名称来定位。以下的函数示范了如何从一个给定了段名称的PE映像文件中获得一个段头部:
  
    PEFILE.C
    BOOL WINAPI GetSectionHdrByName(LPVOID lpFile,
      IMAGE_SECTION_HEADER *sh, char *szSection)
    {
    PIMAGE_SECTION_HEADER psh;
    int nSections = NumOfSections (lpFile);
    int i;
    if ((psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET(lpFile))
        != NULL)
      {
      /* 由名称查找段 */
      for (i = 0; i nSections; i++)
      {
        if (!strcmp(psh-Name, szSection))
        {
   !-- frame contents -- !-- /frame contents --         /* 向头部复制数据 */
          CopyMemory((LPVOID)sh, (LPVOID)psh,
              sizeof(IMAGE_SECTION_HEADER));
          return TRUE;
        }
        else
          psh++;
  
       }
    }
    return FALSE;
    }
  
  这个函数通过SECHDROFFSET宏将第一个段头部定位,然后它开始在所有段中循环,并将要寻找的段名称和每个段的名称相比较,直到找到了正确的那一个为止。当找到了段的时候,函数将内存映像文件的数据复制到传入函数的结构中,然后IMAGE_SECTION_HEADER结构的各域就能够被直接存取了。     段头部的域   ·Name。每个段都有一个8字符长的名称域,并且第一个字符必须是一个句点。
  ·PhysicalAddress或VirtualSize。第二个域是一个union域,现在已不使用了。
  
  ·VirtualAddress。这个域标识了进程地址空间中要装载这个段的虚拟地址。实际的地址由将这个域的值加上可选头部结构中的ImageBase虚拟地址得到。切记,假如这个映像文件是一个DLL,那么这个DLL就不一定会装载到ImageBase要求的位置。所以一旦这个文件被装载进入了一个进程,实际的ImageBase值应该通过使用GetModuleHandle来检验。
  
  ·SizeOfRawData。这个域表示了相对FileAlignment的段实体尺寸。文件中实际的段实体尺寸将少于或等于FileAlignment的整倍数。一旦映像被装载进入了一个进程的地址空间,段实体的尺寸将会变得少于或等于FileAlignment的整倍数。
  ·PointerToRawData。这是一个文件中段实体位置的偏移量。
  
  ·PointerToRelocations、PointerToLinenumbers、NumberOfRelocations、NumberOfLinenumbers。这些域在PE格式中不使用。
  
  ·Characteristics。定义了段的特征。这些值可以在WINNT.H及本光盘(译注:MSDN的光盘)的PE格式规范中找到。
  定义0x00000020代码段0x00000040已初始化数据段0x00000080未初始化数据段0x04000000该段数据不能被缓存0x08000000该段不能被分页0x10000000共享段0x20000000可执行段0x40000000可读段0x80000000可写段  定位数据目录  数据目录存在于它们相应的数据段中。典型地来说,数据目录是段实体中的第一个结构,但不是必需的。由于这个缘故,假如你需要定位一个指定的数据目录的话,就需要从段头部和可选头部中获得信息。
  
  为了让这个过程简单一点,我编写了以下的函数来定位任何一个在WINNT.H之中定义的数据目录。
  
    PEFILE.C
    LPVOID WINAPI ImageDirectoryOffset(LPVOID lpFile,
      DWord dwIMAGE_DIRECTORY)
    {
    PIMAGE_OPTIONAL_HEADER poh;
    PIMAGE_SECTION_HEADER psh;
    int nSections = NumOfSections(lpFile);
    int i = 0;
    LPVOID VAImageDir;
    /* 必须为0到(NumberOfRvaAndSizes-1)之间 */
    if (dwIMAGE_DIRECTORY = poh-NumberOfRvaAndSizes)
      return NULL;
    /* 获得可选头部和段头部的偏移量 */
    poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET(lpFile);
    psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET(lpFile);
    /* 定位映像目录的相对虚拟地址 */
    VAImageDir = (LPVOID)poh-DataDirectory
   !-- frame contents -- !-- /frame contents --       [dwIMAGE_DIRECTORY].VirtualAddress;
    /* 定位包含映像目录的段 */
    while (i++ nSections)
    {
      if (psh-VirtualAddress = (DWORD)VAImageDir &&
          psh-VirtualAddress +
  
           psh-SizeOfRawData (DWORD)VAImageDir)
        break;
      psh++;
    }
    if (i nSections)
      return NULL;
    /* 返回映像导入目录的偏移量 */
    return (LPVOID)(((int)lpFile +
        (int)VAImageDir. psh-VirtualAddress) +
        (int)psh-PointerToRawData);
    }
  
  该函数首先确认被请求的数据目录入口数字,然后它分别获取指向可选头部和第一个段头部的两个指针。它从可选头部决定数据目录的虚拟地址,然后它使用这个值来决定数据目录定位在哪个段实体之中。假如适当的段实体已经被标识了,那么数据目录特定的位置就可以通过将它的相对虚拟地址转换为文件中地址的方法来找到。(未完待续)

来源:https://www.tulaoshi.com/n/20160219/1623518.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的图标文件格式的一种,可以存储单个图案、多尺寸、多色板的图标文件。图标是具有明确指代含义的计算机图形。其中桌面图标是软件标识,界面中的图标是功能标识。图标有一套标准的大小和属性格式,且通常是小尺寸的。每个图标都含有多张相同显示内容的图片,每一张图片具有不同的尺寸和发色数。一个图标就是一套...

经验教程

374

收藏

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