PE文件介绍 (2)-DOS头,DOS存根,NT头

PE头

PE头由许多结构体组成,现在开始逐一学习各结构体

0X00 DOS头

微软创建PE文件格式时,人们正广泛使用DOS文件,所以微软充分考虑了PE文件对DOS文件的兼容性。其结果是在PE头的最前面添加一个 IMAGE_DOS_HEADER 结构体用来扩展DOSEXE头

IMAGE_DOS_HEADER

typedef struct _IMAGE_DOS_HEADER
{
     WORD e_magic;  //DOS签名 4D5A
     WORD e_cblp;
     WORD e_cp;
     WORD e_crlc;
     WORD e_cparhdr;
     WORD e_minalloc;
     WORD e_maxalloc;
     WORD e_ss;
     WORD e_sp;
     WORD e_csum;
     WORD e_ip;
     WORD e_cs;
     WORD e_lfarlc;
     WORD e_ovno;
     WORD e_res[4];
     WORD e_oemid;
     WORD e_oeminfo;
     WORD e_res2[10];
     LONG e_lfanew;   //指向NT头所在的位置
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

IMAGE_DOS_HEADER 结构体的大小位64字节,一个WORD类型两个字节时一个字,一个LONG类型是四个字节两个字,所以该结构体为 30个WORD类型+ 1个LONG类型 为 64字节。

在该结构体中必须知道2个重要的成员:e_magice_lfanew

  • e_magic: DOS签名(4D5A => ASCLL值 “MZ”)
  • e_lfanew: 指示NT头的偏移(不同的文件该值不一样)

0X01 使用Hxd在电脑中查看PE格式

把炉石传说的客户端放入Hxd软件中查看

alt DOS头截图

从图中可以看出标黄的是DOS签名4D5A为MZ,整个红框为 DOS头64个字节,最底下绿色框标出来的为NT文件头所在位置 0X00000120 Intel系列CPU以逆序存储数据,这称为小端序标识法。这些是值被修改后将不能够运行(根据PE规范,它以不再是PE文件)。

0X02 DOS存根

DOS存根在DOS头下面,是个可选项,且大小不固定(即使没有DOS存根,文件也能正常运行)DOS存根由代码与数据混合而成下图为炉石传说的客户端的DOS存根

alt DOS存根截图

DOS存根的大小不固定,从0x40开始到NT头截至。图中文件偏移40-4D区域为16位汇编指令。32位windows OS中直接忽略该命令。

0X03 NT头

下面介绍NT头 IMAGE_NT_HEADERS

代码:IMAGE_NT_HEADERS

typedef struct _IMAGE_NT_HEADERS {
  DWORD                   Signature;         //PE签名 504500 => ("PE"00)
  IMAGE_FILE_HEADER       FileHeader;        //文件头
  IMAGE_OPTIONAL_HEADER32 OptionalHeader;    //可选文件头
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

IMAGE_NT_HEADERS 结构体由三个成员组成,第一个成员为签名(Signature)结构体,其值为50450000h("PE"00)。另外两个成员分别为文件头与可选头。

在hxd中查看NT头

alt NT头

从图上可以看出DOS头的最后一个结构是指向NT头的0X0120,0X0120的前4个字节存储的是签名。

IMAGE_NT_HEADERS结构体的大小为F8,相当大。下面分别说明文件头和可选头结构体。

0X030 NT头:文件头

文件头是NT头第二个结构,文件头是表现文件大致属性的 IMAGE_FILE_HEADER

代码:IMAGE_FILE_HEADER

typedef struct _IMAGE_FILE_HEADER {
  WORD  Machine;
  WORD  NumberOfSections;
  DWORD TimeDateStamp;
  DWORD PointerToSymbolTable;
  DWORD NumberOfSymbols;
  WORD  SizeOfOptionalHeader;
  WORD  Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

IMAGE_FILE_HEADER 结构体中有一下四种重要成员(若它们设置不正确,将导致文件无法运行)。

(1) Machine

每个CPU都拥有唯一的Machine码,兼容32位Intel x86芯片的Machine码为14C.
是定义在winnt.h文件中的Machine码。

(2) NumberOfSections

PE文件把代码,数据,资源等依据属性分类到各节区中存储。NumberOfSections用来指出文件中存在的节区数量。该值一定要大于0,且当定义的节区数量和实际节区不同时,将发生运行错误。
(3) SizeOfOptionalHeader
   IMAGE_NT_HEADERS 结构体的最后一个成员为 IMAGE_OPTIONAL_HEADER32 结构体。SizeOfOptionalHeader 成员用来指出IMAGE_OPTIONAL_HEADER32 结构体的长度。IMAGE_OPTIONAL_HEADER32 结构体由C语言编写而成,故其大小已经确定。但是windows的PE装载器需要查看 IMAGE_NT_HEADERSSizeOfOptionalHeader值,从而识别出IMAGE_OPTIONAL_HEADER32 结构体的大小。
   PE32+格式的文件中使用的是IMAGE_OPTIONAL_HEADER64 结构体,而不是IMAGE_OPTIONAL_HEADER32 结构体。2个结构体尺寸是不同的,所以需要在SizeOfOptionalHeader 成员中指明结构体的大小。

(4) Characteristics

   该字段用于标识文件的属性,文件是否是可运行的形态,是否为DLL文件等信息,以二进制位的方式进行组合。

以下是定义在winnt.h文件中的Characteristics值

Macro Value Meaning
IMAGE_FILE_RELOCS_STRIPPED 0x0001 Relocation information was stripped from the file. The file must be loaded at its preferred base address. If the base address is not available, the loader reports an error.
IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 The file is executable (there are no unresolved external references).
IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 COFF line numbers were stripped from the file.
IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 COFF symbol table entries were stripped from file.
IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 Aggressively trim the working set. This value is obsolete.
IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 The application can handle addresses larger than 2 GB.
IMAGE_FILE_BYTES_REVERSED_LO 0x0080 The bytes of the word are reversed. This flag is obsolete.
IMAGE_FILE_32BIT_MACHINE 0x0100 The computer supports 32-bit words.
IMAGE_FILE_DEBUG_STRIPPED 0x0200 Debugging information was removed and stored separately in another file.
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 If the image is on removable media, copy it to and run it from the swap file.
IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 If the image is on the network, copy it to and run it from the swap file.
IMAGE_FILE_SYSTEM 0x1000 The image is a system file.
IMAGE_FILE_DLL 0x2000 The image is a DLL file. While it is an executable file, it cannot be run directly.
IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 The file should be run only on a uniprocessor computer.
IMAGE_FILE_BYTES_REVERSED_HI 0x8000 The bytes of the word are reversed. This flag is obsolete.

  另外,PE文件中Characteristics的值有可能不是002h吗(不可执行)?也是有可能的,比如类似*.obj的object文件及resource DLL文件等。

(5) TimeDateStamp

该成员的值不影响文件运行,用来记录编译器创建此文件的时间。有些开发工具(VB,VC++)提供了设置该值的工具。而有些开发工具(Delphi)未提供。

0X031 NT头:使用hxd查看炉石传说客户端文件头

alt NT头-文件头

文件头有 四个 WORD 型和三个DWORD型组成 42+34=20 一共占了20个字节
从图上可以看出:

名称 位置(偏移量) 数据值 含义
machine码 0x0124 014C Interl 386
NumberOfSections 0x0126 0005 存在5个节区
TimeDateStamp 0x0128 5B89C5B2 2018/08/31 22:48:18
SizeOfOptionalHeader 0x0134 00E0 IMAGE_OPTIONAL_HEADER32的大小为E0
Characteristics 0X0136 0x0102 是32位的文件 and 是可执行文件

最后一个数值 0x0102 可以看作是 0x100 | 0x002 为 IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_32BIT_MACHINE

原文地址:https://www.cnblogs.com/mhpcuit/p/12435695.html