逆向工程之PE文件格式
Posted 周星星✪
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了逆向工程之PE文件格式相关的知识,希望对你有一定的参考价值。
PE文件格式(一)
一.介绍
-
PE文件是Windows操作系统下使用的可执行文件文件格式。
-
PE文件是指32位的可执行文件,也叫PE32。64位的可执行文件称为PE+或者PE32+,是PE文件的一种扩展形式(不是PE64)。
二.PE文件格式
以上的文件类型中,OBJ(对象)文件是不可以执行的,其他都是可以执行的,DLL,SYS文件不能直接在shell上执行,但是在调试器或服务上是可执行的。(学过汇编语言的同学都知道OBJ是编译结果文件,也是PE文件)
下面以记事本(notepad.exe)程序进行简单说明,首先使用Hex Editor打丁开记事本程序。
图是notepad.exe文件的起始部分,也是PE文件的头部分(PE header)。notepad.exe文件运行需要的所有信息就存储在这个PE头中。
在学习PE文件时,最重要的就是学习PE头中的结构体。
书中将以 Windows XP SP3 的notepad.exe 为例进行说明,与其他版本Windows 下的notepad.exe 文件结构类似,但是地址不同。
1. 基本结构
1.1 基本结构
notepad.exe具有普通PE文件的基本结构。
从DOS头(DOS header)到节区头(Sectionheader)是PE头部分,其下的节区合称PE体。文件中使用偏移(o1fset),内存中使用VA (Virtual Address,虚拟地址)来表示位置。文件加载到内存时,情况就会发生变化(节区的大小、位置等)。文件的内容一般可分为代码(.text)、数据data)、资源(.rsrc)节,分别保存。
提示
根据所用的不同开发工具(VB/VC++/Delphiletc)与编译选项,节区的名称、大小个数、存储的内容等都是不同的。
最重要的是它们按照不同的用途分类保存到不同的节中。
各节区头定义了各节区在文件或内存中的大小、位置、属性等。
1.2VA&RVA
RVA+Imagebase=VA
RVA是相对虚拟地址(相对地址)
VA是进程虚拟内存的绝对地址
Imagebase是基址
32位系统中VA的范围是00000000~FFFFFFFF
1.3PE头
DOS头
一个PE文件起始的部分开始就是DOS头,这和GIF,BMP,JPG,RAR等等都一样,只是在文件起始部位标识这个文件属于什么文件类型。这里是DOS头的结构体:
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
WORD e_magic; // Magic number
WORD e_cblp; // Bytes on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in paragraphs
WORD e_minalloc; // Minimum extra paragraphs needed
WORD e_maxalloc; // Maximum extra paragraphs needed
WORD e_ss; // Initial (relative) SS value
WORD e_sp; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial IP value
WORD e_cs; // Initial (relative) CS value
WORD e_lfarlc; // File address of relocation table
WORD e_ovno; // Overlay number
WORD e_res[4]; // Reserved words
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[10]; // Reserved words
LONG e_lfanew; // File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
IMAGE_DOS_HEADER结构体的大小为64字节。而在结构体中必须知道的两个重要成员:
e_magic:DOS签名(MZ->4D5A)
e_ifanew:指示NT头的偏移(可变值)
DOS存根
DOS存根在DOS头下方,是由代码和数据混合组成的。
![在这里插入图片描述](https://img-blog.csdnimg.cn/c36c929b41304ea09f70d7df9701e608.png)
DOS存根是一段简单的DOS程序,主要用来输出类似“This program cannot be run in DOS mode.”的提示语句,由于DOS存根里的内容无关紧要,所以可以把这部分用来存储其他数据而不改变程序原本的功能。
1.4 NT头
IMAGE_NT_HEADERS结构体:
- 这个PE头标志,也就是标准PE头
- NT头这个结构体的大小为F8
1.5 NT头:文件头
20个字节,对应的结构体名字:IMAGE_FILE_HEADER STRUCT
从结构的定义可以看到第二个字段是当前PE文件的节的数目。
Machine:指出该文件运行所需的CPU。
NumberOfSections:文件的节数目。
Characteristics文件属性:区分文件是exe还是dll等。
1.6 可选头定义
对应的结构体名字:IMAGE_OPTIONAL_HEADER32 STRUCT
由于可选头字段数目多达32个,这里没有对全部字段的定义进行列举,只列举了几个相对重要的一些字段(12个)。
可选头中定义了如下重要信息:
- 所有含代码的节的总大小
- 所有含已初始化数据的节的总大小
- 所有含未初始化数据的节的大小
- 程序执行入口RVA
- 代码的节的起始RVA
- 数据的节的起始RVA
- 程序的建议装载地址
- 内存中的节的对齐粒度
- 文件中的节的对齐粒度
- 内存中整个PE映像尺寸
- 所有头+节表的大小
- 导出表 导入表
- 资源
- 重定位表
- 调试信息
- 版权信息
- 导入函数地址表
1.7 节表
节表:PE代码和数据的结构数据,指示装载系统代码段在哪里,数据段在哪里等。
PE文件中所有节的属性都被定义在节表(段表)中,节表是一个由IMAGE_SECTION_HEADER结构组成的数组,每个结构用来描述一个节。
结构的排列顺序和它们描述的节在文件中的排列顺序是一致的。全部有效结构的最后以一个空的IMAGE_SECTION_HEADER结构作为结束,所以节表中总的IMAGE_SECTION_HEADER结构数量等于节的数量加一。节表总是被存放在紧接在PE文件头的地方,也就是从PE文件头开始的偏移为00f8h的地方。
(注意:不是文件本身的头部,由于程序的dos块的大小并不是固定的,所以导致PE头相对于mz头的偏移变化的。所以我们在计算偏移的时候,对于PE头后面的数据都习惯用相对于PE头的偏移,PE头大小是固定的的。)
在文件头中已经定义了文件的节的数目:0ah个,那么该文件的节表共有11个IMAGE_SECTION_HEADER结构。
1.8 节数据
常见的节数据:
- text:代码段,是在编译或汇编结束时产生的一种块,它的内容全部是指令代码。也有的编译器将该段命名为.code
- .data:初始化的数据块,是初始化的数据块,包含那些编译时被初始化的变量、字符串
- .idata:输入表,包含其他外来dll的函数和数据信息,也就是输入表,也有人称之为导入表。
- .rsrc:资源数据块,包含模块的全部资源数据,如图标、菜单、位图等。
- .reloc:重定位表,用于保存基址的重定位表。即当装在程序不能按照连接器所指定的地址装载文件是,需要对指令或已经初始化的变量进行调整,该块中也包含了调整过程中所需要的一些数据,如果装载能够正常装在则忽略此段中的数据。
- .edata:导出表,是pe文件的输出表,以供其他模块使用,并不是每个pe文件都有此数据段,因为有的文件并不需要输出一些函数,该数据段常见于动态连接库文件中。
- .radata:存放调试目录、说明字符串,该数据块并不常见主要是用于存放一些调试信息。
后续更新PE文件的其他学习内容
参考教材《逆向工程核心原理》
以上是关于逆向工程之PE文件格式的主要内容,如果未能解决你的问题,请参考以下文章