PE结构(二)PE头字段说明

PE头字段 = DOS头 + PE标记 + 标准PE头 + 可选PE头

我们今天分析一下PE头字段中所有重要成员的含义

DOS头

DOS头中我们需要去分析的是如下两个成员:

1.WORD e_magic:MZ标记,用于判断是否为可执行文件,即如果显示4D 5A,说明该文件是一个可执行文件,如:.sys/.dll/.exe等

2.DWORD e_lfanew:NT头(PE签名)相对于文件首地址的偏移,用于定位PE文件真正开始的地址,但该值不是固定的

PE标记

该PE标记的地址即e_Ifanew指向的地址

PE标记中我们要分析的成员只有这一个:

DWORD Signature;  该值存储的是PE两个字,用来表示该文件是PE文件,因此一个可执行文件应该同时满足MZ标记和PE标记,如果这两点不满足可能被修改过,或者就不是一个可执行文件

标准PE头

标准PE头中我们需要去分析的是如下几个成员:

1.WORD Machine:用于约定该文件能在什么样的CPU上运行:如果是0x00表示能在任何CPU上执行,如果是0x14C表示能在386及后续CPU上执行

2.WORD NumberOfSections:用于告知该PE文件中分节的总数(不包括DOS头、NT头、节表):如果要新增节或者合并节,就要修改这个值。

4.DWORD TimeDateStamp:时间戳:文件的创建时间(和操作系统的创建时间无关),当程序被编译器编译时,由编译器填写的

时间戳的使用案例:比如现在要给一个.exe文件加壳,有些加壳软件不光要提供给.exe文件,还需要其对应的.map文件。.map文件中记录了此.exe文件中的所有的函数的名字、地址、参数等信息。这两个文件由编译器编译源文件时生成,.map和.exe的时间戳是一致的。如果现在这个.exe文件被反复修改了以后,.exe文件的时间戳就会改变,但是map的时间戳没有更新,这会导致exe和map不同步。此时如果加壳还是按照map中的记录信息去加壳,就可能出现错误。所以很多加壳软件在加壳之前会检查exe和map文件的时间戳是否一致

5. WORD SizeOfOptionalHeader:可选PE头的大小,该大小不确定:32位PE文件默认E0h,64位PE文件默认为F0h,但其大小可以自定义

6. WORD Characteristics:特征:其大小16位的每个位都表示不同的特征,可执行文件值一般都是0x010F。当某位为1时,表示此文件有此位对应的特征,为0时表示没有此特征

characteristic每一位表示的含义如下图:

把内存中的值读出来后,即读作0x010F,此时化成二进制,第七位省略,其他的每一位都表示一个特征,如果为1,则表示此文件有此位对应的特征;为0表示没有此特征

可选PE头

可选PE头中我们需要去分析的是如下几个成员:

  1. Magic:说明文件类型:如果值为0x010B,表示是32位下的PE文件;如果值为0x020B,表示是64位下的PE文件
  2. SizeOfCode:所有代码节大小的和,必须是FileAlignment的整数倍

比如文件只有一个代码节,大小为100h字节,如果文件对齐粒度是200h,那么会补0填充够200h字节,所以会显示200h(编译器填的);若文件有两个代码节,两个都是10字节,这个值应为400h。但是计算机发展到现在已经不使用这个值了,改了也没事,删除它程序也可以正常运行,但是现在之所以保留下来是因为向下兼容之前的文件

3.SizeOfInitializedData:已初始化数据(比如定义一个有值的全局变量,便是已初始化的数据)大小的和,必须是FileAlignment的整数倍:由编译器填写,目前计算机已经不使用这个值了,保留下来只是为了向下兼容。

4.SizeOfUninitializedData:未初始化数据(比如定义一个没有值的全局变量,便是未初始化的数据)大小的和,必须是FileAlignment的整数倍:编译器填的,现在没用了。

5.AddressOfEntryPoint:程序入口点OEP,即程序真正执行的起始地址:这个值是相对于文件基地址偏移的程序入口地址,而不是真正运行在内存中的程序入口地址。文件装入到4GB虚拟内存中的起始基地址 +相对于文件首地址偏移的程序入口地址,即imagebase + AddressOfEntryPoint,这个值才是真正运行在4GB虚拟内存中的程序入口地址。虽然该值在不同文件中有不同的值,但一般都是0x0040000开始,这是系统的默认ImageBase值。该值我们可以自定义修改,但要保证它可以执行

注意:程序入口在默认情况下一般都在.text节.code代码块当中,且OEP不是只能在.code代码块开始的位置,也可以从此块当中的任何合理位置,或者在其他节(如自定义.tttt节等)的任意合理位置,又或者在数据中。

6.BaseOfCode:代码开始的基址:即PE文件加载到内存后,所有代码的起始地址。编译器填写的,可以改,但不影响程序执行

7.BaseOfData:内存中所有数据开始的地址:编译器填的,程序运行用不到,想改就改

8. ImageBase: 内存镜像基址:该值可以看作模块之间的对齐粒度,也是程序运行装载到自己的虚拟4GB内存后的起始位置。imagebase一般都是0x00400000(具体原因参考上一篇对齐部分),这是系统的默认值,不能超过0x80000000,这是因为我们写的程序的数据只能在内存的2GB用户区中,不能占用2GB系统区。

模块的概念:一个.exe文件可能是由一堆PE文件组成的,每个pe文件都有自己的imagebase,他们共用一个4GB虚拟内存。这是因为.exe文件本身是一个PE文件,满足PE结构,但是.exe中可能还用到了很多.dll,每一个.dll也是一个PE文件,也满足PE结构,这些.dll有自己的功能和作用,当它们拼凑到一个.exe文件中时,.exe文件就有了完整的功能。这时又称.exe文件有很多模块构成,每一个.dll都是一个模块

pe文件(各个模块)不能从0开始的原因是因为内存保护,我们前面学过,free一个动态分配内存的指针后,一定要将指针指向NULL,那么当指针指向NULL后,这个指针指向的地址就是0x0,从0开始往后偏移一定范围的地址,操作系统都把他的地址上内存空了出来,那么此时指针访问这部分的数据,编译器会立马报错,也就是说限制了指针使其不能为所欲为的访问内存。

9.SectionAlignment:内存对齐粒度:可执行文件运行时装入4GB虚拟内存中的对齐粒度,一般为0x1000字节

10.DWORD FileAlignment:文件对齐粒度:可执行文件在硬盘的对齐粒度,一般为0x200字节,还有的是0x1000字节,和内存对齐粒度相等

举例说明内存对齐和文件对齐:(day27.1-PE结构概况中详细说明过)

11. DWORD  SizeOfImage:内存中整个PE文件的映射尺寸:即文件运行时在4GB虚拟内存中的整个文件数据大小。该值可以比实际的值大,但必须是SectionAlignment的整数倍

12. DWORD SizeOfHeaders:所有头+节表按照文件对齐后的大小:即DOS头 + 垃圾数据 + PE签名 + 标准PE头 + 可选PE头 + 节表,按照文件对齐后的大小。必须是FileAlignment的整数倍,否则加载会出错

举例:比如一个可执行文件的所有头和节表加起来大小为0x1800字节,但是因为要满足文件对齐粒度0x1000,示意图SizeOfHeaders的值应该为0x2000,

13. DWORD CheckSum:校验和:一些重要的系统文件、驱动文件等对此有要求,用来判断文件是否被修改(但是可以修改这个值)

校验方法举例:把PE文件中的所有数据中两个字节的值(十六进制)两两相加(如值1 2 3 4,相加:1+2,3+4),最后将所有两两相加的结果再求和得到一个数,存放到checksum表示的4字节内存中,内存可溢出

14. DWORD SizeOfStackReserve:初始化时保留的栈大小 (最大值)

15. DWORD SizeOfStackCommit:初始化时实际提交的栈大小

16. DWORD SizeOfHeapReserve:初始化时保留的堆大小 (最大值)

17. DWORD SizeOfHeapCommit:初始化时实际提交的堆大小

18. DWORD NumberOfRvaAndSizes:目录项数目“如果该值是0x10,表示下面的_IMAGE_DATA_DIRECTORY DataDirectory[16]结构体有16个,一个占8字节,这些结构体用于告诉我们编译器在编译文件时往exe文件中所添加的数据。具体如下图所示:

可执行文件的读取到装入内存过程

文件装入内存流程如图所示:

1.编译器生成.exePE文件

比如我们使用VC,编写程序以后按下F7,编译器会编译生成对应的.exe可执行文件,此时编译器计算生成PE文件的所有数据,比如imagebase或者OEP等全部字段信息,最后将.exe文件保存到硬盘中

2.文件数据读到内存(FileBuffer)

当文件数据读取到内存中时,其数据存储是完全照搬文件在硬盘上的数据。此时文件的格式并非windows运行格式,所以Windows操作系统还无法运行它

3.将文件装载到内存镜像(ImageBuffer)

将文件从FileBuffer装入ImageBuffer,即将文件从imagebase开始对齐拉伸成内存对齐形式的一块内存。这个过程就是将文件装入自己的4GB虚拟内存中,称为PE loader。我们称将文件拉伸装载后的内存为imageBuffer,即内存镜像。此时文件的格式满足windows运行格式。对于硬盘对齐粒度等于内存对齐粒度的文件不需要进行拉伸

此时文件在4GB虚拟内存中的起始地址,就是imagebase,一般为0x00400000,接着就可以通过imagebase + addressofentrypoint找到文件装载到内存后真正的程序入口地址;或者用imagebase加上一些偏移地址值就可以得到文件其他内容在运行时装入4GB内存后的地址

4.操作系统将虚拟地址转化成物理地址

FileBuffer和ImageBuffer提到的所有地址都是虚拟地址,操作系统最后会将这些虚拟地址转换为物理地址,这样才算真正的装入到真实内存中。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[2021年最新]国产时序性数据TDenige入门

一、TDenige简介 TDengine:是涛思数据面对高速增长的物联网大数据市场和技术挑战推出的创新性的大数据处理产品,它不依赖任何第三方软件,也不是优化或包装了一个开源的数据库或流式计算产品,而是在吸取众多传统关系型数据库、NoS…

图搜索的经典启发式算法A星(A*、A Star)算法详解

文章目录 1. 引言2. 广度优先搜索3. Dijkstra 算法4. 启发式优先搜索(Heuristic)4.1 贪心最佳优先搜索4.2 A*搜索 1. 引言 在许多场景中,我们常会遇到一类问题,即“找到一个位置到另一个位置的距离最短(用时最少&…

ELK 日志分析系统(二)

一、ELK Kibana 部署 1.1 安装Kibana软件包 #上传软件包 kibana-5.5.1-x86_64.rpm 到/opt目录 cd /opt rpm -ivh kibana-5.5.1-x86_64.rpm 1.2 设置 Kibana 的主配置文件 vim /etc/kibana/kibana.yml --2--取消注释,Kiabana 服务的默认监听端口为5601 server.po…

ubuntu 24.04 beta server NAT模式上网设置

在Ubuntu 24.04 Beta上设置网络通常涉及使用命令行工具。以下是设置静态IP地址和动态IP地址的步骤: 动态IP设置: 查找你的网络接口名称: ip a ens37是我NAT模型的一张网卡,此时是没有ip的。 下面介绍如何NAT模式下添加DHCP动态…

Maven多模块快速升级超好用Idea插件-MPVP

功能:多模块maven项目快速升级指定版本插件,并提供预览和相关升级模块日志能力。 可快速进行版本升级,进行部署到Maven仓库。 安装: 可在idea插件中心进行安装 / 下载资源拖动安装 MPVP(Maven) - IntelliJ IDEs Plugin | Marke…

node.js 解析post请求 方法一

前提:依旧以前面发的node.js服务器动态资源处理代码 具体见 http://t.csdnimg.cn/TSNW9为模板,在这基础上进行修改。与动态资源处理代码不同的是,这次的用户信息我们借用表单来实现。post请求解析来获取和展示用户表单填写信息 1》代码难点&…

快速新建springboot项目

一、初始化 1.打开IDEA,在Spring initializer这里按照下图项目进行配置。注意:如果jdk是1.8建议将Server URL这里替换为图中的阿里云服务器,否则容易找不到对应的java8,然后点击next 2.在这里提前配置一些需要使用的依赖&#xf…

Linux上部署Jupyter notebook

安装jupyter notebook pip install notebook #或者 conda install notebook配置 jupyter notebook --generate-config## The IP address the notebook server will listen on. # Default: localhost # 设置可以访问的ip, 默认是localhost, 将其改为 * c.NotebookApp.ip *#…

CMakeLists.txt中如何添加编译选项?

1. 引子 编译器有多种可供选择,如g、c、clang等,如下以c作为示例。 2. 使用CMAKE_CXX_FLAGS添加编译选项 在Makefile中可能用类似如下的指令来添加编译选项: /usr/bin/c -Wall -Wextra -Wno-sign-compare -Wno-unused-variable -Wno-unuse…

LLM大语言模型(十三):ChatGLM3-6B兼容Langchain的Function Call的一步一步的详细转换过程记录

# LangChain:原始prompt System: Respond to the human as helpfully and accurately as possible. You have access to the following tools: Calculator: Useful for when you need to calculate math problems, args: {\calculation\: {\description\: \calcul…

云安全防御篇:如何识别并做好服务器DDoS防护?

伴随着全球互联网业务和云计算的快速发展,作为一种破坏力巨大的攻击方式,DDoS攻击正以超出服务器承受能力的流量淹没网站,导致服务器宕机、企业营业额下跌,甚至企业品牌形象受损。越是面对复杂的攻击,就需要性能更强的…

linux安装nacos(单机简易版本)

1. 查看Java版本,必须有jdk支持 2. 下载安装包,解压 下载地址: https://github.com/alibaba/Nacos/releases 2.1 上传到 /opt文件夹 2.2使用解压命令 tar -zxvf nacos-server-2.2.1.tar.gz 2.3 解压后产生文件夹 3. 配置 3.1 修改配置&…

牛客NC98 判断t1树中是否有与t2树完全相同的子树【simple 深度优先dfs C++/Java/Go/PHP】

题目 题目链接: https://www.nowcoder.com/practice/4eaccec5ee8f4fe8a4309463b807a542 思路 深度优先搜索暴力匹配 思路和算法这是一种最朴素的方法——深度优先搜索枚举 s 中的每一个节点,判断这个点的子树是否和 t 相等。如何判断一个节点的子树是否…

zabbix6.4告警配置(短信告警和邮件告警),脚本触发

目录 一、前提二、告警配置1.邮件告警脚本配置2.短信告警脚本配置3.zabbix添加报警媒介4.zabbix创建动作4.给用户添加报警媒介 一、前提 已经搭建好zabbix-server 在需要监控的mysql服务器上安装zabbix-agent2 上述安装步骤参考我的上篇文章:通过docker容器安装za…

WEP、WPA、WPA2 和 WPA3:区别和说明

无线网络安全是保持在线安全的一个重要因素。通过不安全的链路或网络连接到互联网是一种安全风险,可能会导致数据丢失、帐户凭据泄露,以及他人在您的网络上安装恶意软件。必须使用适当的 Wi-Fi 安全措施 - 但在这样做时,也必须了解不同的无线…

[Linux初阶]常见的指令

我们学Linux指令,其实就是和学windows一样,学习Linux的操作 一、Linux下基本指令 ls 指令 语法 : ls [ 选项 ] [ 目录或文件 ] 功能 :对于目录,该命令列出该目录下的所有子目录与文件。对于文件,将列出…

就业班 第三阶段(负载均衡) 2401--4.19 day3

二、企业 keepalived 高可用项目实战 1、Keepalived VRRP 介绍 keepalived是什么keepalived是集群管理中保证集群高可用的一个服务软件,用来防止单点故障。 ​ keepalived工作原理keepalived是以VRRP协议为实现基础的,VRRP全称Virtual Router Redundan…

装饰模式【结构型模式C++】

1.概述 装饰模式是一种结构型设计模式, 允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。 2.结构 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。具体构件(Concrete…

Adobe Illustrator 2024 v28.4.1 (macOS, Windows) - 矢量绘图

Adobe Illustrator 2024 v28.4.1 (macOS, Windows) - 矢量绘图 Acrobat、After Effects、Animate、Audition、Bridge、Character Animator、Dimension、Dreamweaver、Illustrator、InCopy、InDesign、Lightroom Classic、Media Encoder、Photoshop、Premiere Pro、Adobe XD 请…

穿越代码迷雾:解密Tracing技术的神奇力量

穿越代码迷雾:解密Tracing技术的神奇力量 在软件开发和性能优化领域,追踪(Tracing)技术是一种重要的工具,用于收集和分析程序的执行过程和性能数据。本文将深入讲解Tracing的原理、工作方式以及在不同领域的应用场景&a…