PE结构详解(加壳脱壳必备知识)

        近期太忙一直没有抽出时间来更新文章,周末抽空写一篇关于PE结构相关知识,PE结构是windows下的可执行文件的标准结构。可执行文件的装载、内存分步、执行等都依赖于PE结构。如果要掌握反病毒、免杀、权益保护、反调试、加壳脱壳等相关知识,那了解PE结构则是重中之重。

一、PE结构概述

PE文件大致可以分为两部分,即数据管理结构及数据部分。数据管理结构包含:DOS头、PE头、节表。数据部分包括节表数据(节表数据是包含着代码、数据等内容)。详情见下图:

1.DOS头

DOS头分为两个部分,分别是MZ头及DOS存根,MZ头是真正的DOS头部,它的结构被定义为IMAGE_DOS_HEADER。DOS存根是一段简单程序,主要是用于兼容DOS程序,当不兼容DOS程序时,输出:"this program cannot be run in DOS mode"。

2.PE头

PE头分为三个部分,分别是PE标识(IMAGE_NT_SIGNATRUE)、文件头(IMAGE_FILE_HEADER)、可选头(IMAHE_OPTION_HEADER)。PE头是固定不变的,位于DOS头部中e_ifanew字段指出位置。

3.节表

程序中组织按照不同属性存在不同的节中,如果PE中文件头的NumberOfSections值中有N个节,那么节表就是由N个节表(IMAGE_SECTION_HEADER)组成。节表主要是存储了何种借的属性、文件位置、内存位置等。位置紧跟PE头后。

4.节表数据

PE文件真正程序部分的存储位置,有几个节表就有几个节表数据,根据节表的属性、地址等信息,程序的程序就分布在节表的指定位置。位置紧跟节表后。

二、通过代码进行详解

我本地编写了简单的"hello word"的代码。运行程序弹出"hello word"提示框。

2.1基础环境介绍

具体代码如下图:

2.2 DOS头介绍

这时我们通过c32asm查看该程序的二进制文件,详情见下图。

其中 5A 4D 十六进制为MZ。(系统使用的是小尾存储方式,所以需要倒序)。F8 00是DOS头部的e_ifanew字段存储的值。所以PE开头位置位于上图箭头标示处,具体DOS头部代码定义,请见下图(位于winnt.h头文件下)。

其中的DOS存根就位于两者之间,见下图:

DOS存根部分经常由于各种需要而保存其它数据,因此可以进行填充,填充内容你可以自己想象啦。

2.3 PE头介绍

PE在结构概述中,我们讲到,PE头分为三个部分,分别是PE标识(IMAGE_NT_SIGNATRUE)、文件头(IMAGE_FILE_HEADER)、可选头(IMAHE_OPTION_HEADER)。PE标识占4个字节,文件头占20个字节,可选头的大小由文件头的SizeOfOptionalHeader的值来确定。

PE标识见下图:

文件头标识见下图:

其中 machine字段的值为 4c 01,其代表可执行文件的目标CPU类型。

014c:intel;0184:DEC Alpha;0200:inter(64-bit);0284: DEC Alpha(64-bit)

characteristics字段的值为0201即 0x0102,该值表示文件运行的目标为32位平台。

具体不过多介绍啦,有兴趣的小伙伴自行查找吧~

可选头标识见下图:

由于可选头大小由SizeOfOptionalHeader存储的值确定,所以可选头大小为 0x00E0(十进制为224),具体大小见下图:

可选头是文件头的补充,主要用来管理PE文件被操作系统装载时所需的信息。

2.4节表介绍

PE->可选头结束后,即为节表个数由PE中文件头的NumberOfSections值中有N个节。本程序中NumberOfSections值为9个,如下图:

每个节表(IMAGE_SECTION_HEADER) 40个字节,所以总节表共9*40=360个字节。

name字段节名的长度为8个字节,多余会被截取,本示例中2E 74 65 78 74 000000为".text",见下图 。

黑客入口点通常在第一节区。

.text:V偏移:0x00001001;V大小:00004af0; R大小:0000 c400;R偏移;00000400;

.text段是代码段

.data段是数据段。

bss段是全局变量数据段。

节表具体结构如下图:

Name[IMAGE_SIZEOF_SHORT_NAME]; // 节表名称,如“.text”

PhysicalAddress; // 物理地址

VirtualSize; // 真实长度

VirtualAddress; // 节区的 RVA 地址

SizeOfRawData; // 在文件中对齐后的尺寸

PointerToRawData; // 在文件中的偏移量

PointerToRelocations; // 在OBJ文件中使用,重定位的偏移

PointerToLinenumbers; // 行号表的偏移(供调试使用地)

NumberOfRelocations; // 在OBJ文件中使用,重定位项数目

NumberOfLinenumbers; // 行号表中行号的数目

Characteristics; // 节属性如可读,可写,可执行等

关于PE结构对的三种存储地址 VA;RVA;FILEOFFSET,以及如何进行定位我们下篇进行详细介绍。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章