正如我在PE
文件中所理解的,虚拟大小显示了在加载过程中为节分配了多少空间,而原始大小显示了该节在磁盘上的大小。
我遇到了这个执行以下内容的可执行文件:
从原始数据大小(offset 0x8
)中减去虚拟大小(offset 0x10
),并确保有一些空间(例如100个字节)。在文本部分标题的偏移0x14
处,它在文件中找到了该部分本身的偏移量。它添加了虚拟大小,找到该部分在文件中结束的位置。它复制了一些shellcode(最后跳转到可执行文件的原始入口点以确保原始可执行文件运行)到二进制文本部分的末尾。
现在我有点困惑,如果虚拟大小显示将为可执行文件分配的确切空间,则不会在.txt
部分末尾添加代码覆盖可执行文件的其他一些数据并生成它崩溃了吗?感谢。
答案 0 :(得分:1)
嗯,这个黑客代码看起来很容易隐藏各个部分之间的恶意代码。
回答你的问题,你是对的VirtualSize是真正在内存中分配的空间,RawSize是磁盘上用来保存段数据的空间。 您错过的是(来自MS PECOFF规范):
VirtualSize
:加载到内存中的部分的总大小。如果此值大于SizeOfRawData
,则该部分为零填充。此字段仅对可执行映像有效,对于目标文件应设置为零。
这意味着如果SizeOfRawData
- VirtualSize
的结果是肯定的,我们在磁盘上有一些可用空间实际填充0 。
如果该空间足以容纳恶意代码,然后使用VirtualSize
在磁盘上添加文本开头部分,则可以获得可用于复制代码的0的填充区域的开头。
剩下的就是故事......
答案 1 :(得分:1)
这是一个很好的问题,并说明了Windows加载程序如何计算内存大小的一个非常重要的观点(或者你可能会说是怪癖)。
PE / COFF规范确实将VirtualSize描述为"当加载到内存中时该部分的总大小"。如果您认为总数是构成该部分的REAL数据的总量,则这在技术上是正确的,但它不是Windows为该部分分配的内存总量。您会发现VirtualSize通常比Windows为内存中的部分分配的数量少,因为必须将VirtualSize四舍五入到最接近的内存对齐值(在PE映像中设置)。
换句话说,VirtualSize表示节的未包围大小,而SizeOfRawData是图像文件中数据的大小,但向上舍入到最近的文件对齐填充值。这就是为什么VirtualSize更能代表真正的" raw"数据大小,在内存或磁盘上。 PE / COFF规范没有做出这种区分。为什么一个在图像文件中被舍入而另一个可能在向后兼容性方面具有古老的根源。
这正是您的shellcode使用VirtualSize查找" real"数据结束,即使它位于图像文件中。毫不奇怪,您可以通过将VirtualSize四舍五入到文件对齐的值来计算SizeOfRawData,至少在格式良好的PE文件中。
shellcode只是使用VirtualSize来查找REAL代码的结尾。在那里和SizeOfRawData字节之间,只是未使用的填充零,使其成为添加新代码的主要位置,而不会影响文件的大小或破坏PE文件中的寻址偏移。
总之,Windows加载器基本上采用VirtualSize值并将其四舍五入到内存对齐值以获得内存分配的实际大小(甚至可以将其四舍五入到最接近的4k最小内存页)。然后将SizeOfRawData字节从文件复制到内存部分的开头。如果它小于内存中节的大小,则余数为零。