03 PE头属性

首先,我们来看一下PE头的结构体,如下:

typedef struct _IMAGE_NT_HEADERS {
0x00h      DWORD Signature;	//PE标识
0x04h      IMAGE_FILE_HEADER FileHeader;//标准PE头
0x18h      IMAGE_OPTIONAL_HEADER32 OptionalHeader;//扩展PE头
 } IMAGE_NT_HEADERS32,*PIMAGE_NT_HEADERS32;

PE标识:这4个字节的值不能改也不能删,操作系统在启动一个程序时会检测这个值;
标准PE头结构体如下:

typedef struct _IMAGE_FILE_HEADER {
0x04h     WORD Machine;//可执行文件的目标CPU类型
0x06h     WORD NumberOfSections;	//节数目(紧跟在PE头后面)
0x08h     DWORD TimeDateStamp;//编译器编译时间(1970年以来GMT时间	//计算的秒数)
0x0Ch    DWORD PointerToSymbolTable;	//指向符号表(用于调试)
0x10h    DWORD NumberOfSymbols;	//符号表中的符号数量(用于调试)
0x14h    WORD SizeOfOptionalHeader;	//可扩展头大小(紧跟在文件头后,32位系				//统一般为00E0h,64为一般为00F0h)
0x16h    WORD Characteristics;		//文件属性
    } IMAGE_FILE_HEADER,*PIMAGE_FILE_HEADER;

下面我们用Winhex随便打开一个程序来观察一下标准PE头部20个字节,如下图:
在这里插入图片描述
Machine属性:可执行文件的目标CPU类型,此值为0x0时表示能在任意平台下运行,为0x14C时表示可以在Intel 386及后续平台上运行,为0x8664时表示能在X64平台上运行,图中这个程序能在Intel 386及后续平台上运行;我们可以从Windows目录下的System32和SysWOW64目录下分别将64位和32位的notepad.exe用Winhex打开观察此属性,注意64位的notepad.exe放在System32目录下。如下图:
在这里插入图片描述
在这里插入图片描述
NumberOfSections属性:表示当前PE文件中有多少个节,即我们前几篇中提到的节数据。
TimeDateStamp属性:记录了编译器编译的时间,跟平时右键属性中的创建事件和修改时间无关。我们可以做以下实验,先看以下我们的32位notepad.exe文件的属性相关时间,然后修改这个属性,保存后重新查看属性,来验证其是否有关系。未修改前如下图:
在这里插入图片描述
修改属性:
在这里插入图片描述
修改后:
在这里插入图片描述
发现并没有变化。
SizeOfOptionalHeader属性:我们可以看第一张图的32位程序,
其值为0xE0;
Characteristics属性:用于记录当前可执行程序的属性,其值需要对照下图做解析:
在这里插入图片描述
如图是我们的notepad.exe文件该字段的值为:0x0102,转换为二进制则是:
0000 0001 0000 0010从右往左分别对应0~15位,则这个值得第1位和第8位为1,根据上图我们就知道这个文件是可执行且只能在32位平台上运行的。
在这里插入图片描述

接下来我们看一下扩展PE头结构体,如下:

typedef struct _IMAGE_OPTIONAL_HEADER {
0x18h      WORD Magic;//标志字,值0x10B为32位程序,0x20B64位程序(重要)
//一下五个字段了解
0x1Ah      BYTE MajorLinkerVersion;	//连接程序主版本号
0x1Bh      BYTE MinorLinkerVersion;	//连接程序福版本号
0x1Ch      DWORD SizeOfCode;	//所有代码区块的总大小
0x20h      DWORD SizeOfInitializedData;//所有已初始化数据的总大小
0x24h      DWORD SizeOfUninitializedData;//所有未初始化数据的总大小

0x28h      DWORD AddressOfEntryPoint;//程序执行入口RVA(重要)
0x2Ch      DWORD BaseOfCode;//代码区块起始RVA
0x30h      DWORD BaseOfData;	//数据区块起始RVA
//以下属于NT结构增加的领域
0x34h      DWORD ImageBase;	//程序首选装载地址(重要)
0x38h      DWORD SectionAlignment;//内存中区块的对齐值大小(重要)
0x3Ch      DWORD FileAlignment;		//文件中区块的对齐值大小(重要)
0x40h      WORD MajorOperatingSystemVersion;//要求操作系统最低主版本号
0x42h      WORD MinorOperatingSystemVersion;//要求操作系统的最低福版本号
0x44h      WORD MajorImageVersion;//镜像主版本号
0x46h      WORD MinorImageVersion;//镜像福版本号
0x48h      WORD MajorSubsystemVersion;//最低子系统主版本号
0x4Ah      WORD MinorSubsystemVersion;//最低子系统福版本号
0x4Ch      DWORD Win32VersionValue;//保留,必须为0(没有被病毒感染时)
0x50h      DWORD SizeOfImage;//映像装入内存的总尺寸(内存对齐的倍数)(重要)
0x54h      DWORD SizeOfHeaders;//所有头加区块表的大小(文件对齐值得整数倍)(重要)
0x58h      DWORD CheckSum;//映像校验和(重要)
0x5Ch      WORD Subsystem;	//子系统,驱动程序(1),图形界面(2),控制台(3)
0x5Eh	   WORD DllCharacteristics;	//文件属性,不只针对DLL
0x60h      DWORD SizeOfStackReserve;//初始化时栈的大小
0x64h      DWORD SizeOfStackCommit; //初始化时实际提交栈的大小
0x68h      DWORD SizeOfHeapReserve; //初始化时保留的堆大小
0x6Ch      DWORD SizeOfHeapCommit; //初始化时实际提交栈的大小
0x70h      DWORD LoaderFlags;	//与调试有关,默认为0
0x74h      DWORD NumberOfRvaAndSizes;//下边数据目录的项数(重要一般为0x10)
0x78h      IMAGE_DATA_DIRECTORY (重要)DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];//数据目录表
    } IMAGE_OPTIONAL_HEADER32,*PIMAGE_OPTIONAL_HEADER32;

Magic:上面我们用文件属性位来判断当前文件是32位还是64位并不是太准确,这个字段才是判断程序时否是32位程序最准确的字段,值0x10B为32位程序,0x20B为64位程序;
ImageBase:表示当前PE文件在执行时在虚拟地址的什么地方开始展开,实际加载进内存中的值不一定跟这个字段值一直。
AddressOfEntryPoint:这个字段比较有用,表示程序开始执行的时候从哪里开始执行,一定要配合ImageBase字段使用,这个值是相对于ImageBase开始偏移的。
SizeOfImage:展开后的PE文件在内存中占多大由这个值决定;
CheckSum:操作系统用来判断当前的可执行程序有没有被人给改掉,以两个字节为单位相加,结果在加上文件的长度。
DllCharacteristics:此字段拆分后查如下图所示的表;
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/lifeshave/article/details/86496062
03