PE文件及其结构

PE文件

1.什么叫PE文件

PE (Portable Executeable File Format,可移植的执行体文件格式),使用该格式的目的是使连接生成的EXE文件能在不同的CPU指令下工作。
Windows中可执行程序有很多种,COM,PIF,SCR,EXE等,这些文件的格式大部分都继承于PE。其中EXE是最常见的PE文件,动态链接库(大部分以dll为扩展名的文件)也是PE文件。

2.PE文件的结构

PE文件,我们可以将其理解为“头”+“身体”式结构

在这里插入图片描述
在了解PE文件格式之前,我们需要学习一下于PE文件相关的几个概念

  • 地址
  • 指针
  • 数据目录
  • 对齐

地址

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

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

相对虚拟内存地址:
一个进程被操作系统加载到虚拟内存空间后,相关的dll也会被加载,加载到内存空间的文件称为模块,每一格模块在加载时都会有一个基地址,也就是告诉操作系统,从哪里开始存储该模块。
RVA于具体的模块相关,它有一个范围,此范围从模块的开始到结束,脱离这个范围 RVA是无效无意义的,称为越界。
RVA是相对模块而言,VA是相对整个地址空间而言
在这里插入图片描述
文件偏移地址:
与文件有关与内存无关,指某个位置距离文件头的偏移

特殊地址:
从某个特定的位置开始算起的特殊情况

指针

与C语言中的指针定义类似

数据目录

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

节就是存放不同数据类型的地方,不同的节具有不同的访问限权,解释PE文件种存放代码或数据的基本单元。如汇编中的,.data .code伪指令。

对齐

  • 内存对齐
  • 文件对齐
  • 资源数据对齐

Unicode字符串

unicode 是继阿斯克码后的另一种新型字符编码,ASCII码每个字符用7位表示,Unicode则使用16位表示一个字符,所以又称为宽字符串

3. 32位系统的PE结构

在这里插入图片描述

3.1 DOS头

所有的PE文件都是以一个64字节的DOS头开始。这个DOS头只是为了兼容早期的DOS操作系统。

typedef struct IMAGE_DOS_HEADER{  
      WORD e_magic; 
      WORD e_cblp;  
      WORD e_cp;  
      WORD e_crlc;  
      WORD e_cparhdr;  
      WORD e_minalloc;  
      WORD e_maxalloc;  
      WORD e_ss;  
      WORD e_sp;  
      WORD e_csum;  
      WORD e_ip;  
      WORD e_cs;  
      WORD e_lfarlc;  
      WORD e_ovno;  
      WORD e_res[4];  
      WORD e_oemid;  
      WORD e_oeminfo;  
      WORD e_res2[10];  
      DWORD e_lfanew; 
}IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;  

DOS头共64个字节

  • e_magic:判断一个文件是不是PE文件
  • e_lfanew:相对与文件首的偏移量,常用于定位PE头位置

PE头的绝对位置定位:
PE_start = DOS MZ 基地址 + IMAGE_DOS_HEADER.e_lfanew。

PE文件头部=DOS头+PE头+节表
PE文件身体=节内容。

在这里插入图片描述

3.2 PE头

总的PE头:IMAGE_NT_HEADERS

这个结构是广义上的PE头,在标准的PE文件中,其大小为456个字节,是接下来三个小节提到的数据结构的组合
PE头的数据结构被定义为IMAGE_NT_HEADERS。包含三部分,其结构如下:

typedef struct IMAGE_NT_HEADERS{  
      DWORD Signature;  
      IMAGE_FILE_HEADER FileHeader;  
      IMAGE_OPTIONAL_HEADER32 OptionalHeader;  
}IMAGE_NT_HEADERS,*PIMAGE_NT_HEADERS;   

在这里插入图片描述

第一部分:PE头标识Signature

紧跟在DOS Stub之后,与大部分文件格式的头部结果一样,PE头部中有一个四字节的标识,该标识位于指针IMAGE_DOS_HEADER.e_lfanew指向的内同。其内容固定,对应于ASCII码的字符串“PE\0\0”。

第二部分:标准PE头IMAGE_FILE_HEADER

标准PE头,IMAGE_FILE_HEADER紧跟在PE头标识之后,记录了PE文件的全局属性,常用于判断此PE文件时exe类型还是dll类型

第三部分:扩展PE头,IMAGE_OPTIONAL_HEADER32

文件执行是的入口地址,文件被操作系统装入到内存后的默认基地址,以及节在磁盘和内存中的对齐单位等信息都可以在此结构中找到,其内容比标准PE头还要多,对于该结果中的某些数值的改动可能导致PE文件加载或运行失败

PE头中的数据目录项:IMAGE_DATA_DIRECTORY

该字段定义了PE文件中所有不同类型数据的目录信息

IMAGE_DATA_DIRECTORY STRUCT
	VirtualAddress DWORD ?;
	isize DWARD ?;
IMAGE_DATA_DIRECTOR ENDS

两个字段依次为VirtualAddress和isize
在这里插入图片描述

3.3 节表项IMAGE_SECTION_HEADER(块表)

PE头的IMAGE_NT_HEADER后紧跟着节表,有许多个节表项组成,节表项的数据结构详细如下,每个节的结构也是类似于“头”+“身体”结构,节表项就是“头”

IMAGE_SECTION_HEADER
	Name1 db IMAGE_SIZEOF_SHORT_NAME dup(?);
	union Misc
		PhysicalAddress  		dd 		?;
		VirtualSize 			dd		?;
	ends
	VirtualAddress				dd		?;			//节内容的RVA	
	SizeofRawData				dd		?;			//节内容文件中对齐后的大小
	PointerToRawData			dd		?;			//在文件中的偏移
	PointerToRelocations		dd		?;
	PointerToLinenumbers		dd		?;
	NumberOfRelocations			dw		?;
	NumberOfLinenumbers			dw		?;
	Characteristics				dd		?;			//区块属性,如可读,可写,可执行等
IMAGE_SECTION_HEADER ENDS	
	

注:IMAGE_OPTION_HEADER32.AddressOfEntryPoint
双字,该字段的值是一个RVA,他记录了启动代码距离该PE加载后的起始位置到底有多少个字节,我们可以修改这里的值,使之指向自己代码的位置,然后…进行一些操作,然后继续跳转执行原来的代码。
许多病毒程序,加密程序,补丁程序都是用的这个法子

3.6 节内容(区块)

名称 描述
.text 默认的代码区域,内容全是指令代码
.data 默认的读/写数据块,全局变量,静态变量一般存在这个区域
.rdata 默认只读数据块
.idata 包含其他外来的DLL的函数及数据信息,即输入表
.edata 输出表,当创建一个输出API或数据的可执行文件时,连接器会创建一个.EXP文件,这个.EXP文件会包含一个.edata区块,其会被加载到可执行文件中,经常被合并到.text或.rdate区域中
.rsrc 资源,包括模块的全部资源,图标,菜单,位图
.bss 未初始化的数据
.crt 用于C++运行时(CRT)所添加的数据
.tls 线程局部储存器
.reloc 可执行文件的机制重定位
.sdate 相对于全局指针的可被定位的,短的读写数据
.pdata 异常表
.didat 延迟装入数据
发布了43 篇原创文章 · 获赞 16 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/include_IT_dog/article/details/89047852