PE文件格式

目录

介绍

PE文件格式

种类​编辑

基本结构

VA&RVA

PE头

DOS头

NT头:文件头

NT头:文件头

NT头:可选头

目录

介绍

PE文件格式

种类​编辑

基本结构

VA&RVA

PE头

DOS头

NT头:文件头

NT头:文件头

NT头:可选头

节区头



介绍

PE文件是Windows操作系统下使用的可执行文件。PE文件是指32位的可执行文件,也称为PE32。64位的可执行文件称为PE+或者PE32+,是PE文件的一种扩展形式。

PE文件格式

种类

严格的说,OBJ(对象)文件之外的所有文件都是可执行的,DLL,SYS文件等虽然不能直接在shell中运行,但是可以使用其他方法(调试器,服务等)执行。

基本结构

从DOS头(DOS header)到节区头(Section header)是PE头部分,其他的节区合称PE体。文件使用偏移(offset),内存中使用VA(虚拟地址)来表示位置。各节区头定义各节区在文件或内存中的大小,位置,属性。

VA&RVA

VA指的是进程虚拟内存的绝对地址,RVA是相对地址,他们满足关系
RVA+ImageBase=VA.

PE头

DOS头

为了充分考虑PE文件对DOS文件的兼容性,在PE头前面添加了IMAGE_DOS_HEADER结构体,结构如下:

其结构体大小64字节,其中需要知道2个重要成员:

e_magic:DOS签名

e_lfanew:指示NT头的偏移,即真正的PE文件头(不同文件拥有可变值)

 其中e_lfanew的偏移为+3C,如下演示:

可以看到DOS签名和e_lfanew为100h,那查找一下,正好是PE文件头。

NT头:文件头

IMAGE_NT_HEADERS其中第一个成员为签名结构体,值为50450000h(“PE”00),另外两个成员是文件头与可选头。

IMAGE_NT_HEADERS结构体大小为F8

NT头:文件头

如下演示:
其中第一个,第二个,第六个,第七个比较重要,记住。

NT头:可选头

IMAGE_OPTIONAL_HEADER结构

typedef struct _IMAGE_OPTIONAL_HEADER {
+18h    WORD    Magic;                                  //标志字,ROM映像(0107h),普通可执行文件(010Fh)
+1Ah    BYTE    MajorLinkerVersion;            //链接程序的主版本号
+1Bh    BYTE    MinorLinkerVersion;            //链接程序的次版本号
+1Ch    DWORD   SizeOfCode;            //所有含代码的节的总大小
+20h    DWORD   SizeOfInitializedData;     //所有含已初始化数据的节的总大小
+24h    DWORD   SizeOfUninitializedData;   //所有含未初始化数据的节的大小
+28h    DWORD   AddressOfEntryPoint;       //程序执行入口RVA    
+2Ch    DWORD   BaseOfCode;                    //代码的区块的起始RVA
+30h    DWORD   BaseOfData;          //数据的区块的起始RVA
+34h    DWORD   ImageBase;          //程序的首选装载地址
+38h    DWORD   SectionAlignment;          //内存中的区块的对齐大小
+3Ch    DWORD   FileAlignment;         //文件中的区块的对齐大小
+40h    WORD    MajorOperatingSystemVersion;
+42h    WORD    MinorOperatingSystemVersion;
+44h    WORD    MajorImageVersion;
+46h    WORD    MinorImageVersion;
+48h    WORD    MajorSubsystemVersion;
+4Ah    WORD    MinorSubsystemVersion;
+4Ch    DWORD   Win32VersionValue;
+50h    DWORD   SizeOfImage;    //映像装入内存后的总尺寸
+54h    DWORD   SizeOfHeaders;    //所有头+区块表的尺寸大小
+58h    DWORD   CheckSum;
+5Ch    WORD    Subsystem;             //可执行文件期望的子系统
+5Eh    WORD    DllCharacteristics;
+60h    DWORD   SizeOfStackReserve;
+64h    DWORD   SizeOfStackCommit;
+68h    DWORD   SizeOfHeapReserve;
+6Ch    DWORD   SizeOfHeapCommit;
+70h    DWORD   LoaderFlags;
+74h    DWORD   NumberOfRvaAndSizes;       //下边数据目录的项数,这个字段自windows NT发布以来一直是16
+78h    IMAGE_DATA_DIRECTORY DataDirectory  //数据目录表[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

在 IMAGE_OPTIONAL_HEADER32结构体中需要关注下列成员,这些值是文件运行必须的,错误将导致文件不能正常运行。

#1.Magic

在IMAGE_OPTIONAL_HEADER32结构体时,Magic码为10B,IMAGE_OPTIONAL_HEADER64结构体时,Magic码为20B。

#2.AddressOfEntryPoint

持有EP的RVA值,该值指出程序最先执行的代码起始地址

#3.ImageBsae

进程虚拟内存范围0-FFFFFFFF(32位系统)。EXE,DLL文件被装载到用户内存为0-7FFFFFFF,SYS文件被载入内核内存的80000000-FFFFFFFF,一般而言,使用VC++/VB/Delphi创建exe,其基址为00400000,DLL文件的基地址10000000,。

#4.SectionAlignment,FileAlignment

FileAlignment指定了节区在磁盘文件中的最小单位,SectionAlignment指定了节区在内存中的最小单位。磁盘文件或内存的节区大小必定为FileAlignment或SectionAlignment值的整数倍

#5.SizeOfImage

加载PE文件到内存时,指定了PE IMAGE在虚拟内存中所占空间大小

#6.SizeOfHeaders

指出整个PE头的大小。该值也必须是FileAlignment整数倍。第一节区所在位置与SizeOfHeaders距文件开始偏移的量相同

#7.Subsystem

用来区分系统驱动文件与普通可执行文件

#8.NumberOfRvaAndSizes

用来指定DataDirectory数组的个数

#9.DataDirectory

它是由IMAGE_DATA_DIRECTORY结构体组成的数据,数组的每项都有被定义的值,这个结构分为2个部分:
VirtualAddress Dword ?;  数据起始RVA

isize Dword ?; 数据块的长度

DataDirectory结构体数组:

DataDirectory[0] = EXPORT Directory           //导出表
DataDirectory[1] = IMPORT Directory            //导入表
DataDirectory[2] = RESOURCE Directory      //资源
DataDirectory[3] = EXCEPTION Directory     //异常(具体资料不详)
DataDirectory[4] = SECURITY Directory        //异常(具体资料不详)
DataDirectory[5] = BASERELOC Directory    //重定位表
DataDirectory[6] = DEBUG Directory           //调试信息
DataDirectory[7] = COPYRIGHT Directory   //版权信息
DataDirectory[8] = GLOBALPTR Directory   //具体资料不详
DataDirectory[9] = TLS Directory          //Thread Local Storage
DataDirectory[A] = LOAD_CONFIG Directory  //具体资料不详
DataDirectory[B] = BOUND_IMPORT Directory //具体资料不详
DataDirectory[C] = IAT Directory                 //导入函数地址表
DataDirectory[D] = DELAY_IMPORT Directory //具体资料不详
DataDirectory[E] = COM_DESCRIPTOR Directory  //具体资料不详
DataDirectory[F] = Reserved Directory          //未使用

节区头

节区头中定义了各节区属性。把PE文件创建成多个节区结构的好处是,这样可以保证程序的安全性。

IMAGE_SECTION_HEADER

#define IMAGE_SIZEOF_SHORT_NAME              8
typedef struct _IMAGE_SECTION_HEADER {
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];   // \0结尾的节的名称
    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;

其中重要的成员如下:

如下进行演示:

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值