我正在实现一个用于执行某些PE分类的软件。我从每个PE收集的功能值包括部分的数量,部分的名称,图像部分的标题。

我一直在阅读有关ImageHlp结构的信息。但是,没有关于如何从传递的文件/ path_to_a_file中初始化那些结构的示例。我对IMAGE_SECTION_HEADER结构特别感兴趣。

如何以编程方式从可执行文件中获取IMAGE_SECTION_HEADER?

评论

PE格式有据可查。手动解析文件。尽管示例在python中,但该页面可以作为参考。除此之外,您可以使用预构建的解析器库,例如pe-parse

#1 楼

我在Windows上解析PE方面具有丰富的经验,主要用于函数拦截。以下是实现目标所应遵循的步骤。

第一步是找到加载到内存中的图像的基地址。根据可执行文件是否已映射到内存,此步骤将有所不同,但是基本思路是相同的。假设您有兴趣对磁盘上的文件执行此操作,则可以使用文件映射API进行此操作,如果您希望在作为运行进程加载到内存的可执行文件上实现此功能,则可以通过使用工具帮助快照API。基址将与从快照检索到的hModule数据中的字段MODULEENTRY32相同。有关模块句柄是什么的更多信息,请参见此处。

完成第一步后,基地址的结构为IMAGE_DOS_HEADER,尽管MSDN上未对此进行记录,但它具有两个非常重要但神秘的领域。您将需要知道的两个字段是e_magic字段和e_lfanew字段。 e_magic字段包含一个用于32位的双字或一个用于64位的四字,可让您测试是否正在读取文件或实现是否被正确格式化,且正确的值定义为IMAGE_DOS_SIGNATURE,即ASCII-Z字符串“ MZ \ 0”。 e_lfanew字段包含一个相对虚拟地址,您需要将该相对虚拟地址添加到在第一步中找到的映像库中,以计算IMAGE_NT_HEADERS结构的虚拟地址。

第三步将检查第一个成员IMAGE_NT_HEADERS的值以查看它是否是实际的PE文件,这将由结构的Signature字段定义,并且要测试的已定义常数将为IMAGE_NT_SIGNATURE。通常这不是必需的,因为大多数Windows版本将使用可执行文件的PE格式,但这是一种很好的做法,可以确保您的代码更加健壮。

一切检查完毕并执行了步骤1-3后,第四步即是您终于可以计算出IMAGE_SECTION_HEADER结构的地址了。 IMAGE_SECTION_HEADER结构以数组形式存储在文件中,因此要获取数组的大小,您将需要使用嵌套在上述NumberOfSections结构中的IMAGE_FILE_HEADER结构中的IMAGE_NT_HEADERS成员。通过添加IMAGE_SECTION_HEADER结构的Signature成员的大小,IMAGE_NT_HEADERS结构中的FileHeader成员的大小以及最后IMAGE_NT_HEADERS结构中的SizeOfOptionalHeader值,可以找到第一个IMAGE_FILE_HEADER的虚拟地址。您不能简单地对上面列出的公式中的最后一个值执行sizeof( IMAGE_OPTIONAL_HEADER )的原因是因为磁盘上的文件将没有IMAGE_OPTIONAL_HEADER,因此要动态获取适当的大小,您应该通过结构成员I前面已经提到过。

现在,您可以随意从内存中复制IMAGE_SECTION_HEADER结构数组。请记住,这些结构在内存中是连续的,因此您要做的就是将每个结构的大小乘以段数,以找到内存中整个数组的总大小。计算完该值之后,收集数据将变得很简单。

有关PE可执行格式的更多资源,请参见PE深入PE中的Matt Pietrek撰写的精彩文章。您也可以在这里查看官方规格。

评论


努力,但有许多小问题。 1)DOS标头的e_magic始终是一个WORD(16位),不能是32或64位; 2)IMAGE_DOS_SIGNATURE与两个字符的“ MZ”序列匹配-不需要零终止符; 3)严格来说,e_lfanew是文件偏移量而不是RVA(尽管在这种情况下它们恰好匹配); 4)IMAGE_OPTIONAL_HEADER确实存在于磁盘上的文件中,它并不是仅仅因为您使用文件映射而神奇地出现; 5)之所以需要使用SizeOfOptionalHeader,是因为某些恶意软件/打包程序使用的值与sizeof(IMAGE_OPTIONAL_HEADER)不同。

–伊戈尔·斯科钦斯基♦
2014年8月15日23:05

@Igor糟糕,我在想一个目标文件。我的错。

–船长很明显
2014年8月15日23:12



提到的“文件映射API”仅适用于Windows。各种来源都对PE格式进行了详细描述,实际上并不需要使用Windows API-例如,我在Mac上从头开始编写了最新的PE反汇编程序。

–杂件
2014年8月15日在23:13

@Jongware好吧,如果他愿意的话,他总是可以使用一些第三方库以更可移植的方式解析PE。 Windows是我使用的唯一操作系统,因此如果有人想为其他系统提供答案,请随意。他发布的参考资料适用于Windows实现,因此我这样回答了这个问题。

–船长很明显
2014年8月15日在23:18

是的,您是正确的,OP确实似乎正在使用Windows。我的load_exec源代码是(..检查)接近300行代码,它使用了结构和#define的另外250行左右。总而言之,仅加载可执行文件就需要大约2,000行C代码(注意,它还显示了大量的调试数据)。对于RE回答,我可能会冒太多的危险。

–杂件
2014年8月15日在23:28