首先,一个PE文件必须包含的部分就是程序代码部分,data部分,导入导出表部分等。也就是一个程序之所以被称为程序的核心。为了方便管理,window将属性相同的数据放在一起。这些属性相同的内容就被称作section,翻译成节。很多个节就形成节区。
但这样就有一个问题,程序到底如何执行,在哪里找代码,在哪里找数据呢。于是必须对节和节中内容进行描述。
首先是对节区中的节的描述,放在IMAGE_SECTION_HEADER结构中,所有的这种结构就构成了节表。节表描述了相应节的属性和位置等信息。
除了对节的表述,由于程序的数据是按其属性放在不同的节中的,不同用途但属性相同的数据(如导入表,导出表以及.const段指定的只读数据)可能被放在同一个节中,那如何找到这些节中的某电脑一种用途的数据呢。就需要再进行表述。结构IMAGE_DATA_DIRECTORY就是用来进行这种描述的。再PE文件中共有16个这种结构。
除了对节和节中内容数据进行描述。也需要对形成的这个文件进行描述,以及如何找到上述的结构体的位置。首先,需要定义一个文件头,用来标识文件的开始。字符’PE’0 0就用于作为文件开头,这也就是PE文件这种称呼的来历。接着是对这个文件的描述,包括一个IMAGE_FILE_HEADER和IMAGE_OPTIONAL_HEADER32,这两者没有什么本质区别。虽然后者叫optional,但其实是必不可少的。而上面提到的IMAGE_DATA_DIRECTORY就放在了 IMAGE_OPTIONAL_HEADER32了。
最后为了兼容dos系统,又加入了dos部分的内容。
请结合下表学习上面的内容。
我们上面是用逻辑分析出了PE文件的设计思路。我们下面一一分析一些这些结构以及这些结构中重要的字段。
首先是dos部分的结构体。其中最重要的是e_lfanew字段,它指向了PE文件头的位置。
接下来是PE文件部分。包括三部分,前面提到了。
文件标识
IMAGE_FILE_HEADER
IMAGE_OPTIONAL_HEADER32
IMAGE_FILE_HEADER中的重要字段有
Machine运行平台
Numberofsection节的数量
SizeofOptionalHeader 也就是后面那个部分的大小
characteristics 一些重要属性。
IMAGE_OPTIONAL_HEADER32中的重要字段,包括
AddressEntryPoint 文件被执行时的入口地址,可以理解为main函数的地址。
imagebase 文件执行时优先装入内存的地址。
SectionAlignment字段指定了节被装入内存后的对齐单位
FileAlignment字段指定了节储存在磁盘文件中的对齐地址。
然后是16个IMAGE_DATA_DIRECTORY结构了,每个结构包括相应用途的数据的RVA地址,VirtualAddress字段,和其长度,isize字段。(RVA地址后面讲)
接下来是节表中的结构IMAGE_SECTION_HEADER了。里面重要的字段有四个。
VisualSize,没有经过任何对齐处理前的实际大小
VisualAddress,在内存中的偏移电脑地址,也就是RVA
PointerToRawData,该节在磁盘文件中所处的位置
SizeofRawData,Visualsize经过FileAlignment后的大小
有个这四个字段,就可以将数据从磁盘正确的装在到内存中了。具体是把位置在3,大小为4的数据放在地址为2的内存地址中,然后按1提供的大小按SectionAlignment装入内存。
什么是RVA
RVA,relative virtual address,就是内存中的偏移量的意思。由于各种原因,文件在磁盘中的大小和在内存中的大小是不一样。这个RVA就是在内存中时距离PE文件开始的偏移地址。
接下来我们来梳理下,如何在PE文件中找到相应的数据。
首先是dos头指向pe头,pe头固定偏移地址上是IMAGE_DATA_DIRECTORY,找到相应的数据,按照其中的RVA就可以访问响应的数据了。
电脑