PE文件中section和数据目录是什么关系?

What is the relationship between sections and data directories in a PE file?

我试图更好地理解 PE 格式,我想知道 PE 文件中的节和数据目录之间的关系。打开一个 PE 文件,我注意到它们经常重叠,但我不清楚为什么,或者它们是如何关联的,微软的官方 PE 文件格式规范似乎并没有真正说明这一点。

我知道部分 header 的名称值可以更改,因此不能保证对特定块的引用,因此应依赖数据目录来查找特定块在文件中。

在我打开的示例 PE 文件中,我注意到 .text 部分与导入地址 Table 数据目录 header 具有相同的偏移量,尽管 IAT 大小列为 8,而 .text 部分大小为 6804。相比之下,资源数据目录 header 声明它从 16384 开始,长度为 1568 - 与 .rsrc 部分的条目完全一致。后者对我有意义,前者对我来说没有意义。

那么节与数据目录的不同用途是什么?为什么这两个概念都存在,为什么它们有时会重叠,而它们似乎没有意义?

节旨在用 "nearly" 相同的内存保护来打包东西。

例如让我们calc.exe:

这里的代码段有段保护(IMAGE_SECTION_HEADER.Characteritics)设置为0x60000020:

IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ

.idata 部分(导入部分)的值为 0x40000040:

IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ

在某些情况下,链接器可能会决定将相同的内存保护应用于不同的部分并将它们合并在一起(您可以使用 /MERGE 链接器选项强制执行此设置)。

引用 Matt Pietrek 的精彩文章 "An In-Depth Look into the Win32 Portable Executable File Format"(可在此处 (1/2) (2/2), here (1/2) (2/2) and in .chm format (1/2) (2/2) 找到):

If two sections have similar, compatible attributes, they can usually be combined into a single section at link time

如果这些部分共享相同的 IMAGE_SCN_MEM_READ / IMAGE_SCN_MEM_WRITE 保护,这通常是正确的:这就是为什么在某些情况下您可能将导入 table 到代码部分(甚至很难import table 显然不打算执行)。由于您只能阅读代码和导入部分(您不能写入它们),这足以让链接器将它们合并到同一部分。

来自同一篇文章:

For example, it's OK to merge .rdata into .text, but you shouldn't merge .rsrc, .reloc, or .pdata into other sections. Prior to Visual Studio .NET, you could merge .idata into other sections. In Visual Studio .NET, this is not allowed, but the linker often merges parts of the .idata into other sections, such as .rdata, when doing a release build.

据我所知,资源 (.rsrc) 和重定位 (.reloc) 部分始终保持独立。资源部分单独保留的原因可能是因为 some APIs 依赖它。

另一方面,数据目录告诉您在哪里可以找到 PE 文件的重要部分(导入、导出、调试、TLS、资源、重定位等),即使合并了不同的部分,您仍然可以找到相关数据。