所以我过去几天一直在重新研究PE格式,我还有几个问题
数据部分是否已映射到流程'内存,还是程序从磁盘读取它?
如果确实将其映射到内存中,那么该进程如何获取该部分的偏移量? (和其他部分)
有没有办法获取已经映射到内存中的进程的入口点,而不触及磁盘上的文件?
答案 0 :(得分:5)
数据部分是否已映射到进程'内存
是。这不太可能存活很长时间,该程序很容易写入该部分。这会触发写入时复制页面副本,该页面副本将获取由页面文件而不是PE文件支持的页面。
该过程怎样才能获得该部分的偏移?
链接器已经计算了该部分中变量的偏移量。它可能是重定位的,对于具有笨拙的基址的DLL来说是常见的,这些DLL在加载DLL时已经在使用。在这种情况下,加载器使用PE文件中的重定位表来修补代码中的地址。包含此类修补代码的页面获得与数据部分相同的处理,它们不再由PE文件支持,也不能在进程之间共享。
有没有办法获得流程的入口点
整个 PE文件被映射到内存,包括其标头。因此,您无需读取文件即可从内存中读取IMAGE_OPTIONAL_HEADER.AddressOfEntryPoint。请记住,如果您为另一个进程执行此操作会很痛苦,因为您无法直接访问其虚拟地址空间。你必须使用ReadProcessMemory(),这是相当少的快乐,不可能比读取文件更快。该文件很可能存在于文件系统缓存中。地址空间布局随机化功能很容易让您头疼,旨在使这些事情变得困难。
答案 1 :(得分:1)
数据部分是否已映射到进程的内存中,或程序是否从磁盘读取它?
它映射到进程'内存。
如果确实将其映射到内存中,那么该进程如何获取该部分的偏移量? (和其他部分)
通过重定位表:来自可执行代码的全局对象(数据或函数)的每次引用都使用直接寻址,在此表中有一个条目,以便加载器修补代码,修复原始偏移量。请注意,您可以创建没有重定位部分的PE文件,在这种情况下,所有数据和代码部分都有固定的偏移量,并且可执行文件具有固定的入口点。
有没有办法获取已经映射到内存中的进程的入口点,而不触及磁盘上的文件?
不确定,但是如果“不接触”你的意思是甚至不读文件,那么你可以通过向上走来看出来。
答案 2 :(得分:0)
是的,PE标头中描述的所有部分都会映射到内存中。 IMAGE_SECTION_HEADER
结构告诉加载器如何映射它(该部分可以在内存中比在磁盘上大得多)。
我不太确定我是否明白你在问什么。您是说代码部分的代码如何知道数据部分中的数据访问位置?如果模块在首选加载地址加载,则链接器静态生成的地址是正确的,否则加载器会使用重定位信息修复地址。
是的,Windows加载程序还会将PE Header加载到模块基址的内存中。在那里,您可以归档文件PE头中的所有信息 - 也是入口点。
我可以推荐this article关于PE格式的所有内容,尤其是重定位时。
答案 3 :(得分:0)
数据部分是否已映射到流程中'记忆,或者 程序从磁盘读取它?
是的,Windows或Linux操作系统的动态加载程序执行之前的所有内容都必须映射到内存中。
如果它确实被映射到它的内存中,那么进程如何获取它 该部分的偏移量? (和其他部分)
PE文件具有明确定义的结构,加载器使用该信息并解析该信息以获取ImageBase周围部分的相对虚拟地址。此外,如果在系统上激活了ASLR - 地址随机化功能,则加载程序必须使用重定位信息来解决这些偏移。
有没有办法获得已经进行的进程的入口点 被映射到内存中,而不触及磁盘上的文件?
NOPE,用于计算OEP的操作系统的加载器使用可选头结构的ImageBase + EntryPoint成员值,并且在启用地址随机化时的某些特定位置,它使用重定位表来解析所有地址。因此,如果不解析磁盘上的PE文件,我们就无法做任何事情。