如何在Windows PE 32位可执行文件中为我的代码洞穴腾出空间

Eug*_*344 4 windows x86 assembly portable-executable

所以我想在minesweeper.exe中为我的代码洞穴腾出空间(典型的Windows XP扫雷游戏,链接:Minesweeper).所以我通过CFF Explorer修改了文件的PE头,以增加该.text部分的大小.

SEGS

我尝试将.text段的原始大小增加1000h(新大小为3B58),但Windows无法找到入口点并且游戏无法启动.然后我尝试增加该.rsrc部分的大小,添加一个新的部分,增加图像大小,但这些尝试都没有成功,Windows说"这不是x32可执行文件".

所以这就是问题:如何为我的代码洞穴腾出空间?我不想搜索编译器留下的空白空间,我想为我的代码提供漂亮而干净的1000h字节.这个教程以及如何在不破坏游戏的情况下做到这一点的详细解释将是伟大的!(是的,我实际上正在攻击扫雷)

Nei*_*tsa 10

如果不使以下部分无效,则无法增加部分的大小(通常是因为它使这些部分中的偏移和地址无效).这仍然是可能的,但它非常容易出错,并且当您有一个更简单的解决方案时,不值得麻烦.

通常,您需要在PE 的末尾添加一个部分并从代码部分跳转到那里.代码部分的末尾通常有一点空间(代码洞穴),因此您可以将JMP(或一些代码存根)放在那里以重定向到新部分.您还可以为数据或新资源或任何您想要的内容添加其他新部分.


注意:我使用两个工具:CFF explorer作为PE浏览器; 十六进制编辑器.

这个文件非常特别,因此添加新的部分比平时更难.

开始吧!

下面是数组的十六进制视图IMAGE_SECTION_HEADER:

节标题

通常有一些空间可以添加一个新的部分,但在这种特殊情况下,没有...最后一个部分标题后面紧跟一些东西.

根据内容判断,这可能是绑定的导入目录,在CFF资源管理器中确认(绑定目录的偏移量为0x248):

绑定导入目录

绑定导入目录今天没用,特别是ASLR,所以我们可以将整个目录归零:

归零绑定导入目录

您也可以将数据目录中的绑定导入目录RVA清零,尽管这不是严格要求的:

在此输入图像描述

现在,是时候添加新部分了.

添加新部分

Minesweeper默认带有3个部分,因此将部分数从3增加到4:

增加部分数量

转到节标题并添加一个新节(您可以直接在CFF资源管理器中执行此操作):

新的部分

您需要选择两个数字:

  • 新部分的原始大小(我选择了0x400); 它必须是倍数FileAlignment(在这种情况下为0x200).

  • 新部分的虚拟大小(我选择了0x1000); 它必须是SectionAlignement(该二进制文件为0x1000)的倍数.

现在我们"需要计算另外两个成员,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'
Run Code Online (Sandbox Code Playgroud)

这给出了正确的0x5000(.data部分从0x5000开始).

现在,我们的最后一节应该从哪里开始?

.rsrc部分从0x6000开始,大小为0x19160:

>>> hex(round_up_multiple_of(0x6000 + 0x19160, 0x1000))
'0x20000'
Run Code Online (Sandbox Code Playgroud)

所以它必须从0x20000开始.把那个号码放进去Virtual Address.

原始地址

(通常不需要这样,因为所有部分已经对齐,最后一部分必须从文件末尾开始,但我们会这样做).

让我们从一个例子开始(第一和第二部分):

第一部分原始地址是0x400,原始大小是0x3c00.FileAlignement是0x200,因此:

>>> hex(round_up_multiple_of(0x400 + 0x3c00, 0x200))
'0x4000'
Run Code Online (Sandbox Code Playgroud)

第二部分应该从Raw address0x4000 的文件(它)开始,这是正确的.

因此,对于我们的新部分,计算是:

  • .rsrc部分从文件0x4200开始
  • .rsrc文件的大小为0x19200
  • FileAligment 是0x200

计算如下:

>>> hex(round_up_multiple_of(0x4200 + 0x19200, 0x200))
 '0x1d400'
Run Code Online (Sandbox Code Playgroud)

我们的最后一节从文件中的0x1d400开始,用十六进制编辑器确认:

最后一节的位置

最后的步骤

最后一步是必需的,计算SizeOfImageOptional头中的字段.根据PE规范,该领域是:

图像加载到内存中时图像的大小(以字节为单位),包括所有标题.它必须是SectionAlignment的倍数.

因此,计算结果为:最后一节的VirtualAddress+ VirtualSize,对齐SectionAlignment(0x1000):

>>> hex(round_up_multiple_of(0x20000 + 0x1000, 0x1000))
'0x21000'
Run Code Online (Sandbox Code Playgroud)

新尺寸的图像

现在,将所有修改保存在CFF资源管理器中并退出.

为新部分增加空间

最后一步是为最后一节添加所需的字节.当我选择Raw size0x400时,我Raw Address使用十六进制编辑器在(0x1d400)处插入0x400字节.

保存文件.如果您按照所有步骤操作它(在Win 10上测试),您可以启动修改后的可执行文件.

如果0x400不够,请尝试使用不同原始大小的新部分.

现在你有了一个新的空白部分,其余的由你来修改代码:)