OptionalHeader 后的空数据

Empty data after OptionalHeader

我正在研究 PE 解析器,仅用于学习目的。 正如文档所说,第一部分 header 应该紧跟在 OptionalHeader 之后,但就我而言,在第一个 header 之前我有很多空数据。 这是我计算第一部分应该放在哪里的代码:

IMAGE_NT_HEADERS* inth = get_nt_headers(buffer);

DWORD optional_headers_size = inth->FileHeader.SizeOfOptionalHeader;
DWORD calculated_ptr = (DWORD)inth + optional_headers_size;

printf("Pointer to IMAGE_NT_HEADERS: %p\n", inth);

printf("Size of optional headers: %x\n", optional_headers_size);

printf("Pointer to first section header: %p\n", calculated_ptr);

BYTE* pointer = (BYTE*)calculated_ptr;

当我遍历 'pointer' 时,我看到很多可为 null 的数据,因此这不是我需要的部分。 PEView 或 Hexplorer 也显示空数据。这是为什么? 这'nullable'部分数据大约需要24个字节。

我分析的应用程序很简单HelloWorld.exe。

我对一件事感到困惑。

在 FileHeader 中,我设置了 13 个部分,但是如果我在 IMAGE_OPTIONAL_HEADER 中查看 PEView,我会看到 16 个部分,但最后 3 个部分有任何分配的值,这意味着 RVA 和 Size被设置为 0。 这些部分是:DELAY_IMPORT_DESCRIPTORS、CLI_HEADER,但最后一个没有任何名称。

我算了一下最后这三个section的大小是24字节。 这与我之前提到的完全相同。

那么我如何计算第一个 IMAGE_SECTION_HEADER?

问题已解决,但我不确定我的解决方案。

DWORD padding = (IMAGE_NUMBEROF_DIRECTORY_ENTRIES - inth->FileHeader.NumberOfSections) * sizeof(IMAGE_DATA_DIRECTORY);
DWORD calculated_ptr = (DWORD)inth + padding + optional_headers_size;

首先 - 永远不要在指针中使用 DWORD。这是错误。 DWORD 始终为 4 字节大小,当指针为 4 或 8 时。代码如

DWORD calculated_ptr = (DWORD)inth + optional_headers_size;

总是错的。您可以使用 DWORD_PTR(恰好是指针大小)代替 DWORD.

然后 SizeOfOptionalHeader IMAGE_OPTIONAL_HEADER 的大小很容易理解,它是 IMAGE_NT_HEADERS 部分 。但是这样的代码

DWORD_PTR calculated_ptr = (DWORD_PTR)inth + inth->FileHeader.SizeOfOptionalHeader; 使用 SizeOfOptionalHeader 作为 IMAGE_NT_HEADERS 的大小。您只是将 IMAGE_NT_HEADERS 的大小与 IMAGE_OPTIONAL_HEADER

的大小混淆了

所以正确的解决方案是

    PIMAGE_SECTION_HEADER pish = (PIMAGE_SECTION_HEADER)(
        (ULONG_PTR)&inth->OptionalHeader + inth->FileHeader.SizeOfOptionalHeader);

需要将 SizeOfOptionalHeader 添加到 inthPIMAGE_NT_HEADERS 的地址),而是添加到 &inth->OptionalHeader

或更好地使用PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(inth);

IMAGE_FIRST_SECTION - 这是在 winnt.h 中定义的现成宏,与 (PIMAGE_SECTION_HEADER)((ULONG_PTR)&inth->OptionalHeader + inth->FileHeader.SizeOfOptionalHeader);

具有相同的效果(生成相同的代码)