我正在尝试获取 .text 部分的标题。 似乎有效的是:
// 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);
以便指针按节标题方向移动。
另外,
(pNtHeaders->FileHeader.NumberOfSections - 1)
真的是.text部分吗?
原因
pLastSectionHeader = pSectionHeader + (pNtHeaders->FileHeader.NumberOfSections - 1);
是正确的,
pSectionHeader
是PIMAGE_SECTION_HEADER
类型。当您将整数值添加到 C 中的指针时,该值将首先乘以所指向对象的大小(即 IMAGE_SECTION_HEADER
)。这就是指针算术的工作原理!
您不应假设链接器放置不同部分的顺序。最好循环遍历所有节标题,例如将部分名称与
.text
匹配。
另外,我不建议使用
sizeof(IMAGE_NT_HEADERS)
来跳过可选标题。这是因为 IMAGE_OPTIONAL_HEADER
结构(包含在 IMAGE_NT_HEADERS
中)以 IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
结尾,并且您实际上无法保证所有数据目录都存在于 PE 映像中。更好的方法是读取可选标头,并使用 NumberOfRvaAndSizes
字段来确定应跳过多少个数据目录来查找节标头表。
最后,我建议您使用
IMAGE_XYZ32
和 IMAGE_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);
.text
部分并不总是.text
。
请注意这一点:
PE 文件部分有一个
IMAGE_SCN_CNT_CODE
标志。为什么不使用它?
请注意
sizeof(IMAGE_NT_HEADERS)
仅获取分配所需的字节,请改用IMAGE_NT_HEADERS->FileHeader.SizeOfOptionalHeader + sizeof(IMAGE_FILE_HEADER) + sizeof(DWORD)
。
检查代码(C代码):
PIMAGE_NT_HEADERS NtHeaders = (PIMAGE_NT_HEADERS)(hMod + ((PIMAGE_DOS_HEADER)hMod)->e_lfanew);
PIMAGE_SECTION_HEADER SectionHeaders = IMAGE_FIRST_SECTION(NtHeaders);
PIMAGE_SECTION_HEADER codeSection2;
for (WORD SectionIndex = 0; SectionIndex < NtHeaders->FileHeader.NumberOfSections; SectionIndex++)
{
PIMAGE_SECTION_HEADER SectionHeader = &SectionHeaders[SectionIndex];
if (SectionHeader->Characteristics & IMAGE_SCN_CNT_CODE){
codeSection2 = SectionHeader;
break;
}
}
IMAGE_SECTION_HEADER codeSection = *codeSection2;