初步认识PE
第一部分:DOS头部 所有PE文件都必须以DOS MZ Header开头16进制的 DOS MZ Header部分加壳软件会处理DOS MZ Header4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000C80000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000 第二部分:DOS stub它其实是一个有效的EXE,在不支持PE的系统中,它将简单的提示一个错误我在几个软件上做了测试,这部分可以用00填充,不影响正常的使用 第三部分:PE HeaderPE Header是PE相关结构IMAGE_NT_HEADERS的简称执行体在支持PE文件结构的操作系统中执行时,PE装载器将从DOS MZ Header中找到PE Header的起始偏移量。因而跳过了DOS stub直接定位到真正的文件PE Header。注:从3C的位置开始定义,从低位到高位的写法 各区段的名字只是一个代号,不会影响我们正常的使用各种编译器有自己特有的区段名,记住这些能够有帮助与我们的工作 第四部分:Section table(节表/块表)每个结构包含对应节的属性、文件偏移量、虚拟偏移量等。我们可以把节表视为逻辑磁盘中的根目录 装载PE文件的主要步骤1. 当PE文件被执行,PE装载器检查DOS MZ Header里的PE Header偏移量,如果找到就跳转到PE Heardr。2. PE装载器检查PE Header的有效性,如果有效就跳转到PE Header的尾部3. 下面紧跟PE Heardr的是节表。PE装载器读取其中的节信息,并采用文件映射方法将这些节映射到内存,同时附上节表里指定的节属性。4. PE文件映射入内存后,PE装载器将处理PE文件中类似Import Tabel(引入表)逻辑部分。 名词解释:1.入口点(Entry Point)PE文件在执行时都要一个所谓的入口点,通常程序在执行的第一行代码的地址应该就是这个值。2.文件偏移地址(File Offset)所谓文件偏移地址(File Offset)就是我们把PE文件储存在磁盘上时,各数据的地址,也叫做物理地址(RAW Offset),它是从PE文件的第一个字节十六进制工具所显示的地址就是我们这里所讲的文件偏移地址了3.虚拟地址(Virtual Address,VA). 虚拟地址的产生主要是因为Windows程序运行在386保护模式下,因此程序访问存储器所使用的逻辑地址就称为虚拟地址,也就是我们通常讲的内存偏移地址(Memory Offset) 4.基地址(Image Base)是指文件执行时被映射到指定内存地址中的初始内存地址,这个值是有PE文件本身设定的。这是PE文件希望被加载到的虚拟空间地址,比如400000h,除非有其它模块已经占用了这里的空间,否则加载程序将会尝试将PE加载到00400000h处。这个基地址在生成文件是可以设置成其它的 5. 相对虚拟地址(Relative Virtual Address,RVA)是内存中相对于PE文件装入地址(基地址)的偏移量00400000,00401000相对虚拟地址=00401000-00400000 PE Signature字段,也就是PE头了在一个有效的PE文件里,Signature字段被设置为00004550h,ASCII字符是“PE00” 2-2-4-4-4-2-2这样的结构分别是:1.运行平台2.文件区块的数目(Section Tabel紧跟在此结构的后面)3.文件创建日期和事件4.指向符号表(用于调试)5.符号表中的符号个数(用于调试)6.IMAGE_OPTIONAL_HEADER32结构大小(紧跟在此后面)其大小依赖于是32位还是64位文件,对于32位PE文件,这个通常是00E0h;对于64位PE32+文件,这个是00F0h。不管怎么样,这些是要求的最小值,较大的值可能也会出现。7.文件属性 IMAGE_FILE_HAEDER结构完了之后紧接着的就是IMAGE_OPTIONAL_HEADER32结构IMAGE_OPTIONAL_HEADER32结构96字节现在就是IMAGE_DATA_DIRECTORY非常重要里面包含了输出表、输入表和资源等重要数据的定位每个成员占8个字节,分别指向相关的结构前四个字节为地址,后4个字节为大小 从上往下,分别是:导出表导入表资源例外表安全证书重定位表调试信息版本号全局指针TLS表加载构造表绑定表IAT表延迟导入表COM保留紧跟着的就是区块表了,它是一个IMAGE_SECTIN_HEADER结构数组。每个结构包含了它所关联区块的信息,入位置、长度、属性;该数组的数目由IMAGE_FILE_HAEDER中的第2个参数指出每一个IMAGE_SECTIN_HEADER结构体,有40个字节组成分别是:1块名,多数块名以一个“.”开始,这个不是必须的。值得注意的是,如果块名超过8个字节,则没有最后的终止标志“NULL”字节2指出实际的、被使用的区块的大小,是区块在没有对齐处理前的实际大小(物理大小)3该块装载到内存中的RVA。(虚拟地址)4该块在磁盘文件中所占的大小。在可执行文件中,该字段包含经过FileAlignment调整后的长度。例如,指定FileAlignment的大小为200h,如果实际长度为19AH个字节,这个块应保存的长度为200h个字节。(虚拟大小)5该块在磁盘文件中的偏移。(物理位置)6这部分在EXE中无意义。7行号表在文件中的偏移值。8这部分在EXE中无意义9该块在行号表中的行号数目10块属性。如可读、可写等PE文件一般至少有两个区块:一个是代码块,另一个是数据块以下是微软定义的区块意义,大家可以做一个参考 输入表可执行文件使用来自于其它DLL的代码或数据时,称为输入。Windows加载器的工作之一就是定位所有被输入的函数和数据,并让正在被装入的文件可以使用那些地址。这个过程是通过PE文件的输入表(Import Tabel,检查IT,也叫导入表)来完成的,输入表中保存的是函数名和驻留的DLL名等动态链接所需的信息。输入表在软件外壳技术上的地位非常重要。 输入函数是怎么调用的呢输入函数的代码位于相关的DLL文件中,在调用者程序中只保留相关函数信息,如函数名,DLL文件名等。对于磁盘上的PE文件来说,它无法得知这些输入函数在内存中的地址。只有PE文件被装入内存后,Windows加载器才将相关DLL装入,并将调用输入函数的指令和函数实际所处的地址联系起来。当应用程序调用一个DLL的代码和数据时,那它正在隐含连接到DLL另一种是运行期的连接,这意味着必须确定目标DLL已经被加载,然后寻找API的地址,这几乎总是通过调用LoadLibrary个GetProcAddress来完成的。在PE文件中有一组数据结构,它们分别对应着每个被输入的DLL。每一这样的结构都给出了被输入的DLL的名称并指向一组函数指针。这组函数指针被称为输入地址表(IAT)每一个被引入的API函数在IAT里都有自己保留的位置,在那里它将被Windows加载器写入输入函数的地址。一旦模块被装入,IAT中包含所要调用输入函数的地址。 绝对偏移地址=RAV-区段的物理地址-虚拟地址
还行!!!!!! 好文章,鼓励一下。 学习学习了。 好东东,支持! 这个对于新手,还是可以学习的
页:
[1]