PE数据目录表解析

2021-12-09 17:53:27 浏览数 (1)

前言

代码语言:javascript复制
看雪链接:
https://bbs.pediy.com/thread-270585.htm

接着学习PE结构解析。

写的过程中总结一下常用到的基础知识:

  • 基地址(ImageBase):当PE文件通过Windows加载器载入内存后,内存中的版本称为模块,映射文件的起始地址称为模块句柄,可通过模块句柄访问内存中其他数据结构,这个内存起始地址就称为基地址。
  • 虚拟地址(VA):在Windows系统中,PE文件被系统加载到内存后,每个程序都有自己的虚拟空间,这个虚拟空间的内存地址称为虚拟地址。
  • 相对虚拟地址(RVA):可执行文件中,有许多地方需要指定内存中的地址。例如,应用全局变量时需要指定它的地址。为了避免在PE文件中出现绝对内存地址引入了相对虚拟地址,它就是在内存中相对于PE文件载入地址的偏移量。

它们之间的关系:虚拟地址(VA) = 基地址(Image Base) 相对虚拟地址(RVA)

  • 文件偏移地址(Offset):当PE文件存储在磁盘中时,某个数据的位置相对于文件头的偏移量称为文件偏移地址(File Offset)。文件偏移地址从PE文件的第一个字节开始计数,起始值为0。

数据目录表结构

数据目录表是PE中比较重要的一个部分,其也是一个结构。微软在Microsoft Virtual Studio在对其结构又定义。

代码语言:javascript复制
typedef struct _IMAGE_DATA_DIRECTORY {
    DWORD   VirtualAddress; //虚拟地址,就是数据目录表的起始位置
    DWORD   Size;//尺寸, 起始地址 尺寸 = 结束的位置
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

结构如下:

用loadPE打开一个PE文件,点击目录,即可看到数据目录表,再点击每个表对应可以展开的按钮,即可看到相应参数对应的值,

比如点开输入表,可看到调用了哪些动态链接库,又在动态链接库里调用了哪些API:

为了加深理解,下面对一些重要的表进行学习解析。

地址转换函数

解析这些表之前,先写一个地址转换函数,就是将相对虚拟地址(RVA)转换为文件偏移地址(Offset)。

那么为什么要写这样一个函数呢?因为一些PE文件为了减小体积,磁盘对齐值不是一个内存页1000h,而是200h。当这类文件被映射到内存中后,同一数据相对于文件头的偏移量在内存中和磁盘文件是不同的,这样就出现了文件偏移地址和虚拟地址的转换问题。当然,那些磁盘对齐值与内存对齐值相同的区块,同一数据在磁盘文件中的偏移与在内存中的偏移相同,因此不需要转换。

如图,当文件被映射到内存中时,MS-DOS头,PE头和块表的偏移位置都没有改变,但是当区块被映射到内存中后,其偏移地址就发生了改变。

文件偏移地址(Offset)为add1 ,相对虚拟地址(RVA)为add2。它们直接相差了一个以0填充的空白区域,假设这个值为

0 人点赞