当前位置:网站首页 > 编程语言 > 正文

pem文件是什么意思(pe是什么文件夹)



PE文件是指windows系统下使用的可执行文件格式,它是微软在unix平台的COFF基础上制作而成的。PE文件一般指32位的可执行文件,也称为PE32。64位的可执行文件称为PE+或者PE32+(不是PE64),是PE32的一种扩展形式。

要了解PE文件,首先要知道PE格式,那么什么是PE格式呢,既然是一个格式,那肯定是需要遵循的一定的定理。其实PE格式就是各种结构体的结合,这些结构体都定义在在这个头文件中。

PE文件整体结构
一个PE文件大致可分为以下几个部分:

  • DOS部分
  • PE文件头
  • 节区头(节表)
  • 节数据(块数据)
  • 调试信息

从DOS头到节区头是PE头,其下的是PE体。文件中使用偏移(Offset), 内存中使用VA(Virtual Address)来表示位置。

VA指的是进程虚拟内存的绝对地址,RVA(Relative Virtual Address)指从基准位置(ImageBase)开始的相对地.址。两者存在以下换算关系:

PE头内部的信息大多以RVA的形式存在

DOS头结构体大小为40个字节,其中只需要熟悉两个成员变量:与,前者是DOS签名,固定为,取自微软开发人员首字母。后者则是指示NT头的偏移位置(),除了这两个成员,其他成员全部用0填充都不会影响程序正常运行。定义如下

变量固定偏移位置3C处,从此后到所指向的偏移位置为(中文一般翻译为),在win32中未使用。在16位系统中运行便输出一个 就退出了。

pem后缀文件 pe文件格式详解_加载

由图可知的值是,则到的内容便为。

PE文件头由PE文件头标志,标准PE头,扩展PE头三部分组成

0x02.2.1 IMAGE_NT_HEADERS

由上可知定义了3个成员变量,

  • 固定为字符;
  • 指向一个为的结构体;
  • 在32位下指向一个的结构体。在64位下,指向一个的结构体。

0x02.2.2 IMAGE_FILE_HEADER

我们一个一个分析,先看下的定义:

里面大概有4个重要的成员变量需要掌握,如果这些变量的值设置不正确,程序便不能正常运行。

  • :每个CPU都有一个唯一的Machine码,兼容32位Intel x86芯片的machine码是14c。其它Machine码可在winnt.h中查看。
  • : 指示文件中存在的节区数量, 此值是一定要大于0,且当定义的节区数与实际的节区数不一样时,将发生运行错误。
  • :标识第三个成员变量的大小。
  • :标识文件属性,是否是dll,是否可执行等信息。

如下图便是,

pem后缀文件 pe文件格式详解_成员变量_02

根据图片所示,我们可以得出各值:

0x02.2.2 IMAGE_OPTIONAL_HEADER

扩展PE头在32位和64位系统上大小是不同的,在32位系统上有224个字节,16进制就是0xE0,与上面的SizeOfOptionalHeader也能对上。

是PE头结构体最大的一个,先看定义:

部分成员变量说明:

  • :指出文件被加载到内存应该被优先加载的内存地址,exe,dll文件被装载到用户内存的中,sys文件被载入内存的中,一般情况下,exe会被装载到,dll文件的值为
  • : 用来指定数组的个数,在winnt.h中被明确定义为16,但PE loader一般会通过此值来识别的大小,也就是说的长度不一定都是16。
  • 是由结构体数据组成的,数组中的每一项都有定义,详细如下:

pem后缀文件 pe文件格式详解_数组_03

但我们一般只需要关心几个常见的即可,导出表、导入表、资源表、TLS表。详细的我们放到后面再讲。

pem后缀文件 pe文件格式详解_加载_04

根据图片例子,我们把常见的成员变量值列举出来如下:

还需要知道的是,程序的真正入口点 = ImageBase + AddressOfEntryPoint。

节区头由IMAGE_SECTION_HEADER定义,节区头的结构如下。

  • :非必须以NULL结束,也未限制只能使用ASCII,可放入任何值
  • : 内存中节区所占大小
  • : 内存中节区起始地址(RVA)
  • : 磁盘文件中节区所占大小
  • :磁盘文件中节区起始位置
  • :节区属性。

pem后缀文件 pe文件格式详解_pem后缀文件_05

如图所示,可知有四个节区,外加一个全为0的节区。

先看如何定位导入表起始地址,在头中的最后一个成员变量,我们有提到其是一个包含16个元素的数组,其中第2个元素就是导入表的起始位置。

先看的定义

即我们可以通过访问到导入表的起始地址。

再来看一下定义导入表的结构体:

一个程序导入了多少个库就有多少个结构体,这些结构体组成一个数组,且结构体数组以一个全为NULL的结构体作为结束。所以被称为.其中比较重要的成员变量如下(以下地址值全为RVA)

  • :指向INT(导入名称表 、Improt Name Table)的地址,以全NULL结束。
  • :库名称字符串的地址
  • : 指向IAT(导入地址表、Import Address Table)的地址,以全NULL结束。

的值为 即RVA=F5A9C, 换算成RAW则为F4A9C(换算方法见附)。

pem后缀文件 pe文件格式详解_成员变量_06

OriginalFirstThunk - INT (Import Name Table)
第一个成员变量为,它是INT的起始地址,换句话说,就是INT是一个包含导入函数信息的结构体指针数组,每个数组的元素都指向一个的结构体,并以全为NULL的元素结束。根据上图我们知道第一个元素的值为F6284(RVA)->换成RAW则为F5284。来到F5284这个地址.如下。由图可知INT数组长度为5。(以就代表着从这个库文件里面导入了5个函数)

pem后缀文件 pe文件格式详解_成员变量_07

pem后缀文件 pe文件格式详解_pem后缀文件_08

要看懂这个结构得先看下的定义

前两个字节是库中函数的固有编号,后面的则是一个字符数组,以00结束。所以这个导入的函数则是.

Name

根据的结构可知,第四个成员则为,其值为F666A,换成RAW为F566A,我们转到这个地址看下,可知其导入的是SHLWAPI.dll

pem后缀文件 pe文件格式详解_pem后缀文件_09

pem后缀文件 pe文件格式详解_成员变量_10

FirstThunk- IAT (Import Address Table)

由结构体可知其最后一个成员为。根据上面的图可知,第一数组元素的值为C55F4, RAW为:C45F4。我们来到这个地址处:

pem后缀文件 pe文件格式详解_成员变量_11

pem后缀文件 pe文件格式详解_pem后缀文件_12

既然指向同一个地址,为啥需要两个去索引,这是因为需要区分PE加载前还是加载后。如果是加载前,那个IAT跟INT一样,都可以找到依赖的函数名称,如果是加载后。也就是在内存中的话, 那么IAT表保存的就是函数的地址。

PELoader把导入函数输入至IAT的步骤

  • 读取IID的Name成员,获取库名称字符串(eg:kernel32.dll)
  • 装载相应库: LoadLibrary("kernel32.dll")
  • 读取IID的OriginalFirstThunk成员,获取INT地址
  • 逐一读取INT中数组的值,获取相应IMAGE_IMPORT_BY_NAME地址(RVA)
  • 使用IMAGE_IMPORT_BY_NAME的Hint(ordinal)或Name项,获取相应函数的起始地址:GetProcAddress("GetCurrentThreadld")
  • 读取IID的FirstThunk(IAT)成员,获得IAT地址
  • 将上面获得的函数地址输入相应IAT数组值
  • 重复以上步骤4~7,知道INT结束(遇到NULL)

函数查找过程 - GetProAddress工作原理

  • 利用AddressOfNames成员转到“函数名称数组”
  • “函数名称数组”中存储字符串地址。通过比较字符串,查找指定的函数名称(此时数组的索引称为name_index)
  • 利用AddressOfNameOrdinals成员,转到orinal数组
  • 在orinal数组中通过name_index查找相应的值
  • 利用AddressOfFunction成员转到“函数地址数组”
  • 在“函数地址数组”中将刚刚求得的ordinal用作数组索引,获得指定的函数起始地址。

有了导入表的基础,则理解导出表就很简单了,这里就不再举例了。

pem后缀文件 pe文件格式详解_pem后缀文件_13

到此这篇pem文件是什么意思(pe是什么文件夹)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • linux就该这么学电子版(linux就该这么学这本书怎么样)2026-02-19 17:36:04
  • 单播是什么意思主播(直播单播是什么意思)2026-02-19 17:36:04
  • 密码库(密码库在线查询)2026-02-19 17:36:04
  • point和pointat的区别(point at与point to)2026-02-19 17:36:04
  • awvs是什么意思(awq是什么意思)2026-02-19 17:36:04
  • 预训练(预训练权重)2026-02-19 17:36:04
  • 打印控件(lodop打印控件)2026-02-19 17:36:04
  • nvmem.2接口(nvme的两种接口)2026-02-19 17:36:04
  • 网址访问拦截什么意思(网址访问拦截什么意思啊)2026-02-19 17:36:04
  • 网站制作代码怎么写(个人网站的制作代码)2026-02-19 17:36:04
  • 全屏图片