
pe结构详解64位和32位的差别.doc
21页1 基本概念下表描述了贯穿于本文中的一些概念:名称描述地址是“虚拟地址”而不是“物理地址”为什么不是“物理地址”呢?因为数据在内存的位置经常在变,这样可以节省内存开支、避开错误的内存位置等的优势同时用户并不需要知道具体的“真实地址”,因为系统自己会为程序准备好内存空间的(只要内存足够大)镜像文件包含以EXE文件为代表的“可执行文件”、以DLL文件为代表的“动态链接库”为什么用“镜像”?这是因为他们常常被直接“复制”到内存,有“镜像”的某种意思看来西方人挺有想象力的哦^0^RVA英文全称Relatively Virtual Address偏移(又称“相对虚拟地址”)相对镜像基址的偏移节节是PE文件中代码或数据的基本单元原则上讲,节只分为“代码节”和“数据节”VA英文全称Virtual Address基址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图1 解释了Microsoft PE可执行文件格式:PE文件总体上分为“头”和“节”头”是“节”的描述、简化、说明,“节”是“头”的具体化3 文件头PE文件的头分为DOS头、NT头、节头注意,这是本人的分法,在此之前并没有这种分法这样分法会更加合理,更易理解因为这三个部分正好构成SizeOfHeaders所指的范围,所以将它们合为“头”这里的3个头与别的文章的头的定义会有所区别节头紧跟在NT头后面3.1 DOS头(PE文件签名的偏移地址就是大小)用记事本打开任何一个镜像文件,其头2个字节必为字符串“MZ”,这是Mark Zbikowski的姓名缩写,他是最初的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下时,这个程序显示“This program cannot be run in DOS mode(此程序不能在DOS模式下运行)”这条消息用户也可以自己更改该程序,有些还原软件就是这么干的同时,有些程序既能运行于DOS又能运行于Windows下就是这个原因Notepad.exe整个DOS头大小为224个字节,大部分不能在DOS下运行的Win32文件都是这个值MS-DOS程序是可有可无的,如果你想使文件大小尽可能的小可以省掉MS-DOS程序,同时把前面的参数都清03.2 NT头(244或260个字节)紧跟着PE文件签名之后,是NT头NT头分成3个部分,因为第2部分在32与64位系统里有区别,第3部分虽然也是头,但实际很不像“头”第1部分(20个字节)偏移大小英文名中文名描述02Machine机器数标识CPU的数字参考3.2.1节“机器类型”22NumberOfSections节数节的数目。
Windows加载器限制节的最大数目为9644TimeDateStamp时间/日期标记UTC时间1970年1月1日00:00起的总秒数的低32位,它指出文件何时被创建88已经废除162SizeOfOptionalHeader可选头大小第2部分+第3部分的总大小这个大小在32位和64位文件中是不同的对于32位文件来说,它是224;对于64位文件来说,它是240182FillCharacteristics文件特征值指示文件属性的标志参考3.2.2节“特征”第2部分(96或112个字节)偏移大小英文名中文名描述02Magic魔数这个无符号整数指出了镜像文件的状态0x10B表明这是一个32位镜像文件0x107表明这是一个ROM镜像0x20B表明这是一个64位镜像文件21MajorLinkerVersion链接器的主版本号链接器的主版本号31MinorLinkerVersion链接器的次版本号链接器的次版本号44SizeOfCode代码节大小一般放在“.text”节里如果有多个代码节的话,它是所有代码节的和必须是FileAlignment的整数倍,是在文件里的大小84SizeOfInitializedData已初始化数大小一般放在“.data”节里。
如果有多个这样的节话,它是所有这些节的和必须是FileAlignment的整数倍,是在文件里的大小124SizeOfUninitializedData未初始化数大小一般放在“.bss”节里如果有多个这样的节话,它是所有这些节的和必须是FileAlignment的整数倍,是在文件里的大小164AddressOfEntryPoint入口点当可执行文件被加载进内存时其入口点RVA对于一般程序镜像来说,它就是启动地址为0则从ImageBase开始执行对于dll文件是可选的204BaseOfCode代码基址当镜像被加载进内存时代码节的开头RVA必须是SectionAlignment的整数倍244BaseOfData数据基址当镜像被加载进内存时数据节的开头RVA在64位文件中此处被并入紧随其后的ImageBase中必须是SectionAlignment的整数倍28/244/8ImageBase镜像基址当加载进内存时镜像的第1个字节的首选地址它必须是64K的倍数DLL默认是10000000HWindows CE 的EXE默认是00010000HWindows 系列的EXE默认是00400000H324SectionAlignment内存对齐当加载进内存时节的对齐值(以字节计)。
它必须≥FileAlignment默认是相应系统的页面大小364FileAlignment文件对齐用来对齐镜像文件的节中的原始数据的对齐因子(以字节计)它应该是界于512和64K之间的2的幂(包括这两个边界值)默认是512如果SectionAlignment小于相应系统的页面大小,那么FileAlignment必须与SectionAlignment相等402MajorOperatingSystemVersion主系统的主版本号操作系统的版本号可以从“我的电脑”→“帮助”里面看到,Windows XP是5.15是主版本号,1是次版本号422MinorOperatingSystemVersion主系统的次版本号 442MajorImageVersion镜像的主版本号 462MinorImageVersion镜像的次版本号 482MajorSubsystemVersion子系统的主版本号 502MinorSubsystemVersion子系统的次版本号 522Win32VersionValue保留,必须为0 564SizeOfImage镜像大小当镜像被加载进内存时的大小,包括所有的文件头向上舍入为SectionAlignment的倍数。
604SizeOfHeaders头大小所有头的总大小,向上舍入为FileAlignment的倍数可以以此值作为PE文件第一节的文件偏移量644CheckSum校验和镜像文件的校验和计算校验和的算法被合并到了Imagehlp.DLL 中以下程序在加载时被校验以确定其是否合法:所有的驱动程序、任何在引导时被加载的DLL以及加载进关键Windows进程中的DLL682Subsystem子系统类型运行此镜像所需的子系统参考后面的“Windows子系统”部分702DllCharacteristicsDLL标识参考后面的“DLL特征”部分724/8SizeOfStackReserve堆栈保留大小最大栈大小CPU的堆栈默认是1MB76/804/8SizeOfStackCommit堆栈提交大小初始提交的堆栈大小默认是4KB80/884/8SizeOfHeapReserve堆保留大小最大堆大小编译器分配的默认是1MB84/964/8SizeOfHeapCommit堆栈交大小初始提交的局部堆空间大小默认是4KB88/1044LoaderFlags保留,必须为0 92/1084NumberOfRvaAndSizes目录项数目数据目录项的个数。
由于以前发行的Windows NT的原因,它只能为16第3部分数据目录(128个字节)偏移(PE32/PE32+)大小英文名描述96/1128Export Table导出表的地址和大小参考5.1节“.edata”104/1208Import Table导入目录表的地址和大小参考5.2.1节“.idata”112/1288Resource Table资源表的地址和大小参考5.6节“.rsrc”120/1368Exception Table异常表的地址和大小参考5.3节“.pdata”128/1448Certificate Table属性证书表的地址和大小参考6节“属性证书表”136/1528Base Relocation Table基址重定位表的地址和大小参考5.4节“.reloc”144/1608Debug调试数据起始地址和大小152/1688Architecture保留,必须为0160/1768Global Ptr将被存储在全局指针寄存器中的一个值的RVA这个结构的Size域必须为0168/1848TLS Table线程局部存储(TLS)表的地址和大小176/1928Load Config Table加载配置表的地址和大小。
参考5.5节“加载配置结构”184/2008Bound Import绑定导入查找表的地址和大小参考5.2.2节“导入查找表”192/2088IAT导入地址表的地址和大小参考5.2.4节“导入地址表”200/2168Delay Import Descriptor延迟导入描述符的地址和大小。












