• 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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    请添加图片描述

    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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    typedef struct _IMAGE_NT_HEADERS {
        DWORD Signature;
        IMAGE_FILE_HEADER FileHeader;
        IMAGE_OPTIONAL_HEADER32 OptionalHeader;
    } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    标识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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    扩展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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    节表

    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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  • 相关阅读:
    探索云原生数据库技术:构建高效可靠的云原生应用
    java毕业设计音乐社交平台设计Mybatis+系统+数据库+调试部署
    windows域KCC知识点
    java读取服务器数据包并下载至本地目录
    2022买护眼灯到底有没有用?双十二学生护眼灯该怎么选择
    Debian linux系统更换apt源
    MySQL_06:多表查询
    【软考】9.5 排序算法原理
    【2023,学点儿新Java-11】基础案例练习:输出个人基础信息、输出心形 | Java中 制表符\t 和 换行符\n 的简单练习
    kafka第三课-可视化工具、生产环境问题总结以及性能优化
  • 原文地址:https://blog.csdn.net/xf555er/article/details/126210070