• PE文件头入门


    PE文件

    首先需要知道DOS头,其其数据结构不太需要知道,但需要知道其中的两个和偏移

    e_magic    WORD    ;0000h exe标志,"MZ"头
    e_lfanew    DWORD    003ch  "PE"头的偏移地址
    整个数据结构大小为40h

    这里我们随便找一个.exe程序为例

    找到了e_flanew后就可以去找PE头,其头有一个标识,且占4字节,其值也是"PE"的ascii,以两个0结尾"PE"

    PE标志后面接着就是IMAGE_FILE_HEADER(PE标准头),其结构大小为14h,加上标记,就是18h

    IMAGE_FILE_HEADER
        Machine    WORD    004h
        SizeOfSection    WORD    006h    PE中节的数量
        TimeDateStamp    DWORD    008h 文件创建日期
        PointerToSymbolTable    DWORD    00ch 指向符号表的指针
        NumberOfSymbols    DWORD    010h 符号表中符号个数
        SizeOfOptionalHeader    WORD    014h 扩展PE头的长度
        Characteristics    WORD    016h 文件属性

    也就是一下部分

     跟在其后面的是PE扩展头

    PE扩展头大小不一定,但可以通过PE标准头的成员SizeOfOptionHeader来获取PE扩展头的大小

    typedef struct _IMAGE_OPTIONAL_HEADER {

    WORD Magic;                  /*机器型号,判断是PE是32位还是64位*/
    BYTE MajorLinkerVersion;          /*连接器版本号高版本*/
    BYTE MinorLinkerVersion;          /*连接器版本号低版本,组合起来就是 5.12 其中5是高版本,C是低版本*/
    DWORD SizeOfCode;               /*代码节的总大小(512为一个磁盘扇区)*/
    DWORD SizeOfInitializedData;        /*初始化数据的节的总大小,也就是.data*/
    DWORD SizeOfUninitializedData;       /*未初始化数据的节的大小,也就是 .data ? */
    DWORD AddressOfEntryPoint;         /*程序执行入口(OEP) RVA(相对偏移)*/
    DWORD BaseOfCode;               /*代码的节的起始RVA(相对偏移)也就是代码区的偏移,偏移+模块首地址定位代码区*/
    DWORD BaseOfData;               /*数据结的起始偏移(RVA),同上*/
    DWORD ImageBase;               /*程序的建议模块基址(意思就是说作参考用的,模块地址在哪里)*/
    DWORD SectionAlignment;           /*内存中的节对齐*/
    DWORD FileAlignment;             /*文件中的节对齐*/
    WORD MajorOperatingSystemVersion;    /*操作系统版本号高位*/
    WORD MinorOperatingSystemVersion;    /*操作系统版本号低位*/
    WORD MajorImageVersion;          /*PE版本号高位*/
    WORD MinorImageVersion;          /*PE版本号低位*/
    WORD MajorSubsystemVersion;        /*子系统版本号高位*/
    WORD MinorSubsystemVersion;        /*子系统版本号低位*/
    DWORD Win32VersionValue;          /*32位系统版本号值,注意只能修改为4 5 6表示操作系统支持nt4.0 以上,5的话依次类推*/
    DWORD SizeOfImage;             /*整个程序在内存中占用的空间(PE映尺寸)*/
    DWORD SizeOfHeaders;            /*所有头(头的结构体大小)+节表的大小*/
    DWORD CheckSum;               /*校验和,对于驱动程序,可能会使用*/
    WORD Subsystem;              /*文件的子系统 :重要*/
    WORD DllCharacteristics;         /*DLL文件属性,也可以成为特性,可能DLL文件可以当做驱动程序使用*/
    DWORD SizeOfStackReserve;        /*预留的栈的大小*/
    DWORD SizeOfStackCommit;         /*立即申请的栈的大小(分页为单位)*/
    DWORD SizeOfHeapReserve;        /*预留的堆空间大小*/
    DWORD SizeOfHeapCommit;         /*立即申请的堆的空间的大小*/
    DWORD LoaderFlags;            /*与调试有关*/
    DWORD NumberOfRvaAndSizes;       /*下面的成员,数据目录结构的项目数量*/
    IMAGE_DATA_DIRECTORY DataDirectory[16];/*数据目录,默认16个,16是宏,这里方便直接写成16*/
    } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

     在扩展头里,最后一个成员为数据目录项

    其结构为

    typedef struct _IMAGE_DATA_DIRECTORY {
        DWORD   VirtualAddress;        虚拟地址(表格位置)
        DWORD   Size;              大小
    } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

    其成员为

    #define IMAGE_DIRECTORY_ENTRY_EXPORT          0   // Export Directory
    #define IMAGE_DIRECTORY_ENTRY_IMPORT          1   // Import Directory
    #define IMAGE_DIRECTORY_ENTRY_RESOURCE        2   // Resource Directory
    #define IMAGE_DIRECTORY_ENTRY_EXCEPTION       3   // Exception Directory
    #define IMAGE_DIRECTORY_ENTRY_SECURITY        4   // Security Directory
    #define IMAGE_DIRECTORY_ENTRY_BASERELOC       5   // Base Relocation Table
    #define IMAGE_DIRECTORY_ENTRY_DEBUG           6   // Debug Directory
    //      IMAGE_DIRECTORY_ENTRY_COPYRIGHT       7   // (X86 usage)
    #define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE    7   // Architecture Specific Data
    #define IMAGE_DIRECTORY_ENTRY_GLOBALPTR       8   // RVA of GP
    #define IMAGE_DIRECTORY_ENTRY_TLS             9   // TLS Directory
    #define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG    10   // Load Configuration Directory
    #define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT   11   // Bound Import Directory in headers
    #define IMAGE_DIRECTORY_ENTRY_IAT            12   // Import Address Table
    #define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT   13   // Delay Load Import Descriptors
    #define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14   // COM Runtime descriptor

    PE扩展头后面便是节表

    typedef struct _IMAGE_SECTION_HEADER {
        BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];  /*节区的名字*/
        union {
                DWORD   PhysicalAddress;
                DWORD   VirtualSize;        /*节区的尺寸*/
        } Misc;
        DWORD   VirtualAddress;          /*虚拟地址 节区的RVA地址(偏移)*/
        DWORD   SizeOfRawData;           /*在文件中对齐的尺寸*/
        DWORD   PointerToRawData;         /*在文件中的偏移*/
        DWORD   PointerToRelocations;      /*在OBJ文件中使用*/
        DWORD   PointerToLinenumbers;      /*行号表位置,调试使用*/
        WORD    NumberOfRelocations;      /*在OBJ文件中使用*/
        WORD    NumberOfLinenumbers;      /*行号表的数量*/
        DWORD   Characteristics;        /*节的属性*/
    } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
  • 相关阅读:
    Linux 进程间通信(包含一个经典的生产者消费者实例代码)
    Linux多进程编程实例
    web开发中的mysql使用
    Linux 网络编程中的read和write函数正确的使用方式
    Linux 使用tcpdump观察arp通信过程
    Linux 开启echo等服务
    Linux send和recv
    自己动手写http服务器——主程序(三)
    自己动手写http服务器——线程池(一)
    http请求报文格式和响应报文格式
  • 原文地址:https://www.cnblogs.com/pppyyyzzz/p/13204071.html
Copyright © 2020-2023  润新知