逆向分析工程读书笔记之二

PE文件格式

PE文件的基本结构是PE头,PE体。

PE头又分为DOS头,DOS存根,NT头,节区头。

DOS头是一个结构体,在32位系统中,它的长度是64个字节。其中最重要的是首尾两个结构体成员:e_magic和e_lfanew,前者表示这是一个DOS头:用两个字节4D5A,翻译成ascii码就是“MZ”;后者用来标注NT头的偏移(根据文件类型不同是可以变化的)。根据PE规范,一个PE文件开始的两个字节必须是4D5A也就是“MZ”。但是e_lfanew却是可变,通常情况下32位系统为0000-00E0,64位为0000-00F0。

DOS存根是可选项,可有可无。在DOS头下方,大小不固定,代码与数据混合。用来在dos环境下执行文件,在Windows环境下完全忽视该段。

NT头也是一个结构体。它有三个成员。第一个成员是“签名”成员占4个字节,类似于DOS头的“MZ”。第一个成员的值必须是5045-0000,也就是“PE”00。第二个成员本身是一个结构体,叫做文件头:file header。第三个成员本身也是一个结构体,叫做可选头:OptionalHeader。

文件头本身有七个成员,比较重要的有:第一个成员Machine,两个字节,标识CPU型号。第二个成员NumberOfSections,标识节区数目,两个字节。第六个成员SizeOfOptionalHeader,标识可选头的大小,两个字节。第七个成员,Characteristic,标识文件属性,bit OR的形式,每一位代表一种信息,两个字节。其他三个成员都是四个字节。

可选头的成员比较多,我们以可选头起始位置为基准,使用偏移量(十六进制)来描述重要成员。00-01两个字节表示的是Magic成员,32位系统可选头是010B,64位是020B。10-13四个字节是AddressOfEntryPoint,标识PE文件的入口点地址(这个地址是相对虚拟地址)。1C到1F这四个字节是ImageBase成员,用来标识装载到内存时文件的起始位置。20-23这四个字节是SectionAlignment成员,标识节区在内存中的最小单位。24-27这四个字节则是FileAlignment成员,标识节区在文件中的最小单位。34-37这四个字节是成员SizeOfImage,标识着文件加载到内存之后,在内存中的大小。38-3B这四个字节是成员SizeOfHeaders,标识着PE头的大小,同时也就标识着第一节区头的偏移量。40-41这两个字节是成员Subsystem,标识着文件的类型,1表示驱动文件(sys)2表示窗口应用程序3表示控制台应用程序。58-5B这四个字节是成员NumberOfRvaAndSizes,标识着DataDirectory成员的个数。最后一个成员是一个结构体数组:DataDirectory,每个数组成员的大小是8个字节,成员的数目由NumberOfRvaAndSizes来给出,默认是16个。

节区头定义了各个节区的属性。将代码、数据资源分为不同的节区存放的好处是保证程序的安全性。节区头是由结构体数组组成的。每个数组元素对应一个节区,数组元素的个数由文件头成员NumberOfSections标识。每个数组元素都是一个结构体,每个结构体内成员个数是一样的。第一个成员是name,标识着节区名字,默认为八个字节,可以变更。第二个成员是一个联合体,物理地址PhysicalAddress和虚拟空间大小VirtualSize,四个字节(两个成员存储任意一个,这里一般存储后一个),VitualSize标识着该节区在内存中的大小。第三个成员位虚拟地址,VirtualAddress,占用四个字节;第四个成员SizeOfRawData,标识着该节区在磁盘中的大小,四个字节。第五个成员PointerToRawData,四个字节。第三、五个成员的值一般与可选头中SectionAlignment和FileAlignment成员的值的整数倍。最后一个成员为特征值,四个字节,以bit OR来表示节区属性。

PE头到此就结束了。

RVAtoRAW

RVA意思是相对虚拟内存地址,RAW意思就是相对磁盘文件地址。所谓相对都是指的以某一地址为基准而产生的偏移。

给定RVA为5000,根据PE文件头中各个数据可知在第一个节区内(可选头中SizeOfHeaders可知不在文件头中,在节区体内;依次查询节区头内Virtualaddress和VirtualSize),第一个节区起始位置由virtualaddress(1000)确定,因此可以求得偏移量为4000。在第一节区头中知道PointerToRawData(也就是磁盘文件中第一节区的起始位置)值为400,因此加上400得到RAW为4400。

这里之所以不以磁盘文件的起始位置和虚拟内存的起始位置为基准,是因为加载进内存之后,内存中的大小和磁盘文件的大小是不同的。也正是因为这样,才会产生给出RVA之后计算出的RAW却在下一个节区这样的事情。

posted @ 2015-12-02 14:38  半城日暖  阅读(374)  评论(0编辑  收藏  举报