获取 PE 文件的 .text 部分 header

Getting .text section header of PE file

我正在尝试获取 .text 部分的 header。 似乎起作用的是:

// Get the DOS header.
pDosHeader = (PIMAGE_DOS_HEADER) hMap;

// Get header of first section
pSectionHeader = (PIMAGE_SECTION_HEADER) ((DWORD) hMap + pDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS));

// Get last section's header.
pLastSectionHeader = pSectionHeader + (pNtHeaders->FileHeader.NumberOfSections - 1);

但我不明白为什么。我本以为最后一条指令必须是:

// Get last section's header.
pLastSectionHeader = pSectionHeader + (pNtHeaders->FileHeader.NumberOfSections - 1) * sizeof(IMAGE_SECTION_HEADER);

使指针移动 section-header-wise。

此外,(pNtHeaders->FileHeader.NumberOfSections - 1) 真的是 .text 部分吗?

的原因
pLastSectionHeader = pSectionHeader + (pNtHeaders->FileHeader.NumberOfSections - 1);

是正确的,就是pSectionHeaderPIMAGE_SECTION_HEADER类型。当您在 C 中将一个整数值添加到一个指针时,该值将首先乘以所指向的 object 的大小(即 IMAGE_SECTION_HEADER)。这就是指针算法的工作原理!

您不应假设链接器放置不同部分的顺序。最好遍历所有 header 部分,例如将部分名称与 .text.

匹配

此外,我不建议使用 sizeof(IMAGE_NT_HEADERS) 来跳过可选的 header。这是因为 IMAGE_OPTIONAL_HEADER 结构(包含在 IMAGE_NT_HEADERS 中)以 IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; 结尾,您实际上无法保证所有数据目录都存在于 PE 映像中。更好的方法是读取可选的 header,并使用 NumberOfRvaAndSizes 字段来确定您应该跳过多少个数据目录以找到 header table.[=24 部分=]

最后,我建议您使用结构的 IMAGE_XYZ32IMAGE_XYZ64 版本,而不仅仅是 IMAGE_XYZ,这取决于您是否要解析 PE32 (32-位)或 PE32+(64 位)。否则,您将默认使用系统默认的体系结构大小。

给你:

// Get DOS and PE Header
PIMAGE_DOS_HEADER hdos = (PIMAGE_DOS_HEADER)pe_file.data();
PIMAGE_NT_HEADERS hpe = (PIMAGE_NT_HEADERS)((DWORD)hdos + hdos->e_lfanew);

// Get header of first section
DWORD section_offset = (DWORD)hdos + hdos->e_lfanew + sizeof(IMAGE_NT_HEADERS);
PIMAGE_SECTION_HEADER text_section = (PIMAGE_SECTION_HEADER)(section_offset);