关于Windows:PE文件中的节和数据目录之间是什么关系?

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

我试图更好地理解PE格式,并且想知道PE文件中节与数据目录之间的关系是什么。打开PE文件时,我注意到它们经常重叠,但是我不清楚它们为什么或如何关联,而且Microsoft的官方PE文件格式规范似乎并没有使它变得更加清晰。

我了解到节头的名称值可以更改,因此不能保证对特定块的引用,因此应依赖这些数据目录在文件中查找特定块。 >

在我打开的一个示例PE文件中,我注意到.text节具有与Import Address Table数据目录头相同的偏移量,尽管IAT大小被列为8,而.text节的大小是6804。相反,资源数据目录标头指出它始于16384,长度为1568,与.rsrc节的条目精确吻合。后者对我来说很有意义,而前者则没有。

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


部分用于打包具有几乎相同的内存保护的东西。

例如,以calc.exe为例:

enter

1
IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ

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

1
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ

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

引用Matt Matt Tretrek的精彩文章分为两部分:"深入了解Win32便携式可执行文件格式"(可在此处(1/2)(2/2),此处(1/2)找到) (2/2)和.chm格式(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保护,通常是这样:这就是为什么在某些情况下您可能会将导入表放入代码部分的原因(即使强悍,导入表显然也不打算执行) )。由于您只能阅读代码并导入部分(不能写入它们),因此链接程序将它们合并到同一部分中就足够了。

来自同一篇文章:

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.

AFAIK,资源(.rsrc)和重定位(.reloc)节始终保持单独状态。之所以单独保留资源部分,可能是因为某些API依赖它。

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