IMAGE_IMPORT_DESCRIPTOR
已经指向解析的虚拟地址的RVA,因此IAT似乎是多余的。为什么要包含此数据目录?如果我覆盖IAT数据目录的RVA /大小,则二进制文件仍然可以正常运行。我遗漏了什么吗?是否存在IAT数据目录对二进制文件运行至关重要的情况?
#1 楼
首先,有几点说明导入地址表是仅由导入函数的地址组成的表。与
Import Table
(由IMAGE_IMPORT_DESCRIPTOR
组成)不同,IMAGE_IMPORT_DESCRIPTORS
也包含在哪里查找这些导入的详细信息。重申一下:(这有点过分简化了)Import Address Table是导入函数在内存中实际地址的数组。当前的过程。不分为模块,没有其他信息(如序数或名称)。只是所有导入函数的地址的数组。
Characteristics
的结构,清理和分区方式更加合理。它们使加载程序能够找到所需的功能。您所称的“已解析虚拟地址的RVA”(在FirstThunk
结构中实际上有两个IMAGE_IMPORT_DESCRIPTOR
和IMAGE_IMPORT_DESCRIPTOR
)不是指向远程DLL中的实际导入功能,而是指向导入地址表中的位置该IMAGE_IMPORT_DESCRIPTOR
中的第一项。相同的IMPORT_TABLE
中的后续项目也是导入地址表中的以下项目。表格位置。 IMAGE_IMPORT_DESCRIPTOR
是加载程序如何知道FirstThunk
s中描述的函数的导入地址表位置的原因。为什么? (又是回答您的问题)
因此,如您所见,
IMAGE_IMPORT_DESCRIPTOR
仅为多个导入功能保存一个地址,并且仅指向该地址(而不是如您的问题所暗示的那样直接保存该地址),因此我们可以轻松地“使用thunk”而不是“导入地址表”。至于为什么您可以覆盖磁盘上PE的IAT中的实际内容,而所有内容仍然可以工作-隐式回答,但我也将明确回答。磁盘上的数据与
FirstThunk
结构中的数据相同,指针相同。但是,永远不要根据Microsoft自己的文档实际读取数据,IAT通常是在PE加载过程中填充的。我想用相关数据初始化它的原因有点像是开发人员的想法。但是,为什么呢?您应该问一个类似的问题(实际上,这就是该问题的大致含义):
该结构仍然比以前复杂得多,这是在压缩方式(而不是作为地址包含在不同的
Characteristics
或其他类似结构中)实际上是一种优化。很高兴您问到! ;)我会解释。
您可能知道,DLL被有效地加载到相同的地址中,并使用称为写入时复制的Windows机制来实际上仅具有大多数模块的单个副本。当模块映射到不同的虚拟地址时,也是如此。但是,当需要为模块填充导入的功能时,则需要写入PE结构。无论您在哪里存放地址,都必须更改。导入地址表仅用于触发尽可能少的页面写时复制(即实际的“导入地址表”页面本身)。
这部分是由于存在额外的级别PE中的间接访问从此开始。
评论
我已经很长时间没有使用PE格式了。但是,如果我没记错的话,IAT目录会将RVA保存到导入地址表中。该表包含每个导入函数的地址。假定DLL加载在其首选地址处,则可以用函数的RVA填充它。但是,如果两个DLL具有重叠的虚拟地址,则系统可能必须将DLL加载到其他地址,在这种情况下,它将对其进行重新定位,并且IAT中的地址将是错误的。我认为在这种情况下,加载的PE会在加载时覆盖IAT。请不要在评论中回答,谢谢。