PE文件结构

  Dos操作系统中的Com文件是最早也是结构最简单的可执行文件,Com文件是"纯代码的"。它没有附加数据来指定文件入口,因此第一条指令必须处于文件开头的位置。而且,没有重定位信息,这样代码中不能有跨段操作数据的指令。

  EXE文件是我们熟悉的另一种可执行文件,EXE文件的代码前面加了一个文件头,其中包含各种数据,如文件入口、堆栈位置、重定位表等。操作系统会根据文件头中的信息将代码部分装入内存,根据重定位表修正代码,最后在设置好堆栈后从文件头中指定的入口开始执行。


PE格式(Portable Executable File Format/可移植的执行体)

  Windows3.x  起引入了一种新的文件格式,既PE格式。在PE文件中,代码、已初始化数据、资源、和重定位信息等数据被按照属性分类放到不同的节(Section)中,而每个节的属性和位置信息用一个 IMAGE_SECTINO_HEADER 结构来描述,所有的IMAGE_SECTINO_HEADER结构组成一个节表(Section Table),节表数据在PE文件中被放在所有节数据的前面。

  由于数据是按照属性在节中放置的,不同用途但是属性相同的数据(如导入表、导出表以及.const段指定的只读数据)可能被放在同一个节中,所以PE文件中还用一系列的数据目录结构 IMAGE_DATA_DIRECTORY 来分别指明这些数据的位置,数据目录表和其他描述文件属性的数据合在一起称为PE文件头,PE文件头被放置在节和节表的前面。

 

PE文件的基本结构:

 

DOS文件头和DOS块

  PE文件中的DOS部分由Dos文件头和可执行代码两部分组成,可执行代码被称为“DOS块”。最前面的 

 MZ Header 是一个Dos文件头,占用了PE文件的前64个字节。它由 IMAGE_DOS_HEADER 结构定义:

 

  WINNT.H

typedef struct _IMAGE_DOS_HEADER {  // DOS .EXE header
    USHORT e_magic;         // Magic number
    USHORT e_cblp;          // Bytes on last page of file
    USHORT e_cp;            // Pages in file
    USHORT e_crlc;          // Relocations
    USHORT e_cparhdr;       // Size of header in paragraphs
    USHORT e_minalloc;      // Minimum extra paragraphs needed
    USHORT e_maxalloc;      // Maximum extra paragraphs needed
    USHORT e_ss;            // Initial (relative) SS value
    USHORT e_sp;            // Initial SP value
    USHORT e_csum;          // Checksum
    USHORT e_ip;            // Initial IP value
    USHORT e_cs;            // Initial (relative) CS value
    USHORT e_lfarlc;        // File address of relocation table
    USHORT e_ovno;          // Overlay number
    USHORT e_res[4];        // Reserved words
    USHORT e_oemid;         // OEM identifier (for e_oeminfo)
    USHORT e_oeminfo;       // OEM information; e_oemid specific
    USHORT e_res2[10];      // Reserved words
    LONG   e_lfanew;        // File address of new exe header
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
  e_magic 字段是DOS可执行文件标记,其数值等于Ascii码“MZ”。(在Windows.inc中已预定义为IMAGE_DOS_SIGNATURE)
对于PE文件来说,有用的是最后的 e_lfanew 字段,它指出了PE文件头在文件中的位置,这个位置总是以8字节为单位对齐的。
  
  

 

下图是用 UltraEdit 打开某个EXE文件的样子:


( UltraEdit :一个强大的替代Windows记事本(Notepad)的编辑器,可以用它直接编辑器十六进制文件(HEX)。)

 




  我们可以看到前两个字节是 4D 5A  其Ascii码等于“MZ”。这就是 e_magic 字段,不过值得注意的是在小端法

机器上,数据在内存中是按低位在低字节存放的,所以 e_magic = 0x5A4D 

 

PE文件头

PE文件头的第一个4字节是一个标志,它被定义为0x00004550,也就是"P","E"。这也是“PE”这个称呼的由来。

PE文件头是由 IMAGE_NT_HEADERS结构定义的:

IMAGE_NT_HEADERS STRUCT
  Signature      DWORD ?                      ; PE signature
  FileHeader     IMAGE_FILE_HEADER <>
  OptionalHeader IMAGE_OPTIONAL_HEADER32 <>
IMAGE_NT_HEADERS ENDS
 

 

DOS文件头的 e_lfanew字段(文件头偏移 0x003C)的值就是PE文件头相对于文

件头的偏移值。 

现在让我们从上图找出e_lfanew字段的数值,它的地址就是0x0000003C。方法是从最左边找到地址 00000030h 这一

行与图中最上边C这一列的交界点,这就是地址0x0000003C,也就是e_lfanew字段的第一个

字节。我们看到 e_lfanew = 0x000000d0 ,这表明PE文件头的地址等于文件头的地址加 0x000000d0 。看看

0x000000d0 这个地址有什么东西,嗯,0x00004550 正是PE文件标识"PE"。

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值