PE:在 .txt 部分末尾添加代码
PE: Adding code at the end of .txt section
据我了解,在 PE
文件中,虚拟大小显示了它在加载期间为部分分配了多少 space,而原始大小显示了该部分在磁盘上的大小。
我遇到了这个执行以下操作的可执行文件:
它从原始数据大小 (offset 0x10
) 中减去虚拟大小 (offset 0x8
) 并确保有一些 space(例如 100 字节)。在距文本部分 header 的偏移量 0x14
处,它在文件中找到了该部分本身的偏移量。它将虚拟大小添加到此,找到该部分在文件中结束的位置。它复制了一些 shellcode(最终跳转到可执行文件的原始入口点以确保原始可执行文件运行)到二进制文件文本部分的末尾。
现在我在这里有点困惑,如果虚拟大小显示将分配给可执行文件的确切 space,不会在 .txt
部分末尾添加代码覆盖一些其他数据的可执行文件并使其崩溃?谢谢。
嗯嗯,这个黑客代码似乎是精心设计来隐藏各部分之间的恶意代码。
关于您的问题,您是正确的 VirtualSize 是真正分配在内存中的 space,而 RawSize 是磁盘上用于保存节数据的 space。
你错过的是(来自 MS PECOFF 规范):
VirtualSize
: The total size of the section when loaded into memory. If this value is greater than SizeOfRawData
, the section is zero-padded. This field is valid only for executable images and should be set to zero for object files.
这意味着 如果 SizeOfRawData
-VirtualSize
的结果为正,我们在磁盘上有一些可用的 space 实际上填充了 0.
如果 space 足以容纳恶意代码,则在磁盘上添加带有 VirtualSize
的文本部分的开始,您可以获得可用于复制的 0 填充区域的开始代码。
剩下的就是故事了...
这是一个很好的问题,说明了关于 Windows 加载程序如何计算内存大小的一个非常重要的观点(或者你可能会说怪癖)。
PE/COFF 规范确实将 VirtualSize 描述为 "The total size of the section when loaded into memory"。如果您认为 total 是包含该部分的 REAL 数据总量,这在技术上是正确的,但它不是分配给该部分的内存总量 Windows。您会发现 VirtualSize 通常小于 Windows 为内存中的部分分配的数量,因为 VirtualSize 必须四舍五入到最接近的内存对齐值(在 PE 映像中设置)。
换句话说,VirtualSize 表示部分的未舍入大小,而 SizeOfRawData 是图像文件中数据的大小,但舍入到最接近的文件对齐填充值。这就是 VirtualSize 是内存或磁盘上数据真实 "raw" 大小的更好表示的原因。 PE/COFF 规范没有做出这种区分。为什么一个在图像文件中是圆形的,而另一个不是圆形的,这可能与向后兼容性有关。
这正是您的 shellcode 使用 VirtualSize 来查找数据的 "real" 结尾的原因,即使它驻留在图像文件中也是如此。毫不奇怪,您可以通过将 VirtualSize 四舍五入到文件对齐值来计算 SizeOfRawData,至少在格式良好的 PE 文件中是这样。
shellcode 只是使用 VirtualSize 来找到 REAL 代码的结尾。在 SizeOfRawData 字节和 SizeOfRawData 字节之间,只是未使用的填充零,使其成为添加新代码而不影响文件大小或破坏 PE 文件内寻址偏移的主要位置。
总而言之,Windows 加载程序本质上是采用 VirtualSize 值并将其四舍五入为内存对齐值以获得内存分配的实际大小(甚至这可能会四舍五入到最接近的 4k -最小内存页)。然后将最多 SizeOfRawData 字节从文件复制到内存部分的开头。如果小于内存中段的大小,则余数补零
据我了解,在 PE
文件中,虚拟大小显示了它在加载期间为部分分配了多少 space,而原始大小显示了该部分在磁盘上的大小。
我遇到了这个执行以下操作的可执行文件:
它从原始数据大小 (offset 0x10
) 中减去虚拟大小 (offset 0x8
) 并确保有一些 space(例如 100 字节)。在距文本部分 header 的偏移量 0x14
处,它在文件中找到了该部分本身的偏移量。它将虚拟大小添加到此,找到该部分在文件中结束的位置。它复制了一些 shellcode(最终跳转到可执行文件的原始入口点以确保原始可执行文件运行)到二进制文件文本部分的末尾。
现在我在这里有点困惑,如果虚拟大小显示将分配给可执行文件的确切 space,不会在 .txt
部分末尾添加代码覆盖一些其他数据的可执行文件并使其崩溃?谢谢。
嗯嗯,这个黑客代码似乎是精心设计来隐藏各部分之间的恶意代码。
关于您的问题,您是正确的 VirtualSize 是真正分配在内存中的 space,而 RawSize 是磁盘上用于保存节数据的 space。 你错过的是(来自 MS PECOFF 规范):
VirtualSize
: The total size of the section when loaded into memory. If this value is greater thanSizeOfRawData
, the section is zero-padded. This field is valid only for executable images and should be set to zero for object files.
这意味着 如果 SizeOfRawData
-VirtualSize
的结果为正,我们在磁盘上有一些可用的 space 实际上填充了 0.
如果 space 足以容纳恶意代码,则在磁盘上添加带有 VirtualSize
的文本部分的开始,您可以获得可用于复制的 0 填充区域的开始代码。
剩下的就是故事了...
这是一个很好的问题,说明了关于 Windows 加载程序如何计算内存大小的一个非常重要的观点(或者你可能会说怪癖)。
PE/COFF 规范确实将 VirtualSize 描述为 "The total size of the section when loaded into memory"。如果您认为 total 是包含该部分的 REAL 数据总量,这在技术上是正确的,但它不是分配给该部分的内存总量 Windows。您会发现 VirtualSize 通常小于 Windows 为内存中的部分分配的数量,因为 VirtualSize 必须四舍五入到最接近的内存对齐值(在 PE 映像中设置)。
换句话说,VirtualSize 表示部分的未舍入大小,而 SizeOfRawData 是图像文件中数据的大小,但舍入到最接近的文件对齐填充值。这就是 VirtualSize 是内存或磁盘上数据真实 "raw" 大小的更好表示的原因。 PE/COFF 规范没有做出这种区分。为什么一个在图像文件中是圆形的,而另一个不是圆形的,这可能与向后兼容性有关。
这正是您的 shellcode 使用 VirtualSize 来查找数据的 "real" 结尾的原因,即使它驻留在图像文件中也是如此。毫不奇怪,您可以通过将 VirtualSize 四舍五入到文件对齐值来计算 SizeOfRawData,至少在格式良好的 PE 文件中是这样。
shellcode 只是使用 VirtualSize 来找到 REAL 代码的结尾。在 SizeOfRawData 字节和 SizeOfRawData 字节之间,只是未使用的填充零,使其成为添加新代码而不影响文件大小或破坏 PE 文件内寻址偏移的主要位置。
总而言之,Windows 加载程序本质上是采用 VirtualSize 值并将其四舍五入为内存对齐值以获得内存分配的实际大小(甚至这可能会四舍五入到最接近的 4k -最小内存页)。然后将最多 SizeOfRawData 字节从文件复制到内存部分的开头。如果小于内存中段的大小,则余数补零