#1 楼
在PE文件中,节通常映射到4kb倍数的地址(这是默认值,尽管可以覆盖)。这意味着即使是单个物理字节长的部分也将为其分配全部4kb的内存。第一部分映射到文件头之后的内存中,因此它将与文件头相距4kb。既然绑定导入表已被弃用,很少有文件头需要使用那么多空间,因此有很多可用空间。 0x100是一个不错的整数,超出了记录的标准标头大小,这就是使用它的原因。#2 楼
简短答案:因为您的普通程序将永远不会访问这些值。长答案:彼得·费里(Peter Ferrie)的答案指出,在该偏移量处通常不存在任何东西。那是不对的。 Portable Executable的最短有效报头长度为0xc8。但这是针对具有单个节的程序,没有导入(或任何其他需要数据目录的东西),没有DOS存根和没有Rich标头(在不修补链接程序的情况下Visual Studio不可能的)。带有导入和两个部分的实际(但仍主要是学术性)程序的最短标头至少为0x160长。添加默认的DOS存根,您位于0x1a0。添加Rich Header,通常为另一个0x30-0x80字节。实际上,您很少会看到标头适合前512个字节的PE。因此,在0x100,您将覆盖数据,但是,一旦加载程序将映像加载到内存中,操作系统就不再使用该数据,因此只要程序也不使用该数据(例如加载资源),会没事的。
可能值得注意的是0x40之后的所有偏移量都是可变的,因此如果不先检查目标二进制文件,您甚至都不知道在0x100处要覆盖什么。由于无论如何都要调用VirtualProtectEx(无论是使数据段可执行还是使代码段可写),因此您最好调用VirtualAllocEx,而不必费心寻找代码陷阱。如果我不得不猜测为什么另一个人总是注入0x100,那是因为那是因为他是从一个已知地址运行的(除非启用了ASLR并且目标二进制文件是可重定位的),所以他不必重新定位注入/使其位置独立之前的代码。这是懒惰,草率和不安全的。
评论
非常棒的解释。为了确保我理解正确,在进入任何其他部分之前,我实际上要使用0x100至0x1000的范围,对吗?最后,我假设我需要通过VirtualProtectEx()使该区域的RWX成为内存。我可以尝试一下,但是只是为了将它扔给以后可能在此线程上发生的任何人。
–dsasmblr
18年8月13日在17:51
是的,在一般情况下,您可以使用0x0100至0x0FFF;是的,在一般情况下,您需要VirtualProtectEx()使标头可写。
–彼得·弗里
18年8月27日在21:16