PE文件PE结构图PE文件结构简介1. DOS头1.1 MZ头1.2 DOS残留2. PE头2.1 PE标记2.2文件头2.3可选头3.3节表4 .节结构图PE详细信息1. DOS头2. PE头2 3可选标题3 .节表4 .节地址文件偏移地址文件偏移基地址ImageBase虚拟地址VA相对于虚拟地址RVA PE文件从存储器RVA映射到文件偏移
参考
甲鱼PE详细系列
PE文件PE (可移植可执行体)是什么? 利用PE文件构造的可执行文件被称为PE文件,Win下面包含exe、DLL、SYS、OCX等
PE结构图
PE文件结构概述1. DOS头部1.1 MZ头部MZ头部是真实的DOS头部,其前2个字节是MZ。 此部分用于在DOS系统上加载程序,其结构定义为IMAGES_DOS_HEADER
1.2 DOS提供了一个简单的程序,主要用于输出' thisprogramcannotberunindosmode.'的提示字符串
2. PE表头2.1 PE标识宏: IMAGE_NT_SIGNATRUE
2.2文件头结构: IMAGE_FILE_HEADER
2.3可选磁头结构: IMAGE_OPTIONAL_HEADER
三.节表和节
程序的组织存储在每个属性的不同部分中,每个部分由一个IMAGE_SECTION_HEADER表示。 如果PE文件包含n个节,则节表是由n个IMAGE_SECTION_HEADER结构和表示结束的空IMAGE_SECTION_HEADER结构组成的数组。
空结构不计入节数pimagentheaders-file header.number of sections中
“节”表包含各节的属性、文件位置和内存位置等信息,并且是节的索引。
4 .子句实际上是同一属性数据的组合,一个子句可能有多种类型的数据,它们只是因为读写属性相同而被编入同一子句。 将节加载到内存中后,相同节对应的内存页将分配相同的页属性。 实际上,在Windows系统上,内存中各节的对齐单位必须至少为一页大小,因为内存属性的设置是按页进行的。 )小鳖温馨提示:对于32位操作系统,该值通常为4KB或1000H; 对于64位操作系统,此值通常为8KB或2000H。)
结构关系图的源
PE详查1. DOS头的DOS头用于加载DOS残留,其中的一个字段中存储了向PE头的位置
在这个结构体中
e_magic:2B,DOS可执行文件的标识符
此标识符在winnt.h中有宏定义
# define images _ dos _ signature0x 5a 4d
由于系统以小字节序方式保存,因此实际保存时的前两个字节为4D 5A
e_lfanew:2B,PE头的开始位置
偏移将保存在0x0000003C的位置
那个值是0x0110
2. PE头
2.1查看PE标记0x00000110的位置
Signature:4B,值为0x00004550,即PE
2.2文件头PE标记后的20字节是文件头,主要描述与文件有关的信息
结构_IMAGE_FILE_HEADER的定义:
Machine:2B,可执行文件的目标处理器类型
图中的0x8664示出了x64处理器
NumberOfSections:2B,节数
图中0x0008表示有8个节区
TimeDataStamp:4B,从1970年到创建文件之间的秒数
SizeOfOptionHeader:2B,可选的头大小。 图中为0x00f 0,10进制数为240字节
Characteristics:2B,文件类型。 图中为0x0022
2.3可选的标题选项标题主要用于管理在将PE文件加载到OS中时所需的信息。
注:可选标题之所以称为可选标题,是因为数据目录数组中可以有也可以没有数据目录条目,但此标题必须存在。
从文件头的SizeOfOptionHeader中发现,选项头的大小为240字节,紧跟在文件头之后。 文件头的结束位置为0x00000127时,选项头的地址范围为0x00000128 ~0x00000217
结构的定义如下:
SizeOfCode:4B,所有代码节的大小之和。 图中为0x001c6400
AddressOfEntryPoint :
数据目录:
例如,导入表RVA:8000H、大小: 1964
从PE文件中读取所需的块(部分)时,块名称不能作为定位依据。 将数据目录中的虚拟地址
标准,因为区块名没有任何意义。 3. 节表紧挨在可选头之后,由文件头标识有8个节区
一个IMAGE_SECTION_HEADER大小为40字节,图中从0x00000218开始,下图为第一个节区对应的节表
ISH结构体定义如下:
Name:8B,多余的自动截断。图中为
VirtualSize:该区块的数据没有进行对齐处理前的实际大小。
VirtualAddress:装入内存中的RVA地址,按内存页对齐,因此其数值是OptionalHeader->SectionAlignment的整数倍
如内存分页大小为4096B
两个节的RVA分别为4096和12288
一个区块(节)中的数据仅仅只是由于属性相同而放在一起,并不一定是同一种用途的内容。如输入表、输出表等就有可能和只读常量一起被放在同一个区块中,因为他们的属性都是可读不可写的
几种地址 文件偏移地址FileOffsetPE文件中某处相对于文件头的地址
基地址ImageBase内存中PE文件的头地址
虚拟地址VA内存中某处相对于基地址的位置
相对虚拟地址RVA内存中某一虚拟地址相对于基地址的偏移量
PE文件映射到内存注意:块与块之间有空隙,因为要对齐
映射与装载的区别:
PE文件在磁盘上和内存上的结构是一致的,略有不同的是,在磁盘上PE文件是按照可选头的FileAlignment值对齐的,在内存中,PE文件是按可选头的SectionAlignment值对齐的。
FA的最小值是512B,Win32下的SA值一般为4096B
如果PE文件的SA值和FA值相等,则其磁盘文件结构与内存映像的结构是完全一样的。如果不相等,则略有差异。
当知道某数据的RVA,想要在文件中读取同样的数据时,就要将RVA转换为FileOffset,反之同理。
如:
观察输入表
RVA:6000H
ImageBase:40000H
SectionAlignment:1000H
FileAlignment:200H
内容:
接下来进行RVA到FileOffset的转换:
总体的思路是:
.text节的RVA范围是:VisualOffset 到 VisualOffset + RawDataSize
即:1000H到2788H
.data节的RVA范围是:3000H到3030H
…
.idata节的RVA范围是6000H到659EH输入表的RVA为6000H,属于.idata节。输入表的RVA相对于.idata节的偏移量为6000H - 6000H = 0.idata节的ROffset (2400H)即此节的文件偏移地址用2400H + 0H 即得到导入表的FileOffset 2400H
使用C32ASM查看其文件偏移地址为2400H的内容,一致