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
添加到 inth
(PIMAGE_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);
具有相同的效果(生成相同的代码)
我正在研究 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
添加到 inth
(PIMAGE_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);