PE文件格式分析

PE(Portable Execute)文件是Windows下可执行文件的总称,常见的有DLL,EXE,OCX,SYS等,事实上,一个文件是否是PE文件与其扩展名无关,PE文件可以是任何扩展名。
PE文件主要分为以下几种:

种类主扩展名
可执行系列.exe .scr
库系列.dll .ocx .cpl .drv
驱动程序系列.sys .vxd
对象文件系列.obj

首先来看一下PE文件的基本结构
在这里插入图片描述

DOS头

typedef struct _IMAGE_DOS_HEADER {
    WORD e_magic;       // 魔术数字					
    WORD e_cblp;        // 文件最后页的字节数
    WORD e_cp;          // 文件页数
    WORD e_crlc;        // 重定义元素个数
    WORD e_cparhdr;     // 头部尺寸,以段落为单位
    WORD e_minalloc;    // 所需的最小附加段
    WORD e_maxalloc;    // 所需的最大附加段
    WORD e_ss;          // 初始的SS值(相对偏移量)
    WORD e_sp;          // 初始的SP值
    WORD e_csum;        // 校验和
    WORD e_ip;          // 初始的IP值
    WORD e_cs;          // 初始的CS值(相对偏移量)
    WORD e_lfarlc;      // 重分配表文件地址
    WORD e_ovno;        // 覆盖号
    WORD e_res[4];      // 保留字
    WORD e_oemid;       // OEM标识符(相对e_oeminfo)
    WORD e_oeminfo;     // OEM信息
    WORD e_res2[10];    // 保留字
    LONG e_lfanew;      // 新exe头部的文件地址
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
//注:该结构中只有两个重要的成员变量,分别是e_magic和e_lfanew。

NT头包含标志位DWORD Signature和标准PE头以及可选PE头,DOS头与标准PE头字节固定,可选PE头字节不固定

typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;          //4个字节的PE标志,通常设置成00004550h,其ASCII码为PE00,这个字段是PE文件头的开始 
    IMAGE_FILE_HEADER FileHeader;      //文件头
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;//可选头
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

标准PE头

typedef struct _IMAGE_FILE_HEADER {
    WORD    Machine;            //程序运行的CPU型号,作用是区别这个exe是哪个CPU可以跑的.重要.
    WORD    NumberOfSections;      //节的数量  (可以理解为汇编中区的个数)现在我们有两个,一个.rdata 一个.text
    DWORD   TimeDateStamp;        //时间戳,文件的创建时间  --程序的编译时间,参考用,没有实际作用
    //DWORD   PointerToSymbolTable;   //符号表地址  我们使用的PDB文件(里面有函数吗什么的)都存放在这个表中,不过微软是单独生成的PDB文件,所以这个字段没用,主要是给别人用
    //DWORD   NumberOfSymbols;      //符号表大小
    WORD    SizeOfOptionalHeader;   //可选头大小,这个字段很重要.因为要通过这个字段,才知道可选头是多大,而不懂PE的人求选项头都是用sizeof()求出来的.所以真正的选项头大小要靠这个字段
    WORD    Characteristics;    //文件属性,描述文件信息的,每个位有不同含义,可执行文件值为10F,即第0 1 2 3 8位置1
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

可选PE头

typedef struct _IMAGE_OPTIONAL_HEADER {
    WORD    Magic;                  /*机器型号,判断是PE是32位:10B还是64位:20B*/
    //BYTE    MajorLinkerVersion;          /*连接器版本号高版本*/
    //BYTE    MinorLinkerVersion;          /*连接器版本号低版本,组合起来就是 5.12 其中5是高版本,C是低版本*/
    DWORD   SizeOfCode;           //代码节的总大小(512为一个磁盘扇区),必须是FileAlignment整数倍      没用
    DWORD   SizeOfInitializedData;      //初始化数据的节的总大小,也就是.data必须是FileAlignment整数倍	 没用
    DWORD   SizeOfUninitializedData;    //未初始化数据的节的大小,也就是 .data ?必须是FileAlignment整数倍  没用
    DWORD   AddressOfEntryPoint;      //程序执行入口(OEP) RVA(相对偏移)       					   重要
    DWORD   BaseOfCode;            //代码的节的起始RVA(相对偏移)也就是代码区的偏移,偏移+模块首地址定位代码区
    DWORD   BaseOfData;               //数据结的起始偏移(RVA),同上						      没用
    DWORD   ImageBase;          //内存镜像基址,程序在内存中执行时的加载基址  																					内存中的程序入口地址一般都是OEP的值加上这个地址的值     最重要

    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映尺寸),可以比实际值大,必须是SectionAlignment整数倍 重要
    DWORD   SizeOfHeaders;   //所有头(头的结构体大小)+节表的大小,严格按照FileAlignment对齐					重要
    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;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值