PE文件结构基础(28)
1.PE文件结构简介
PE 文件就是windows下可执行文件的总称,常见的有:DLL,EXE,OCX,SYS。
Windows 是如何区分可执行文件的呢?也许你会说文件扩展名,但我要告诉你,这是错误的。因为这个是涉及到PE结构的。
DOS头是用来兼容MS-DOS操作系统的,目标一般是用来指明NT头在文件中的位置
NT头包含windows PE文件的主要信息,其中包括一个‘PE’字样的签名,PE文件头【IMAGE_FILE_HEADER】和PE可选头【IMAGE_OPTIONAL_HEADER32】,头部的详细结构以及其具有意义在PE文件头文章中详细描述
节表是PE文件后续节的描述,windows根据节表的描述加载每个节
节每个节实际上是一个容器,可以包含代码,数据…每个节可以有独立的内存权限,比如代码节默认有读/执行权限,节的名字和数量是可以自己定义的【不一定就是上图中的三个】
当一个PE文件被加载到内存中以后,就称之“映像【image】”,一般来说,PE文件在硬盘上和内存是不完全一样的,被加载到内存以后占用的虚拟地址空间要比硬盘上占用的空间大一些,这是因为:各个节在硬盘上是连续的,但是在内存中是按照耶对齐的,所以加载到内存以后节之间会出现一些“空洞”
因为存在这种对齐,所以在PE结构内部,表示某个位置的地址采用了两种方式:
1.针对在硬盘上存储文件中的地址,称为原始存储地址或者物理地址表示距离文件头的偏移;
2.另外一种是针对加载到内存以后映像中的地址,称为相对虚拟地址【RVA】,表示相对内存映像头的偏移
然而CPU的某些指令是需要使用绝对地址的,比如取全局变量的地址,传递函数的地址 编译以后的汇编指令中肯定需要用到绝对地址而不是相对映像头的偏移,因此PE文件会建议操作系统将其加载到某个内存地址【这个叫基地址】,编译器便根据这个地址求出代码中一些全局变量和函数的地址,并将这些地址用到对应的指令中。
可执行文件头
DOS头和NT头就是PE文件中两个重要的文件头。
一、DOS头
主要是兼容,对于32位PE文件来说,DOS所起的作用就是显示一行文字,提示用户:我需要在32位windows上才可以运行。我认为这是个善意的玩笑,因为他并不像显示的那样不能运行,其实已经运行了,只是在DOS上没有干用户希望看到的工作而已,好吧,我承认这不是重点。但是,至少我们看一下这个头是如何定义的:
1 | typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header |
需要关注的就2个地方
- e_magic:一个WORD类型,值是一个常数0x4D5A,用文本编辑器查看该值位‘MZ’,可执行文件必须都
是’MZ’开头
- e_lfanew:为32位可执行文件扩展的域,用来表示DOS头之后的NT头相对文件起始地址的偏移。
二.NT头
顺着 e_lfanew 很容易就能找到NT头,这个才是32位PE文件中最有用的头
1 | typedef struct _IMAGE_NT_HEADERS { |
我们可以通过010里面的模块来分析文件,
2.PE字段简介
用PEtools 这个工具
贼多嘞,后面在学吧 《windows PE 权威指南》
3.PE节表
节表位置的计算:DOS头大小+标准PE头大小+标准PE头SizeofoftimHeader的值
FileBuffer 是从硬盘读到内存的缓存
ImageBuffer(映像或镜像)是把内存中的FileBuffer拉伸后的结果
节表 VirtualAddress 属性的意思
真实代码的大小,包括为初始化数据的大小,例如 char a[100] ,a数组没有初始化数据,但是还是要算100字节大小,
节表****SizeOfRawData 属性的意思
节表 PointerToRawData****属性
Characteristics 节的属性
1 | 标志(属性块) 常用特征值对照表: |