您无法在不使后续部分无效的情况下增加部分的大小(通常是因为它会使这些部分中的偏移量和地址无效)。这仍然是可能的,但它非常容易出错,并且当您有更简单的解决方案时,不值得这么麻烦。
通常,您只需要添加一个部分在最后PE 的并从代码部分跳转到那里。代码部分(代码洞)末尾通常有一点空间,因此您可以将 JMP(或一些代码存根)放在那里以重定向到新部分。您还可以添加其他新的数据部分或新资源或任何您想要的内容。
注意:我使用两个工具:CFF explorer 作为 PE 浏览器;十六进制编辑器。
该文件非常特殊,因此添加新部分比平常要困难一些。
开始吧!
下面是数组的十六进制视图IMAGE_SECTION_HEADER
:
![Section headers](https://i.stack.imgur.com/jLjTR.png)
通常有一些空间可以添加新的部分,但在这种特殊情况下,没有空间......最后一个部分标题后面紧跟着一些东西。
从内容来看,这很可能是一个绑定的导入目录,在CFF explorer中确认了这一点(绑定目录的偏移量为0x248):
![Bound import directory](https://i.stack.imgur.com/tgGIj.png)
绑定的导入目录现在没有用处,特别是对于 ASLR,因此我们可以将整个目录归零(其大小为 0xA8 字节,如上一个屏幕截图所示):
![Zeroed bound import directory](https://i.stack.imgur.com/MrCWI.png)
您还可以将数据目录中的绑定导入目录 RVA 清零,尽管这不是严格要求的:
![enter image description here](https://i.stack.imgur.com/2fu7n.png)
现在,是时候添加新部分了。
添加新部分
扫雷默认有 3 个部分,因此将部分数量从 3 增加到 4:
![Increment number of sections](https://i.stack.imgur.com/dLSMu.png)
转到节标题并添加一个新节(您可以直接在 CFF 资源管理器中执行此操作;我将其命名为我的,.foobar
,请注意部分名称是at most8 个字符并且不需要以 NULL 字节结尾):
![New section](https://i.stack.imgur.com/PepTn.png)
您需要选择两个数字:
现在我们“需要计算另外两个成员,Virtual Address
and Raw Address
.
虚拟地址
让我们以第一部分和第二部分为例。
第一部分从虚拟地址 0x1000 开始,虚拟大小为 0x3A56。下一节虚拟地址must对齐于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 开始,该地址已通过十六进制编辑器确认:
![Last section location](https://i.stack.imgur.com/3zAEm.png)
最后步骤
还需要最后一步,计算SizeOfImage
可选标头中的字段。根据 PE 规范,该字段为:
图像的大小(以字节为单位),包括所有标题,如图像
已加载到内存中。它必须是SectionAlignment 的倍数。
因此计算可以简化为:VirtualAddress
+ VirtualSize
最后一部分,对齐SectionAlignment
(0x1000):
>>> hex(round_up_multiple_of(0x20000 + 0x1000, 0x1000))
'0x21000'
![New size of image](https://i.stack.imgur.com/uZbPJ.png)
现在,在 CFF 资源管理器中保存所有修改并退出。
为新部分添加空间
最后一步是为最后一部分添加所需的字节。当我选择一个Raw size
0x400,我在处插入0x400字节Raw Address
(0x1d400) 使用十六进制编辑器。
保存您的文件。如果您遵循了所有步骤,它必须按原样工作(在 Win 10 上测试),并且您可以启动修改后的可执行文件而不会出现任何错误。
如果 0x400 不够,请尝试对新部分使用不同的原始大小。
现在你有了一个新的空部分,剩下的就由你来修改代码了:)