《逆向工程核心原理》第13章——PE文件格式(1):PE头


介绍

PE是指32位可执行文件,也称PE32。64位可执行文件称为PE+或PE32+,是PE文件的一种扩展形式。


PE文件格式

PE文件种类如下:

种类主扩展名
可执行系列exe scr
库系列dll ocx cpl drv
驱动程序系列sys vxd
对象文件系列obj

严格来讲,obj文件之外的所有文件都是可执行的。ddl、sys文件虽然不能直接在shell执行,但可以使用其他方法(调试器、服务等)执行。

PE文件基本结构

从DOS头到节区头是PE头部分下面的节区合称为PE体。文件中使用偏移,内存中使用VA虚拟地址来表示位置。文件加载到内存后,节区的位置大小会发生变化。文件内容一般可分为代码、数据、资源节,分别保存。

各节区头分别定义各节区在文件或内存中的大小、位置、属性等

PE头和各节区尾部存在NULL填充区域,这是因为为了提高处理效率,计算机中使用“最小基本单位的概念”。

在这里插入图片描述

VA:进程虚拟内存的绝对地址。
RVA:从某一个基准位置(ImageBase)开始的相对地址

VA=RVA+ImageBase,两者都指的是装载进入内存后的地址

PE头内部信息大多以RVA形式存在:因为PE文件(主要是DLL)加载到进程虚拟内存的特定位置时,该位置可能已经加载了其他DLL,此时必须通过重定位将其加载到其他空白区域。发生重定位后,只要相对于基准位置的相对地址没有变化,就能正常访问。


PE头

包括

  • DOS头
  • DOS存根
  • NT头
  • 各节区头

DOS头

PE头最前面的40H字节是一个IMAGE_DOS_HEADER结构体——DOS头
在这里插入图片描述
两个重要成员:

  • e_magic:多有PE文件开始部分都有的DOS签名(‘MZ’,4D5A)
  • e_lfanew:指示NT头的偏移
    在这里插入图片描述

DOS存根

在DOS头下方,可选项且大小不固定由代码和数据混合而成
在这里插入图片描述
文件偏移40~4D区域为16位汇编指令:功能为输出偏移0E处字符串。在DOS调试器debug.exe中运行:
在这里插入图片描述
若使用得当,可以在一个可执行文件中创建另一个文件,在16位DOS和32位Windows中都能运行。

NT头

NTIMAGE_NT_HEADERS结构体由3个成员组成:签名、文件头、可选头。其结构体大小为F8H起始位置由DOS头的e_lfanew确定(因为DOS存根大小不确定,这里为0000 00E0h
在这里插入图片描述
签名:50450000h(‘PE’00)
在这里插入图片描述

NT头:文件头

文件头是表现文件大致属性的IMAGE_FILE_HEADER结构体。
在这里插入图片描述
四个重要成员:

  • Machine:每个CPU唯一拥有的机器码,这里为Intel 386芯片14C。
  • NumberOfSections:节区数,此处为3。
  • SizeOfOptionalHeader:可选头大小,用来指出IMAGE_OPTIONAL_HEADER32/64的长度,此处是e0。
  • Characteristics表示文件属性,记住0002h与2000h。此处为010F,包含了重定向信息删除,可执行文件,行数移除,本地符号表移除以及系统文件等属性。
    在这里插入图片描述在这里插入图片描述

NT头:可选头

IMAGE_OPTIONAK_HEADER是PE头结构中最大的。其大小在IMAGE_FILE_HEADER的SizeOfOptionalHeader中标明,此处为00E0。
在这里插入图片描述
在这里插入图片描述
几个重要成员:

  • Magic:可选头是32结构体时,该值为10B。可选头是64位结构体时,该值为20B。
  • AddressOfEntryPointEP的RVA值,指出程序最先执行的代码起始地址
  • ImageBase:文件优先装入的虚拟内存地址。32位系统进程虚拟内存范围为0~FFFFFFFF。一般来说,EXE文件ImageBase值为00400000,DLL文件为10000000
    PE装载器先创建进程,再将文件载入内存,然后把EIP寄存器的值设为ImageBase+AddressOfEntryPoint。所以说EIP的初始值由可执行文件描述部分决定。
  • SectionAlignment、FileAligment:SectionAlignment指定了节区在内存中的最小单位,FileAligment指定了节区在磁盘文件中的最小单位。磁盘文件或内存的节区大小必定为对应最小单位的整数倍。
  • SizeOfImage:PE文件在虚拟内存中所占空间的大小,即加载后大小。
  • SizeOfHeadersPE头的大小,是FileAlignment的整数倍(磁盘文件中)。
  • Subsystem:区分系统驱动文件与普通可执行文件。
    在这里插入图片描述
  • NumberOfRvaAndSizes:指定最后一个成员DataDirectory数组的个数,以这个为准,而不是IMAGE_NUMBEROF_DIRECTERY_ENTRIES(16)。
  • DataDirectory:以IMAGE_DATA_DIRECTORY结构体数组,数组每一项都有被定义的值。DataDirectory[n]结构体中的每一个都有两个属性:一个是相对虚拟地址,一个是大小,其中每个结构体的大小为8字节。
    在这里插入图片描述
    在这里插入图片描述
    更正:程序EP的RVA应该是0000739D,上图框选应该向右移动两字节。

节区头

节区头中定义了各节区属性。PE文件中的code(代码)、data(数据)、resourse(资源)等按照属性分类存储在不同节区,这样可以保证程序的安全性。

节区头是由IMAGE_SECTION_HEADER结构体组成的数组,每个结构体对应一个节区。大小固定为40字节
在这里插入图片描述
几个重要成员:

  • VirtualSize内存中节区所占实际大小
  • VirtualAddress内存中节区起始地址(RVA),运行时会加上ImageBase值。按SectionAlignment对齐。
  • SizeofRawData:磁盘中节区所占大小,通常是VirtualSize按照FileAligment值对齐后得到的
  • PointerToRawData:磁盘中节区起始地址。按FileAligment对其。
  • Characteristics:节区属性,由bit OR组合而成。
    在这里插入图片描述
    下图显示notpad.exe的三个节区头数组:
    在这里插入图片描述在这里插入图片描述在这里插入图片描述

RVA与RAW

PE文件加载到内存时,每个节区都要准确完成内存地址与磁盘文件偏移之间的映射,这种映射称为RVA to RAW。方法为:(1)查找RVA所在节区(2)使用下方公式计算处文件偏移RAW。

RAW-PointerToRawData(磁盘中节区偏移)=RVA-VirtualAddress(内存中节区偏移)

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值