【PE】PE文件结构(一)

news2024/11/25 18:25:42

概述:PE文件结构基础认识之DOS头和PE头(以 rpcrt4.dll 为例分析)

0x01 前言

PE(Portable Executable),即可移植的执行体。

  • Linux平台:ELF(Executable and Linking Format)文件结构。

  • Windows平台下,所有的可执行文件。诸如:exe、dll、sys、ocx、com等均适用PE文件结构,这些使用PE文件结构也被称为PE文件。

0x02 PE结构

PE 结构是由若干个复杂的结构体组合而成的,不是单单的一个结构体那么简单,它的结构就像文件系统的结构是由多个结构体组成的。PE结构 包含的结构体有 DOS 头、PE 标识、文件头、可选头、目录结构、节表等。如下图所示:

在这里插入图片描述

DOS头

DOS头中声明用的寄存器(我们可以看到e_ss、e_sp、e_ip、e_cs还是16位的寄存器),所以在32位/64为系统中用到的只有两个成员了(第一个和最后一个)。无论是32位还是64位PE文件,其文件的头部必定是DOS头。大小为 40H(64字节)。相关结构如下所示:

// WORD 为2字节
// DWORD 为4字节

typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header(※Magic DOS signature MZ(4Dh 5Ah):MZ标记)
    WORD   e_magic;                     // Magic number
    WORD   e_cblp;                      // Bytes on last page of file
    WORD   e_cp;                        // Pages in file
    WORD   e_crlc;                      // Relocations
    WORD   e_cparhdr;                   // Size of header in paragraphs
    WORD   e_minalloc;                  // Minimum extra paragraphs needed
    WORD   e_maxalloc;                  // Maximum extra paragraphs needed
    WORD   e_ss;                        // Initial (relative) SS value
    WORD   e_sp;                        // Initial SP value
    WORD   e_csum;                      // Checksum
    WORD   e_ip;                        // Initial IP value
    WORD   e_cs;                        // Initial (relative) CS value
    WORD   e_lfarlc;                    // File address of relocation table
    WORD   e_ovno;                      // Overlay number
    WORD   e_res[4];                    // Reserved words
    WORD   e_oemid;                     // OEM identifier (for e_oeminfo)
    WORD   e_oeminfo;                   // OEM information; e_oemid specific
    WORD   e_res2[10];                  // Reserved words
    LONG   e_lfanew;                    // File address of new exe header
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

DOS 头又分为两部分,MZ头部DOS存根

MZ头部
  • MZ文件头:IMAGE_DOS_HEADER 结构体,其大小占64个字节,并且该结构中的最后一个LONG类型e_lfanew成员指向PE文件头的位置为中的PE文件头标志的地址。
    DOS头中有两个重要的成员,分别是 e_magice_lfanew,如PE文件结构说明一图所示:

    • e_magic:对应 MZ标识(固定值) ,也就是 0x5A4D
    • e_lfanew: 指pe的偏移量,对应的PE数据块的基地址

    在这里插入图片描述

DOS存根(DOS stub)

DOS头(IMAGE_DOS_HEADER)和PE头(IMAGE_NT_HEADERS)中间的空余位置是一些垃圾值以及编译器填充的一些 *The is program cannot be run in DOS mode.*或 This program must be run under Win32 等信息。这些信息就是 DOS存根。DOS存根实际上是一段汇编代码。用于在DOS环境下启动PE文件时输出一些上述文本。

在这里插入图片描述

在pe文件利用的时候,我们可以把payload写入到当前区域,诸如存放我们的shellcode,在读取时,获取dos头字节数,减去MZ头字节数,即为dos存根字节大小。然后拿去操作加载shellcode等。

PE头

在MS-DOS头下main,就是PE头,PE头是PE相关结构NT映像头(IMAGE_NT_HEADER)的简称,其中包含许多PE装载器用到的重要字段。PE头又分为标准PE头和可选PE头,其同为NT结构的成员:

IMAGE_NT_HEADER数据结构定义:

//NT头
//pNTHeader = dosHeader + dosHeader->e_lfanew;
struct _IMAGE_NT_HEADERS{
    0x00 DWORD Signature;   //PE文件标识:ASCII的"PE\0\0"
    0x04 _IMAGE_FILE_HEADER FileHeader;
    0x18 _IMAGE_OPTIONAL_HEADER OptionalHeader;
};

根据DOS头的e_lfanew成员我们就可以找到NT头,NT头的第一个成员SignaturePE\0\0(0X50 0X45 0X00 0X00四字节的签名),后两个成员则分别是标准PE头FileHeader_IMAGE_FILE_HEADER)和OptionalHeader可选PE头(_IMAGE_OPTIONAL_HEADER)。

在这里插入图片描述

PE标识 Signature

将文件标识为 PE 映像的 4 字节签名。字节为PE\0\0。这个字段是PE文件的标志字段,通常设置成 00004550h,其ASCII码为 PE00,这个字段是PE文件头的开始,前面的DOS_HEADER结构中的字段e_lfanew字段就是指向这里。

文件头 FileHeader

文件头结构体为 _IMAGE_FILE_HEADER,见IMAGE_FILE_HEADER (winnt.h) - Win32 apps | Microsoft Learn。结构体成员变量如下所示:

typedef struct _IMAGE_FILE_HEADER {
    WORD Machine;			//运行平台
    WORD NumberOfSections;	//文件的区块数目
    DWORD TimeDateStamp;	//文件创建的用时间戳标识的日期
    DWORD PointerToSymbolTable;		//指向符号表(用于调试)
    DWORD NumberOfSymbols;			//符号表中符号的个数
    WORD SizeOfOptionalHeader;		//IMAGE_OPTIONAL_HEADER32结构大小
    WORD Characteristics;			//文件属性
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

参照上述结构体,分析一下 rpcrt4.dll 的 FileHeader 成员。

PE头存储内容如下所示:

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

000000E0                            50 45 00 00 4C 01 06 00           PE  L   
000000F0   77 7B 41 86 00 00 00 00  00 00 00 00 E0 00 02 21   w{A?       ? !

现在有数据也知道结构体,可以根据存储的内容知道 rpcrt4.dll 的一些信息了(地址是由低位向高位增长的,这里直接复制粘贴了,读者知道这回事就行)

成员变量MachineNumberOfSectionsTimeDateStampPointerToSymbolTableNumberOfSymbolsSizeOfOptionalHeaderCharacteristics
大小WORDWORDDWORDDWORDDWORDWORDWORD
4C 0106 0077 7B 41 8600 00 00 0000 00 00 00E0 0002 21
说明0x014C 表示当前体系结构类型为 x86当前PE文件的节数,当前所示有 6 个当前PE文件的时间戳符号表的偏移量(以字节为单位),如果没有 COFF 符号表,则为 0符号表中的符号数,当前为 0可选文件头大小,当前所示有 224 个图像的特征 0x2102
补充机器标识标识区块的数目,关于区块后面会详细讲指的就是PE文件创建的事件,这个时间是指从1970年1月1日到创建该文件的所有的秒数紧跟着IMAGE_FILE_HEADER后面的数据大小,这也是一个数据结构,它叫做IMAGE_OPTIONAL_HEADER,其大小依赖于是64位还是32位文件。32位文件值通常是00EOh,对于64位值通常为00F0h普通EXE文件这个字段值为010fh,DLL文件这个字段一般是0210h

最后一个参数图像特征 Characteristics 的值 0x2102 的说明

  • 0x2000 该图像是一个DLL文件,虽然是可执行文件,但不能直接运行
  • 0x0100 计算机支持32位
  • 0x0002 该文件是可执行文件,(没有未解析的外部引用)
可选头 OptionalHeader

可选PE头紧接着标准PE头,其大小在标准PE头中给出:大小为 E0H 即224字节。_IMAGE_OPTIONAL_HEADER结构如下所示:

WinNT.h 中的实际 结构IMAGE_OPTIONAL_HEADER32命名IMAGE_OPTIONAL_HEADER 定义为 IMAGE_OPTIONAL_HEADER32。 但是,如果定义了 _WIN64 ,则 IMAGE_OPTIONAL_HEADER 定义为 IMAGE_OPTIONAL_HEADER64

typedef struct    _IMAGE_OPTIONAL_HEADER 
{
	//
	// Standard      fields. 
	//
	/*+0x00*/         WORD     Magic;                       // 标志字, ROM 映像(0107h),普通可执行文件(010Bh)
	/*+0x02*/         BYTE     MajorLinkerVersion;          // 链接程序的主版本号
	/*+0x03*/         BYTE     MinorLinkerVersion;          // 链接程序的次版本号
	/*+0x04*/         DWORD    SizeOfCode;                  // 所有含代码的节的总大小
	/*+0x08*/         DWORD    SizeOfInitializedData;       // 所有含已初始化数据的节的总大小
	/*+0x0c*/         DWORD    SizeOfUninitializedData;     // 所有含未初始化数据的节的大小
	/*+0x10*/         DWORD    AddressOfEntryPoint;         // 程序执行入口RVA
	/*+0x14*/         DWORD    BaseOfCode;                  // 代码的区块的起始RVA
	/*+0x18*/         DWORD    BaseOfData;                  // 数据的区块的起始RVA

	//
	// NT additional fields.  以下是属于NT结构增加的领域。
	//
	/*+0x1c*/         DWORD    ImageBase;                   // *程序的首选装载地址
	/*+0x20*/         DWORD    SectionAlignment;            // *内存中的区块的对齐大小
	/*+0x24*/         DWORD    FileAlignment;               // *文件中的区块的对齐大小
	/*+0x28*/         WORD     MajorOperatingSystemVersion; // 要求操作系统最低版本号的主版本号
	/*+0x2a*/         WORD     MinorOperatingSystemVersion; // 要求操作系统最低版本号的副版本号
	/*+0x2c*/         WORD     MajorImageVersion;           // 可运行于操作系统的主版本号
	/*+0x2e*/         WORD     MinorImageVersion;           // 可运行于操作系统的次版本号
	/*+0x30*/         WORD     MajorSubsystemVersion;       // 要求最低子系统版本的主版本号
	/*+0x32*/         WORD     MinorSubsystemVersion;       // 要求最低子系统版本的次版本号
	/*+0x34*/         DWORD    Win32VersionValue;           // 莫须有字段,不被病毒利用的话一般为0
	/*+0x38*/         DWORD    SizeOfImage;                 // 映像装入内存后的总尺寸
	/*+0x3c*/         DWORD    SizeOfHeaders;               // 所有头+区块表的尺寸大小
	/*+0x40*/         DWORD    CheckSum;                    // 映像的校检和
	/*+0x44*/         WORD     Subsystem;                   // 可执行文件期望的子系统
	/*+0x46*/         WORD     DllCharacteristics;          // DllMain()函数何时被调用,默认为0
	/*+0x48*/         DWORD    SizeOfStackReserve;          // 初始化时的栈大小
	/*+0x4c*/         DWORD    SizeOfStackCommit;           // 初始化时实际提交的栈大小
	/*+0x50*/         DWORD    SizeOfHeapReserve;           // 初始化时保留的堆大小
	/*+0x54*/         DWORD    SizeOfHeapCommit;            // 初始化时实际提交的堆大小
	/*+0x58*/         DWORD    LoaderFlags;                 // 与调试有关,默认为0 
	/*+0x5c*/         DWORD    NumberOfRvaAndSizes;         // 下边数据目录的项数,这个字段自Windows NT发布以来,一直是16
	/*+0x60*/         IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];	// *数据目录表
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

上述共计 31 个字段,常用的一般是加*的几个。这里还是简单的按照内存和结构体一一对应分析看下。

内存如下所示:

在这里插入图片描述

成员变量大小说明补充
MagicWORD0B 01映像文件的状态,0x01 标识当前是可执行映像
MajorLinkerVersionBYTE0E链接器的主要版本号,当前是 14
MinorLinkerVersionBYTE14链接器的次要版本号,当前是 20
SizeOfCodeDWORD00 C2 0A 00如果有多个代码节,则为代码节的大小(以字节为单位)或所有此类节的总和。
SizeOfInitializedDataDWORD00 EA 00 00初始化的数据节的大小。代码节的大小或所有此类节的总和
SizeOfUninitializedDataDWORD00 00 00 00未初始化数据节的大小
AddressOfEntryPointDWORD50 D3 03 00指向入口点函数的指针
BaseOfCodeDWORD00 10 00 00指向代码部分的开头的指针
BaseOfDataDWORD00 E0 0A 00指向数据部分开头(相对于图像基数)的指针。
ImageBaseDWORD00 00 F8 4E图像加载到内存中的第一个字节的首选地址。 此值是 64K 字节的倍数。 DLL 的默认值为 0x10000000。 应用程序的默认值为 0x00400000,0x00010000 Windows CE除外。
SectionAlignmentDWORD00 10 00 00内存中加载的节的对齐方式(以字节为单位)。 此值必须大于或等于 FileAlignment 成员。 默认值是系统的页大小。
FileAlignmentDWORD00 02 00 00图像文件中各部分的原始数据的对齐方式(以字节为单位)。 该值应为介于 512 和 64K 之间的幂 ((含) )。 默认值为 512。 如果 SectionAlignment 成员小于系统页面大小,则此成员必须与 SectionAlignment 相同。
MajorOperatingSystemVersionWORD0A 00所需操作系统的主版本号。 0x0A 为 10
MinorOperatingSystemVersionWORD00 00所需操作系统的次要版本号。
MajorImageVersionWORD0A 00映像的主版本号。
MinorImageVersionWORD00 00映像的次要版本号。
MajorSubsystemVersionWORD0A 00子系统的主版本号。
MinorSubsystemVersionWORD00 00子系统的次要版本号。
Win32VersionValueDWORD00 00 00 00此成员是保留的,必须为 0。
SizeOfImageDWORD00 F0 0B 00图像的大小(以字节为单位),包括所有标头。 必须是 SectionAlignment 的倍数。
SizeOfHeadersDWORD00 04 00 00以下项的组合大小,舍入为 FileAlignment 成员中指定的值的倍数。
CheckSumDWORD3B 06 0C 00映像文件校验和。 以下文件在加载时进行验证:所有驱动程序、在启动时加载的任何 DLL,以及加载到关键系统进程中的任何 DLL。
SubsystemWORD03 00运行此映像所需的子系统。 定义了以下值。 0x03 标识 windows 字符膜片式用户界面(CUI)系统
DllCharacteristicsWORD40 41图像的 DLL 特征。 定义了以下值。
SizeOfStackReserveDWORD00 00 04 00
SizeOfStackCommitDWORD00 10 00 00
SizeOfHeapReserveDWORD00 00 10 00
SizeOfHeapCommitDWORD00 10 00 00
LoaderFlagsDWORD00 00 00 00
NumberOfRvaAndSizesDWORD10 00 00 00
DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]IMAGE_DATA_DIRECTORY16个指针地址,大小为 80H这个是一个指针类型,指向 IMAGE_DATA_DIRECTORY 结构的指针。会根据传入的索引号返回不同指向的结构体

最后一个成员变量结构体如下所示,详见IMAGE_DATA_DIRECTORY (winnt.h) - Win32 apps | Microsoft Learn:

struct _IMAGE_DATA_DIRECTORY{
    DWORD   VirtualAddress;
    DWORD   Size;
};
//占用16*8 = 128Byte = 80H = E0H(可选PE头默认大小) - 60H(前面所有成员固定占用大小)

关于最后一个成员变量,可枚举的 IMAGE_NUMBEROF_DIRECTORY_ENTRIES 索引总共有15个,外加一个保留指针。也就是说,在 DataDirectory 位置存放了 16 个指针。可以参考之前的PE头对照一下,剩下的PE内存刚好存放了 16 个指针,参考 PE 块的总大小,剩下的部分大小也刚好为 80 h 80h 80h

$ 16 * 8 = 128 = 80H$

如下图所示:

在这里插入图片描述

节表

下篇文章记录

节表数据

下篇文章记录

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1206523.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

新生儿奶瓣:原因、科普和注意事项

引言: 新生儿奶瓣是一种婴儿口腔内的常见现象,它通常被视为正常的生理发展。然而,对于一些新父母而言,了解奶瓣的原因以及如何处理是至关重要的。本文将科普新生儿奶瓣的原因,提供相关信息,并为父母和监护…

YOLOv8-Seg改进:卷积变体系列篇 | DCNv3可形变卷积基于DCNv2优化 | CVPR2023

🚀🚀🚀本文改进:DCNv3算子,基于DCNv2算子引入共享投射权重、多组机制和采样点调制,引入到YOLOv8,与C2f结合实现二次创新; 🚀🚀🚀DCNv3 亲测在多个数据集能够实现涨点,同样适用于小目标分割 🚀🚀🚀YOLOv8-seg创新专栏:http://t.csdnimg.cn/KLSdv 学姐…

算法的入门基础了解

目录 算法的特征 如何设计算法? 伪代码 “算法”一词最早出现在《周髀算经》这本书中,对应的英文单词是“algorism”(由 9 世纪的波斯数学家阿尔霍瓦里兹米提出),代指阿拉伯数字的运算规则。随着计算机的快速发展&a…

设计大咖亲授:Figma中文环境设置全攻略!

作为UI设计师,你一定很熟悉Figma,Figma是一款专注于UI/UX设计的在线协作工具,使用非常高效方便,不需要下载和安装。它只需要通过浏览器编辑,在国外很受欢迎。但是Figma对于国内的小伙伴来说,使用Figma有一定…

Java面试题(每天10题)-------连载(30)

目录 多线程篇 1、可以运行时kill掉一个线程吗? 2、关于synchronized 3、分布式锁,程序数据库中死锁机制及解决方案 4、spring单例为什么没有安全问题(ThreadLocal) 5、线程池原理 6、Java锁多个对象 7、Java线程如何启动 …

基于opencv+tensorflow+神经网络的智能银行卡卡号识别系统——深度学习算法应用(含python、模型源码)+数据集(一)

目录 前言总体设计系统整体结构图系统流程图 运行环境Python环境TensorFlow 环境OpenCV环境 相关其它博客工程源代码下载其它资料下载 前言 本项目基于从网络获取的多种银行卡数据集,采用OpenCV库的函数进行图像处理,并通过神经网络进行模型训练。最终实…

雅虎、美客多、Temu、Allegro、亚马逊跨境平台选品技巧方法,测评养号攻略。

(1) Best Sellers选品法 这个方法顾名思义,就是大家熟悉的热销榜单选品法。 不做过多解释,在自己熟悉的品类,隔几天就会观察一下前100名里有没有冒出什么新品。 它和现有的产品相同还是不同,自己做哪些搭配或者迭代…

数字农业农村解决方案:PPT全文69页,附下载

关键词:智慧农业解决方案,数字农村,数字农业,智慧农业大数据平台 一、数字农业建设背景 数字农业建设是在国家大数据战略和“互联网”行动计划的指引下,充分利用现代信息技术和人工智能手段,对农业农村领…

ioc是什么

IOC是什么? 在面向对象的软件设计中,底层都是由多个对象耦合组成共同实现逻辑业务的,如下图: 耦合关系不仅会出现在对象与对象之间,也会出现在软件系统的各模块之间,以及软件系统和硬件系统之间。如何降低…

电脑监控软件丨功能详情丨特点分析

电脑监控软件的出现,是在信息技术的飞速发展以及计算机使用的普及的背景下产生的。随着计算机在企业、学校以及家庭等各个场所的广泛使用,管理和保护计算机数据安全的问题变得越来越重要。因此,电脑监控软件应运而生,旨在帮助用户…

企业大楼门禁,千万不要这么管理!太慢了!

随着社会科技的飞速发展,安全管理已经成为各行业关注的焦点之一。在这个信息化时代,门禁监控系统作为一种全面提升安全性、管理效率的关键工具,逐渐成为企事业单位、学校、医疗机构等场所的不可或缺的一部分。 传统的门禁系统已经无法满足现代…

threejs太阳系(源码加相关素材)

目录 前言 效果预览图 完整代码 html部分 js部分 模块aa 前言 Three.js 是一款基于原生 WebGL 封装通用 Web 3D 引擎,在小游戏、产品展示、物联网、数字孪生、智慧城市园区、机械、建筑、全景看房、GIS 等各个领域基本上都有 three.js 的身影。本篇文章简单的使…

开源维修上门服务小程序SAAS系统源码 带完整搭建教程

在现代生活中,家电设备维修往往是一个耗时且繁琐的过程。消费者需要花费大量时间寻找合适的维修人员,并面临服务质量不稳定的风险。同时,对于维修人员来说,寻找客户和接收订单的过程也十分繁琐。因此,开发一款基于小程…

cryptopp Base64Encoder \n问题

1、问题: new Base64Encoder(new StringSink(out_base)) 调用库函数Base64Encoder进行base64加密后确认多出来了\n 2、原因 base64加密的问题, 由于base64一行不能超过76字符, 超过就会添加回车换行符(在Windows中是 \r\n , 在Linux中是 \n ) 3、解决 方法一、给定参…

Python中的filter函数用法详解

目录 引言 一、filter函数基本用法 二、filter函数应用场景 1、筛选符合条件的元素 2、数据清洗和预处理 3、复杂条件筛选 4、与其他函数结合使用 三、filter函数与lambda表达式 四、filter函数与列表推导式 五、总结 引言 Python中的filter函数是一种内置的高效过滤…

电脑桌面图标打不开?三种方法让你轻松应对

电脑桌面上的图标是我们日常使用电脑的入口,但有时候您可能会遇到一个常见问题,电脑桌面图标打不开。这个问题可能会让您感到困惑,但幸运的是,通常有多种方法可以解决。本文将详细介绍三种常见的解决方法,帮助您恢复桌…

测试:面试问题(多精全)

目录 面试问题 1,你们原来项目的测试流程是怎么样的? 2,你介绍下,你最熟悉的项目? 3,你们原来项目的主要的功能模块有哪些,你主要负责哪些模块? 4,你说原来充值…

Axure9学习

产品经理零基础入门(四)Axure 原型图教程,2小时学会_哔哩哔哩_bilibili 1. ① 页面对应页面个数,概要对应每个页面的具体内容 ② 文件类型 ③ 备用间隔改为5分钟 ④ 当多个元件重叠,想把在下面的元件b直接拖出来&…

一款IT团队都在用的私有化知识库,技术开放,还开源了!

IT和软件开发团队需要处理大量的技术文档和知识,通过建立内部知识库,可以将技术文档、代码示例、最佳实践等知识整理和归档起来,方便团队成员查找和参考。 IT和软件开发团队为什么要建立内部知识库? 提高知识管理效率&#xff1a…

汇川(Inovance) PLC——H2u 和H3u:编程口通讯协议

文章目录 说明通讯帧通讯命令字通讯数据地址汇川 H2u H3u通讯协议举例 说明 该协议适用于汇川H2u系列和H3u系列PLC。 通讯帧 通讯采用ASCII码,校验方式采用和校验。 请求帧格式:报文开始命令字地址(有些无)长度(有些无&#xf…