1基本概念
下表描述了贯穿于本文中的一些概念:
名称 | 描述 |
地址 | 是虚拟地址而不是物理地址。为什么不是物理地址呢?因为数据在内存的位置经常在变,这样可以节省内存开支、避开错误的内存位置等的优势。同时用户并不需要知道具体的真实地址,因为系统自己会为程序准备好内存空间的(只要内存足够大) |
镜像文件 | 包含以EXE文件为代表的可执行文件、以DLL文件为代表的动态链接库。为什么用镜像?这是因为他们常常 被直接复制到内存,有镜像的某种意思。看来西方人挺有想象力的哦人0人 |
RVA | 英文全称RelativelyVirtualAddress。偏移(又称相对虚拟地址)。相对镜像基址的偏移。 |
节 | 节是PE文件中代码或数据的基本单元。原则上讲,节只分为代码节和数据节。 |
VA英文全称VirtualAddress。基址
2概览
x86都是32位的,IA-64都是64位的。64位Windows需要做的只是修改PE格式的少数几个域。这种新的格式被称为PE32+。它并没有增加任何新域,仅从PE格式中删除了一个域。其余的改变就是简单地把某些域从32位扩展到64位。在大部分情况下,你都能写出同时适用于32位和64位PE文件的代码。
EXE文件与DLL文件的区别完全是语义上的。它们使用的是相同的PE格式。惟一的不同在于一个位,这个位用来指示文件应该作为EXE还是DLL。甚至DLL文件的扩展名也完全也是人为的。你可以给DLL一个完全不同的扩展名,例如.OCX控件和控制面板小程序(.CPL)都是DLL。
COFF符号表 | ||
CQFF行号 | ||
.rdoc | ||
.edata | ||
.data | ||
.text | ||
IhIAGE_SECTKMCHEACER | ||
IkiAGE_5ECTIONJSEADER | ||
ILIAGE_5ECTIONJILADEE. | ||
IMAGE_SECTICUCHEABER | ||
— | ||
专指目李杰 | ||
ILIAGE_OPTIONAL_HEADEP32 | ||
ZMAGE_TLLE_HEADEE. | ||
■PE'ACi | ||
DOSstub | ||
CoimPew谑莅适息
IX>5'MZ'HEADER
i | |
J | L |
*u,pud\y.L'Inn
调试信息
I | |
J | L |
生(Secti-MZ;
1 | l |
I | ! |
PE文件头
! | |
J | I |
DOSSEf
K件表
FE文件框架结构
图1解释了MicrosoftPE可执行文件格式:
PE文件总体上分为头和节。头是节的描述、简化、说明,节是头的具体化。
3文件头
PE文件的头分为DOS头、NT头、节头。注意,这是本人的分法,在此之前并没有这种分法。这样分法会更加合理,更易理解。因为这三个部分正好构成SizeOfHeaders所指的范围,所以将它们合为头。这里的3个头与别的文章的头的定义会有所区别。
节头紧跟在NT头后面。
3.1DOS头(PE文件签名的偏移地址就是大小)
用记事本打开任何一个镜像文件,其头2个字节必为字符串MZ,这是MarkZbikowski的姓名
缩写,他是最初的MS-DOS设计者之一。然后是一些在MS-DOS下的一些参数,这些参数是在MS-DOS下运行该程序时要用到的。在这些参数的末尾也就是文件的偏移0x3C(第60字节)处是是一个4字节的PE文件签名的偏移地址。该地址有一个专用名称叫做E_lfanew。这个签名是PE00(字母P和E后跟着两个空字节)。紧跟着E_lfanew的是一个MS-DOS程序。那是一个运行于MS-DOS下的合法应用程序。当可执行文件(一般指exe、com文件)运行于MS-DOS下时,这个程序显示TisroramcannotberninDOSmode(此程序不能在DOS模式下运行)这条消息。用户也可以自己更改该程序,有些还原软件就是这么干的。同时,有些程序既能运行于DOS又能运行于Windows下就是这个原因。整个DOS头大小为224个字节,大部分不能在DOS下运行的Win32文件都是这个值。MS-DOS程序是可有可无的,如果你想使文件大小尽可能的小可以省掉MS-DOS程序,同时把前面的参数都清0。
3.2NT头(244或260个字节)
紧跟着PE文件签名之后,是NT头。NT头分成3个部分,因为第2部分在32与64位系统里有区别,第3部分虽然也是头,但实际很不像头。
x86架构和arm架构区别
第1部分(20个字节)
偏移 | 大小 | 英文名 | 中文名 | 描述 |
0 | 2 | Machine | 机器数 | 标识CPU的数字。参考3.2.1节机器类型。 |
2 | 2 | NumberOfSections | 节数 | 节的数目。Windows加载器限制节的最大数目为96。 |
4 | 4 | TimeDateStamp | 时间/日期标记 | UTC时间1970年1月1日00:00起的总秒数的低32位,它指出文件何时被创建。 |
8 | 8 | 已经废除 | ||
16 | 2 | SizeOfOptionalHeader | 可选头大小 | 第2部分+第3部分的总大小。这个大小在32位和64位文件中是不同的。对于32位文件位文件来说,它是240。 |
18 | 2 | FillCharacteristics | 文件特征值 | 指示文件属性的标志。参考3.2.2节特征。 |
第2部分(96或112个字节)
偏移 | 大小 | 英文名 | 中文名 | 描述 |
0 | 2 | Magic | 魔数 | 这个无符号整数指出了镜像文件的状态。 0x10B表明这是一个32位镜像文件。 0x107表明这是一个ROM镜像。 0x20B表明这是一个64位镜像文件。 |
2 | 1 | MajorLinkerVersion | 链接器的主版本号 | 链接器的主版本号。 |
3 | 1 | MinorLinkerVersion | 链接器的次版本号 | 链接器的次版本号。 |
4 | 4 | SizeOfCode | 代码节大小 | 一般放在.text节里。如果有多个代码节的话,它是所有代码节的和。必须是FileAlignment的整数倍,是在文件里的大小。 |
8 | 4 | SizeOfInitializedData | 已初始化数大小 | 一般放在.data节里。如果有多个这样的节话,它是所有这些节的和。必须是FileAlignment的整数倍,是在文件里的大小。 |
12 | 4 | SizeOfUninitializedData | 未初始化数大小 | 一般放在.bss节里。如果有多个这样的节话,它是所有这些节的和。必须是FileAlignment的整数倍,是在文件里的大小。 |
16 | 4 | AddressOfEntryPoint | 入口点 | 当可执行文件被加载进内存时其入口点RVA。 |
对于一般程序镜像来说,它就是启动地址。为0则从ImageBase开始执行。对于dll文件是可选的。 | ||||
20 | 4 | BaseOfCode | 代码基址 | 当镜像被加载进内存时代码节的开头RVA。必须是SectionAlignment的整数倍。 |
24 | 4 | BaseOfData | 数据基址 | 当镜像被加载进内存时数据节的开头RVA。(在64位文件中此处被并入紧随其后的ImageBase中。)必须是SectionAlignment的整数倍。 |
28/24 | 4/8 | ImageBase | 镜像基址 | 当加载进内存时镜像的第1个字节的首选地址。 它必须是64K的倍数。DLL默认是10000000H。 WindowsCE的EXE默认是00010000H。 Windows系列的EXE默认是00400000H。 |
32 | 4 | SectionAlignment | 内存对齐 | 当加载进内存时节的对齐值(以字节计)。它必须FileAlignment。默认是相应系统的页面大小。 |
36 | 4 | FileAlignment | 文件对齐 | 用来对齐镜像文件的节中的原始数据的对齐因子(以字节计)。它应该是界于512和64K之间的2的幂(包括这两个边界值)。默认是512。 如果小于相应系统的页面大 小,那么FileAlignment必须与SectionAlignment 相等。 |
40 | 2 | MajorOperatingSystemVersion | 主系统的主版本号 | 操作系统的版本号可以从我的电脑帮助 里面看到,WindowsXP是5.1。5是主版本号, 1是次版本号 |
42 | 2 | MinorOperatingSystemVersion | 主系统的次版本号 | |
44 | 2 | MajorImageVersion | 镜像的主版本号 | |
46 | 2 | MinorImageVersion | 镜像的次版本号 | |
48 | 2 | MajorSubsystemVersion | 子系统的主版本号 | |
50 | 2 | MinorSubsystemVersion | 子系统的次版本号 | |
52 | 2 | Win32VersionValue | 保留,必须为0 | |
56 | 4 | SizeOfImage | 镜像大小 | 当镜像被加载进内存时的大小,包括所有的文件头。向上舍入为SectionAlignment的倍数。 |
60 | 4 | SizeOfHeaders | 头大小 | 所有头的总大小,向上舍入为FileAlignment的倍数。可以以此值作为PE文件第一节的文件偏移量。 |
64 | 4 | CheckSum | 校验和 | 镜像文件的校验和。计算校验和的算法被合并到了Imagehlp.DLL中。以下程序在加载时被校验以确定其是否合法:所有的驱动程序、任何在引导时被加载的DLL以及加载进关键Windows进程中的DLL。 |
68 | 2 | Subsystem | 子系统类型 | 运行此镜像所需的子系统。参考后面的 |
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论