PE结构学习(2)_PE结构的组成

PE结构的组成

PE结构概述图

由下图可得,PE文件主要分为四部分,分别有DOS部分、PE文件头、节表以及节数据

请添加图片描述


DOS部分

DOS MZ文件头

DOS文件头结构体代码一共有64字节,最后一个成员指向pe头

在以下结构体代码中的成员只需记住两个,最开始的和最末尾的成员

e_magic和e_lfanew是构成PE指纹的重要成员,不能被修改

typedef struct _IMAGE_DOS_HEADER {      
    WORD   e_magic;                     //通常为"MZ"
    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;                    // 指向PE头的指针
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

请添加图片描述

DOS块

又称DOS Sub, 其大小不确定, 可以随意填充垃圾数据或者恶意代码


PE文件头(NT头)

PE头又分为标识PE头、标准PE头、扩展PE头

PE文件一些重要信息通常存储在标准PE头和扩展PE头中

如以下代码所示PE文件头结构体,分别是32位与64位的

typedef struct _IMAGE_NT_HEADERS64 {
    DWORD Signature;  //标识PE头,占2字节
    IMAGE_FILE_HEADER FileHeader;  //标准PE头,占20字节
    IMAGE_OPTIONAL_HEADER64 OptionalHeader;  //扩展PE头,占224字节
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;
typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

标识PE头

标识PE头占2个字节,且不能被修改
请添加图片描述

标准PE头

标准PE头占20个字节,其结构体如下代码所示

typedef struct _IMAGE_FILE_HEADER {
  	WORD    Machine;  //决定能运行在什么样的cpu上,若值为0则表示能任意cpu运行;值为14C表示能在intel386及后续版本;值为8664能运行在x64cpu上。因此可以用来判断程序是32位还是64位的
    
    WORD    NumberOfSections;  //表示当前节的数量
    
    DWORD   TimeDateStamp;  //编译器填写的时间戳,与文件创建或修改时间无关
    
    DWORD   PointerToSymbolTable;  //与调试相关
    
    DWORD   NumberOfSymbols;  //与调试相关
    
    WORD    SizeOfOptionalHeader; //扩展PE头的大小,一般32位为E0,64位为F0
    
    WORD    Characteristics;  //文件属性
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

扩展PE头

扩展PE头占224个字节

以下结构体成员中有几个成员要重点注意

如果一个可执行文件它的dos部分+pe头+节表的共同大小为332,其FileAlignment(文件对齐)的值为200, 那么SizeOfHeaders的值应该为文件对齐的整数倍,所以SizeOfHeaders的值为400

#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
typedef struct _IMAGE_OPTIONAL_HEADER {
    WORD    Magic;  //32位的值为10B,64位的值为20B
    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;  //内存中整个PE文件映射的尺寸,可比实际值大,必须是内存对齐的整数倍
    DWORD   SizeOfHeaders;   //所有头+节表按照文件对齐后的大小,否则加载会出错
    DWORD   CheckSum;  //校验和,用来判断文件是否被修改
    WORD    Subsystem;  //子系统 驱动程序(1) 图形界面(2) 控制台或dll(3)
    WORD    DllCharacteristics;  //文件特效,并非针对dll文件 
    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;

节表

PE文件中所有节的属性都定义在节表里面

节表是由一系列IMAGE_SECTION_HEADER结构的元素组成的结构体数组, 每个元素占40个字节

以下是IMAGE_SECTION_HEADER结构体代码

#define IMAGE_SIZEOF_SHORT_NAME  8
typedef struct _IMAGE_SECTION_HEADER {
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME]; //ASCII字符串,当前节的名字
    union {
            DWORD   PhysicalAddress;  
            DWORD   VirtualSize;
    } Misc; //当前节实际的大小(内存未对齐)
    DWORD   VirtualAddress;  //节在内存中的偏移地址(真正的地址需加上Imagebase)
    DWORD   SizeOfRawData;  //节在文件对齐后的大小
    DWORD   PointerToRawData;  //节在文件中的偏移地址
    DWORD   PointerToRelocations;
    DWORD   PointerToLinenumbers;
    WORD    NumberOfRelocations;
    WORD    NumberOfLinenumbers;
    DWORD   Characteristics;  //节的属性,涉及到此节是否可读可写可执行
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值