如果不使以下部分无效(通常是因为它使这些部分中的偏移量和地址无效),则无法增加部分的大小。这仍然是可能的,但它极易出错,并且当您有更简单的解决方案时不值得麻烦。
通常,您只需在PE 的末尾添加一个部分,然后从代码部分跳转到那里。代码部分(代码洞穴)的末尾通常有一点空间,因此您可以将 JMP(或一些代码存根)放在那里以重定向到新部分。您还可以为数据或新资源或您想要的任何内容添加其他新部分。
注意:我使用了两个工具:CFF explorer 作为 PE 浏览器;十六进制编辑器。
这个文件非常特殊,因此添加新部分比平时要困难一些。
开始吧!
下面是IMAGE_SECTION_HEADER数组的十六进制视图:
通常有一些空间可以添加一个新的部分,但在这种特殊情况下,没有空间......最后一个部分的标题紧跟在后面。
从内容来看,这可能是绑定的导入目录,在CFF explorer中确认(绑定目录的偏移量为0x248):
绑定的导入目录在今天已经没有用了,尤其是使用 ASLR,所以我们可以将整个目录清零(它的大小为 0xA8 字节,如上一个屏幕截图所示):
您也可以将数据目录中的绑定导入目录 RVA 清零,尽管这不是严格要求:
现在,是时候添加新部分了。
添加新部分
扫雷默认有 3 个部分,因此将部分的数量从 3 增加到 4:
转到部分标题并添加一个新部分(您可以直接在 CFF 资源管理器中进行操作;我命名为 .foobar,请注意部分名称最多 8 个字符,不要'不需要以 NULL 字节结尾):
你需要选择两个数字:
现在我们“需要计算另外两个成员,Virtual Address 和 Raw Address。
虚拟地址
让我们以第一和第二部分为例。
第一部分从虚拟地址 0x1000 开始,虚拟大小为 0x3A56。下一节虚拟地址必须对齐SectionAlignement (0x1000) 所以计算是(这里使用python):
>>> def round_up_multiple_of(number, multiple):
num = number + (multiple - 1)
return num - (num % multiple)
>>> hex(round_up_multiple_of(0x1000 + 0x3a56, 0x1000))
'0x5000'
这给出了正确的 0x5000(.data 部分从虚拟地址 0x5000 开始)。
现在,我们的最后一部分应该从哪里开始?
.rsrc 部分从 0x6000 开始,大小为 0x19160:
>>> hex(round_up_multiple_of(0x6000 + 0x19160, 0x1000))
'0x20000'
所以它必须从虚拟地址 0x20000 开始。将该号码输入Virtual Address。
原始地址
(通常不需要这样做,因为所有部分都已对齐,最后一个部分必须从文件末尾开始,但我们会这样做)。
提醒一下,原始地址是文件中的地址(不在内存中)。
让我们从一个例子开始(第一和第二部分):
第一部分的原始地址是 0x400,它的原始大小是 0x3c00。 FileAlignement 是 0x200,因此:
>>> hex(round_up_multiple_of(0x400 + 0x3c00, 0x200))
'0x4000'
第二部分应该从文件(Raw address)的 0x4000 开始,这是正确的。
因此对于我们的新部分,计算为:
- .rsrc 部分在文件中的 0x4200 处开始
- .rsrc 文件中的部分大小为 0x19200
-
FileAligment 是 0x200
计算如下:
>>> hex(round_up_multiple_of(0x4200 + 0x19200, 0x200))
'0x1d400'
我们的最后一部分从文件中的原始地址 0x1d400 开始,使用十六进制编辑器确认:
最后的步骤
需要最后一步,计算 Optional 标头中的 SizeOfImage 字段。根据 PE 规范,该字段为:
图像的大小(以字节为单位),包括所有标头,作为图像
被加载到内存中。它必须是 SectionAlignment 的倍数。
因此计算可以简化为:最后一节的VirtualAddress + VirtualSize,对齐SectionAlignment (0x1000):
>>> hex(round_up_multiple_of(0x20000 + 0x1000, 0x1000))
'0x21000'
现在,在 CFF 资源管理器中保存所有修改并退出。
为新部分添加空间
最后一步是为最后一部分添加所需的字节。当我选择 0x400 的 Raw size 时,我使用十六进制编辑器在 Raw Address (0x1d400) 处插入 0x400 个字节。
保存文件。如果您按照所有步骤操作,它必须按原样工作(在 Win 10 上测试),并且您可以启动修改后的可执行文件而不会出现任何错误。
如果 0x400 不够,请尝试为新部分体验不同的原始大小。
现在你有了一个新的空白部分,剩下的就是你修改代码了:)