Jirairya

与PE有关的基本概念

2017-03-27

与PE文件结构有关的几个概念

加载配置信息中的数据组织示意图.png

地址

PE文件涉及四类地址:

  • 虚拟内存地址(VA)
  • 相对虚拟内存地址(RVA)
  • 文件偏移地址(FOA)
  • 特殊地址

32位CPU的寻址能力为4GB(即2^32个字节),但有些机器的物理内存无法达到这个值。于是操作系统和CPU的内存管理单元共同作用,为用户提供了虚拟内存的管理机制。即分页机制。该机制让用户感觉自己在使用4GB的内存。

分页机制的基本原理:操作系统假设一个进程独立拥有4GB内存,按照某个固定的大小(如4KB)将这4GB分成N(1M)个页。在某一刻,所有这些页只有一部分和物理内存是对应的,没有物理内存对应的页面被标记为脏(dirty)的页面,一般存储在一个“交换文件”的磁盘文件中。在XP中,交换文件为pagefile.sys,它位于系统盘的根目录,是一个系统隐藏文件。当系统需要读取未在内存中的数据时,这部分数据会将内存中不经常读写的页交换出内存,而把要读取的、位于交换文件中的页换进内存。 通过这种“虚拟内存”的存取机制可以让一个进程拥有比实际内存大得多的内存。

虚拟内存地址(VA)

用户的PE文件被操作系统加载进内存后,PE对应的进程支配了自己独立的4GB虚拟空间。在这个空间中定位的虚拟地址称为虚拟内存地址(Virtual Address),所以虚拟内存地址的范围是00000000h~0ffffffffh。在PE进程的本身的VA被解释为:进程的基地址+相对虚拟内存地址

相对虚拟内存地址(RVA)

一个进程被操作系统加载到虚拟内存空间后,其相关的动态链接库也会被加载。这些同时加载到进程地址空间的文件称为模块。每一个模块 在加载时都会有一个基地址,也就是预先告诉操作系统:它会占用4GB空间的哪个部分(即从哪里开始存储该模块)。不同模块的基地址一般是不同的,若两个模块的基地址相同,就由操作系统来决定这两个模块在虚拟空间中的具体位置。 相对虚拟内存地址(Reverse Virtual Address,RVA)是相对于基地址的偏移,即RVA是虚拟内存中用来定位某个特定位置 的地址,该地址的值是这个特定位置距离某个模块基地址的偏移量,所以说RVA是针对某个模块而存在的。

内存地址示意图.png

假设模块2的基地址为0x01000000,而模块2中的某个位置距离模块2的基地址偏移为400h,那么值0x00000400就是模块2中某个位置的RVA,而值0x01000400是该位置的VA。RVA是相对于模块而言,VA是相对于整个空间而言。

文件偏移地址(FOA)

文件偏移地址(File Offset Address,FOA)和内存无关,它是指某个位置距离文件头的偏移 ###特殊地址 在PE结构中的一种特殊地址,计算方法并不是从文件头算起,也不是从内存的某个模块的基地址算起,而是从某个特定的位置算起。这种地址在PE结构中很少见,如在资源表里就出现过这样的地址。

指针

PE数据结构中的指针的定义:若数据结构中某个字段存储的值为一个地址,那么这个字段就是一个指针

数据目录

PE中有一个数据结构称为数据目录,其中记录了所有可能的数据类型。这些类型中,目前已定义的由15种,包括导入表、导出表、资源表、异常表、属性证书表、重定位表、调试数据、Architecture、Global Ptr、线程局部存储、加载配置表、绑定导入表、IAT、延迟导入表和CLR运行时头部

节就是存放不同类型数据(比如代码、数据 、常量、资源等)的地方,不同的节具有不同的访问权限。节是PE文件中存放代码或数据的基本单元。例如,一个目标文件中的所有代码可以组合成单个节,或者每个函数独占一个节(若编译器行为允许)。增加节的数目会增加文件开销,但是链接器在链接代码时会有更大的选择余地。一个节中的所有原始数据必须被加载到连续的内存空间中。

从操作系统加载的角度来看,节是相同属性数据的组合。与数据目录不同的是,尽管有些数据类型不同,分别属于不同的数据目录,但由于其访问属性相同,便被归类到同一个节中。这个节最终可能会占用一个或多个页面;但无论有多少个,所有相关页面均会被赋予相同的页属性。这些属性包括只读、只写、可读、可写等。

###对齐

有的对齐是为了美观,有的对齐则是为了效率。PE中规定了三类对齐:数据在内存中的对齐、数据在文件中的对齐、资源文件中资源数据的对齐。

内存对齐

由于Windows操作系统对内存属性的设置以页为单位,所以通常情况下,节在内存中的对齐单位必须至少是一个页的大小。对32位的XP系统来说,这个值是4KB(1000h),而对于64位操作系统来说,这个值就是8KB(2000h)

文件对齐

相对来说,节在磁盘文件中的对齐尺寸没有那么严格。为了提高磁盘利用率,通常情况下,定义的节在文件中的对齐单位要远小于内存对齐的单位;通常会以一个物理扇区的大小作为对齐粒度的值,即512字节,十六进制表示为200h。 出于节约资源的考虑,操作系统允许节在内存和文件中的对齐尺寸不一致。这就直接造成了PE在文件中和内存中的大小也会不一致。通常情况下,PE在内存中的尺寸要比在文件中的尺寸大。用户可以自己定为这些对齐的值。

资源数据对齐

资源文件中,资源字节码部分一般要求以双字(4个字节)方式对齐

###Unicode字符串

Unicode是继ASCII字符编码后的另一种新型字符编码。严格意义讲,ASCII码的每个字符使用7位表示,Unicode则使用全16位表示一个字符。Unicode字符串中的每个字符均为双字节,所以称为宽字符。

由于Unicode兼容ASCII字符,所以被大多数程序所支持,如Windows内核。Unicode的前128个字符码(十六进制,0x0000~0x007F)同ASCII具有同样的字节值。接下来的128个Unicode字符(代码为0x0080~0x00FF)是ISO 8859-1对ASCII码的扩展。 PE格式中涉及字符串的部分均用ANSI字符串(使用一个字节表示字符串的字符),然而在资源表中,对菜单名、对话框标题等的描述则全部使用Unicode字符串。所以在读取这些资源的字符串时,首先需要使用一些API函数实现从宽字符集到窄字符集的转换。

Unicode字符串不像ANSI字符串那样,保证用字符\0结束;如果开发者在程序设计时以字符\0作为Unicode字符串结尾的判断条件,就可能发生错误。


Similar Posts

上一篇 PE

下一篇 周结0

Comments