浅谈PE文件结构(一)

0x00 前言

​ 了解一个程序的结构在逆向过程中是非常重要的,虽然也有很多工具可以直接读取到PE文件的结构,但是作为一个有信仰的逆向学习者,个人认为有必要从根本上去理解,所以今天就结合一个简单的32位.exe程序配合WinHex浅浅分析一下PE文件结构,将会将文章分为多篇对PE文件结构进行分析,第一篇主要对PE文件的整体结构和DOS头进行剖析。

0x01 PE文件结构概述

​ PE文件可以大概分为:DOS头、NT头、节表、.idata段、.text段、.data段,本文将一一对其进行分析。

​ 结构示意图如下:
在这里插入图片描述

0x02 DOS头

​ DOS头的字段有

IMAGE_DOS_HEADER 
typedef struct _IMAE_DOS_HEADER {		
	WORD e_magic;	    //2					                
	WORD e_cblp;        //2                  
	WORD e_cp;          //2                  
	WORD e_crlc;        //2                                  
	WORD e_cparhdr;		//2				      
	WORD e_minalloc;    //2               
	WORD e_maxalloc;	//2				
	WORD e_ss;          //2              
	WORD e_sp;			//2				
	WORD e_csum;		//2				
	WORD e_ip;			//2				
	WORD e_cs;			//2				
	WORD e_lfarlc;		//2			
	WORD e_ovno;		//2				
	WORD e_res[4];		//2				
	WORD e_oemid;		//2				
	WORD e_oeminfo;		//2				
	WORD e_res2[10];	//2				
	LONG e_lfanew;		//4				
} IMAGE_DOS-HEADER, *PIMAGE_DOS_HEADER;

​ 共占据64个字节,结合WinHex查看如下图所示:

在这里插入图片描述

​ 图中标记的位置即整个DOS头的内容,我们依次按字段进行分析:

  • e_magic:0x00,占两个字节,即4D 5A,是DOS的签名,PE文件的e_magic一般都是MZ(MZ标签是MS-DOS原架构师Mark Zbikowski姓名的首字母缩写)。
  • e_cblp:0x02,占两个字节,即90 00,是文件最后页的字节数,由于win32是小端序,所以这个程序的文件最后页的字节数为0x0090字节。
  • e_cp:0x04,占两个字节,即03 00,是文件的页数,该程序共有0x0003页。
  • e_crlc:0x06,占两个字节,即00 00,是重定义元素个数,即引用第三方链接库、虚拟变量等,该文件重定义元素个数为0。
  • e_cparhdr:0x08,占两个字节,即04 00,参数头大小。
  • e_minalloc:0x0A,占两个字节,即00 00,最小所需附加段大小。
  • e_maxalloc:0x0C,占两个字节,即00 00,最小所需附加段大小。
  • e_ss:0x0E,初始代码段地址。
  • e_sp:0x10,初始栈内存地址。
  • e_csum:0x12,校验和,是对整个PE文件的校验和,如未开启校验和,则该字段为0。
  • e_ip:0x14,初始化EIP指针的地址。
  • e_cs:0x16,初始化CS段的地址。
  • e_lfarlc:0x18,重定向表的文件地址。
  • e_ovno:0x1A,覆盖号。
  • e_res[4]:0x1C,保留字段。
  • e_oemid:0x24,OEM标识符,厂商序列号。
  • e_oeminfo:0x26,OEM信息。
  • e_res2[10]:0x28,保留字段。
  • e_lfanew:0x3C,PE头的偏移地址,该文件的PE头位置在0x0000C0。

​ 其中最重要的DOS头为e_magic和e_lfanew,e_magic是用于确定文件是否为PE文件,e_lfanew的用于确定PE头的位置。

0x03 DOS存根

​ 从地址0x40至0xBF为DOS的存根,该段不会影响PE文件的正常运行。
在这里插入图片描述

0x04 NT头

​ NT头可分为三部分,依次为PE签名,PE文件头以及PE可选头。

在这里插入图片描述

​ NT头的字段如下:

typedef struct _IMAGE_NT_HEADERS {
  DWORD                   Signature;
  IMAGE_FILE_HEADER       FileHeader;
  IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
  • Signature字段为双字型数据,占4个字节,是PE文件的签名。

  • FileHeader字段是PE文件头,以下是FileHeader的字段,后面再展开说明。

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;
  • OptionalHeader字段是PE的可选头,以下是OptionalHeader的字段,后面再展开说明。
typedef struct _IMAGE_OPTIONAL_HEADER {
  WORD                 Magic;
  BYTE                 MajorLinkerVersion;
  BYTE                 MinorLinkerVersion;
  DWORD                SizeOfCode;
  DWORD                SizeOfInitializedData;
  DWORD                SizeOfUninitializedData;
  DWORD                AddressOfEntryPoint;
  DWORD                BaseOfCode;
  DWORD                BaseOfData;
  DWORD                ImageBase;
  DWORD                SectionAlignment;
  DWORD                FileAlignment;
  WORD                 MajorOperatingSystemVersion;
  WORD                 MinorOperatingSystemVersion;
  WORD                 MajorImageVersion;
  WORD                 MinorImageVersion;
  WORD                 MajorSubsystemVersion;
  WORD                 MinorSubsystemVersion;
  DWORD                Win32VersionValue;
  DWORD                SizeOfImage;
  DWORD                SizeOfHeaders;
  DWORD                CheckSum;
  WORD                 Subsystem;
  WORD                 DllCharacteristics;
  DWORD                SizeOfStackReserve;
  DWORD                SizeOfStackCommit;
  DWORD                SizeOfHeapReserve;
  DWORD                SizeOfHeapCommit;
  DWORD                LoaderFlags;
  DWORD                NumberOfRvaAndSizes;
  IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

0x05 节表

​ 节表(SECTION)即区块表,定义了PE文件中所有节的属性,SECTION字段如下,再下篇再展开叙述:

typedef struct _IMAGE_SECTION_HEADER {
  BYTE  Name[IMAGE_SIZEOF_SHORT_NAME];
  union {
    DWORD PhysicalAddress;
    DWORD VirtualSize;
  } Misc;
  DWORD VirtualAddress;
  DWORD SizeOfRawData;
  DWORD PointerToRawData;
  DWORD PointerToRelocations;
  DWORD PointerToLinenumbers;
  WORD  NumberOfRelocations;
  WORD  NumberOfLinenumbers;
  DWORD Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

0x06 结语

​ 也是刚开始学逆向没多久,文章的目的一个是归纳总结学习内容,一个是希望把学到的内容分享出来与志同道合之士一起学习进步,文章中如有错误的地方,请各位师傅批评指正,非常感谢!下篇我会继续对FileHeader、OptionalHeader、.idata段、.text段以及,data段进行逐一分析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值