C++ PE:在.txt节末尾添加代码

C++ PE:在.txt节末尾添加代码,c++,c,windows,exe,portable-executable,C++,C,Windows,Exe,Portable Executable,正如我在PE中所了解的,文件虚拟大小显示加载期间为节分配的空间量,原始大小显示磁盘上的节有多大 我遇到了这个可执行文件,它执行以下操作: 它从原始数据大小(offset 0x10)中减去虚拟大小(offset 0x8),并确保有一些空间(例如100字节)。在文本节头的偏移量0x14处,它在文件中找到了该节本身的偏移量。它增加了虚拟大小,找到了文件中节结束的位置。它将一些外壳代码(最终跳到可执行文件的原始入口点以确保原始可执行文件运行)复制到二进制文件文本部分的末尾 现在我有点困惑了,如果虚拟大小

正如我在
PE
中所了解的,文件虚拟大小显示加载期间为节分配的空间量,原始大小显示磁盘上的节有多大

我遇到了这个可执行文件,它执行以下操作:

它从原始数据大小(
offset 0x10
)中减去虚拟大小(
offset 0x8
),并确保有一些空间(例如100字节)。在文本节头的偏移量
0x14
处,它在文件中找到了该节本身的偏移量。它增加了虚拟大小,找到了文件中节结束的位置。它将一些外壳代码(最终跳到可执行文件的原始入口点以确保原始可执行文件运行)复制到二进制文件文本部分的末尾


现在我有点困惑了,如果虚拟大小显示了将分配给可执行文件的确切空间,那么在
.txt
部分末尾添加代码是否会覆盖可执行文件的其他数据并使其崩溃?谢谢。

嗯,这段黑客代码似乎是精心设计的,用来隐藏各部分之间的恶意代码

转到您的问题,您是正确的VirtualSize是内存中实际分配的空间,而RawSize是磁盘上用于保存节数据的空间。 您错过的是(来自MS PECOFF spec):

VirtualSize
:加载到内存中时节的总大小。如果该值大于
SizeOfRawData
,则该部分为零填充。此字段仅对可执行图像有效,对于对象文件应设置为零

这意味着如果
SizeOfRawData
-
VirtualSize
的结果是肯定的,那么磁盘上的一些可用空间实际上已经被0填满了

如果该空间足以容纳恶意代码,则使用
VirtualSize
在磁盘上添加文本开头部分,可以获得0的填充区域的开头,该区域可用于复制代码


剩下的是故事…

这是一个很好的问题,说明了Windows loader如何计算内存大小的一个非常重要的问题(或者你可能会说是怪癖)

PE/COFF规范确实将VirtualSize描述为“加载到内存中时节的总大小”。如果将总数视为包含该节的真实数据的总量,这在技术上是正确的,但它不是为该节分配的内存窗口总量。您会发现VirtualSize通常小于Windows为内存中的节分配的量,因为VirtualSize必须向上舍入到最接近的内存对齐值(在PE映像中设置)

换句话说,VirtualSize表示节的未舍入大小,而SizeOfRawData表示图像文件中数据的大小,但舍入到最接近的文件对齐填充值。这就是为什么VirtualSize能够更好地表示内存或磁盘中数据的真实“原始”大小。PE/COFF规范不作此区分。为什么一个在图像文件中被舍入而另一个不被舍入,这可能源于向后兼容性

这正是外壳代码使用VirtualSize查找数据“真实”端的原因,即使它驻留在图像文件中。毫不奇怪,至少在格式良好的PE文件中,您可以通过将VirtualSize四舍五入到文件对齐方式的值来计算SizeOfRawData

外壳代码只是使用VirtualSize查找实际代码的结尾。在there和SizeOfRawData字节之间,只是未使用的填充零,这使得它成为添加新代码的主要位置,而不会影响文件的大小或破坏PE文件中的寻址偏移


总之,Windows加载器本质上获取VirtualSize值并将其向上舍入到内存对齐值,以获得内存分配的实际大小(甚至可以向上舍入到最接近的4k最小内存页)。然后,从文件复制到内存段开头的最大SizeOfRawData字节数。如果小于内存中节的大小,则剩余部分为零填充。

感谢您的回复:)但即使添加了代码,在执行right时也只会加载
.txt
VirtualSize
节?很难说是否对大小进行了任何控制。考虑到该部分本身将扩展到多个架构页面(PECOFF规范),一些OS版本加载程序可以简单地复制整个块。但无论如何,在经过如此大量的修改之后,同时更改
VirtualSize
值并不是什么大问题……所以你说
VirtualSize
不是什么大问题,加载程序将复制整个块,这意味着它将把实际的
.txt
部分扩展到架构页面。这是否意味着将加载的
.txt
节大小始终为
RawDataSize
?对不起,如果我误解了你的意思,我没那么说。我说过,复制文件中的数据后,还要修改偏移量0x8处的
virtualSize
字段,添加复制数据的大小,以确保加载数据。但在这一点上,我真的认为我们已经谈论了太多非标准编码的内容,不应该讨论这些内容,因为它们对不良实践很有用。
VirtualSize代表了这一绝对错误的部分的未经修正的大小<代码>虚拟化
-这是为节保留的内存数量
SizeOfRawData
-这是磁盘上包含节的字节数。例如,节(
.bss
)具有未初始化的数据-在这种情况下,
SizeOfRawData
将为0-因此
virtualize
SizeOfRawData
。从另一个大小,因为四舍五入到FileAligment(通常为512字节)可以是和
VirtualSize
。问题不在于SizeOfRawDat所在的未初始化数据节