如果我们有 IMAGE_IMPORT_DESCRIPTOR,那么 IAT 是多余的吗?

逆向工程 视窗 聚乙烯 文件格式 二进制格式
2021-06-10 03:36:32

由于每个IMAGE_IMPORT_DESCRIPTOR已经指向已解析虚拟地址的 RVA,因此 IAT 似乎是多余的。为什么包含这个数据目录?如果我覆盖 IAT 数据目录的 RVA/大小,二进制文件仍然能够正常运行。

我错过了什么吗?是否存在 IAT 数据目录对运行二进制文件至关重要的情况?

1个回答

首先,澄清几点

导入地址表是一个表,仅由导入函数的地址。Import Table(由IMAGE_IMPORT_DESCRIPTORs组成)不同,它也详细说明了在何处查找这些导入。

重申:(这是略微简单化)导入地址表是导入的功能的实际地址在存储器中的当前处理的阵列。不分为模块,没有像序数或名称这样的额外信息。只是所有导入函数的地址的数组。

这些IMAGE_IMPORT_DESCRIPTORS方式更加结构化,干净和分区。它们使加载程序能够找到它正在寻找的函数。在你称他们为“已解决的虚拟地址的RVAs”(实际上有两个,Characteristics并且FirstThunk,在IMAGE_IMPORT_DESCRIPTOR结构)没有指向远程DLL其实际进口的功能,但在该位置导入地址表中的第一项目中IMAGE_IMPORT_DESCRIPTOR相同IMAGE_IMPORT_DESCRIPTOR的后续项目也是导入地址表中的以下项目

当加载器遍历sIMPORT_TABLE和不同的IMAGE_IMPORT_DESCRIPTORs 时,它解析每个函数并将该函数的最终地址放置在该函数指定的导入地址表位置。FirstThunk是加载器如何知道IMAGE_IMPORT_DESCRIPTORs 中描述的函数的导入地址表位置

但为什么?(又名回答你的问题)

因此,大家可以看到,FirstThunk仅持有一个地址多个导入功能,它只指向的地址(而不是直接作为你的问题暗示抱着它),所以我们不能轻易“使用的thunk”代替的进口地址表

至于为什么您可以为磁盘上的 PE 覆盖 IAT 中的实际内容并且一切仍然有效 - 这是隐式回答的,但我也会明确回答。磁盘上的数据与Characteristics结构中的数据相同,指针相同。然而,根据 Microsoft 自己的文档,不应实际读取该数据,IAT 主要是在 PE 加载过程中填充的。我猜想用相关数据初始化它的原因是开发人员对“为什么不呢”的想法。

但是,为什么?

现在,如果你一直在关注,你应该问一个类似的问题(你问过,这就是这个问题的大致内容):

该结构仍然比它本来的复杂,并且导入地址表以压缩方式创建(而不是作为地址包含在不同IMPORT_NAME或其他类似结构中)的主要原因实际上是优化。

我很高兴你问了!;) 我会解释的。

您可能知道,DLL 被有效地加载到相同的地址,并使用称为“写时复制”的 Windows 机制实际上只有大多数模块的单个副本。当模块映射到不同的虚拟地址时也是如此。但是,当需要为模块填充导入的函数时,需要写入 PE 结构。无论你在哪里持有地址,它都必须改变。导入地址表是那里只触发写时复制了为几页地(这些是实际导入地址表页面本身)。

顺便说一下,这也是 PE 中存在额外的间接级别的部分原因。