【问题标题】:64-Bit PE File without Import Lookup Table没有导入查找表的 64 位 PE 文件
【发布时间】:2019-05-14 14:34:23
【问题描述】:

我有一个用于 Windows 的 64 位 hello world 应用程序。它是使用平面汇编程序(fasm)创建的。我没有源代码了,但这是一个非常简单的例子,它调用:

  1. MessageBoxA()
  2. 退出进程()

我在PE编辑器(CFF Explorer)中打开文件,看到:“导入目录表”中“导入查找表”的RVA为0x0。尽管如此,“导入地址表”RVA 仍然存在,包含指向 API 名称的指针,并且 Windows 10 启动程序时没有任何抱怨。

我的问题是:是否存在定义这种二进制文件的 PE 规范?其他编译器是否具有相同的行为?是PE+的东西吗?

从技术上讲,缺少“导入查找表”没什么大不了的,因为“导入地址表”中提供了相同的数据(尽管被 PE 加载程序覆盖)。但 Microsoft 文档 (https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#the-idata-section) 并未涵盖此类 .idata 部分。

【问题讨论】:

  • 在技术上是可行的,导入可以通过名称或序数(一个简单的数字)来定义。使用序数时不需要查找表。这是不寻常的,但是您不能再向我们展示您的导入语句,并且对链接器只字未提。最好不要纠结于此。
  • 澄清事情:这不是“按名称导入”与“按序号导入”。 “导入查找表”和“导入地址表”中的每个条目都可以是指向名称或序数的指针(取决于是否设置了最后一位)。我的问题是:应该有两个具有相同值的表(根据 MS 文档),但只有“导入地址表”存在。
  • 我怀疑您弄错了,或者 CFF Explorer 向您显示了错误的数据。导入目录表中应该有三个条目,一个用于 USER32.DLL,一个用于 KERNEL32.DLL,一个空的,所有零值标记表的结尾。这三个条目中的每一个都有自己的“导入查找表 RVA”和“导入地址表 RVA”值。

标签: assembly 64-bit portable-executable fasm


【解决方案1】:

我正在编写一些解析 .EXE 文件的工具,我也见过这样的 .EXE 文件。

您链接的 Microsoft 文档中暗示了此类文件存在的原因:

导入查找表的 RVA。 ...(Winnt.h 中使用了名称“Characteristics”,但不再描述该字段。)

对我来说,括号中的句子和“不再”意味着旧的 Windows 版本使用“导入查找表的 RVA”字段来存储不同类型的信息,因此为这些 Windows 版本编写的 .EXE 文件具有没有导入查找表。

而且由于较新的 Windows 版本应该能够运行旧的可执行文件,最近的 Windows 版本似乎仍然接受使用该字段获取其他信息的可执行文件。

另一方面,一些链接器或编译器似乎仍然用零填充这个字段,因为 Windows 在这里仍然接受零值。

但是,据我了解,只有 32 位版本的 Windows 使用此字段来存储不同类型的信息。如果这是真的,那么只有将此字段设置为零的 32 位 .EXE 文件(为旧 Windows 版本编写)才有效。

这意味着 Microsoft 将来可能会禁用对此字段设置为零的 64 位 .EXE 文件的支持。这意味着 64 位链接器或编译器将此字段设置为零是错误的。

【讨论】:

  • 谢谢,很高兴知道我不是唯一一个看过这种文件的人:)
  • 不,该字段绝对可以为零。这只是随着链接器/加载器中添加的功能而改变的含义。
【解决方案2】:

您正在查看本机图像(仅导入 ntdll),您已经绑定了导入,或者您正在延迟加载所有内容。或者您使用的查看器不能处理 PE32+,它在可选标头中缺少字段。

编辑:我重新阅读了这个问题。如果您查看导入表条目中的时间戳,它可能不为零,表示绑定导入。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多