Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I make space for my code cave in a Windows PE 32bit executable

So I want to make a space for my code caves in minesweeper.exe (typical Windows XP minesweeper game, link: Minesweeper). So I modified the PE header of the file via CFF Explorer to increase size of the .text section.

Segs

I tried increasing raw size of .text segment by 1000h (new size was 3B58), but Windows was unable to locate the entry point and the game failed to launch. Then I tried increasing the size of the .rsrc section, adding a new section, increasing the image size, but none of those attempts were successful, Windows was saying that "This is not x32 executable".

So here is the question: how do I make space for my code cave? I don't want to search for empty space left by the compiler, I want to have nice and clean 1000h bytes for my code. A tutorial for that and a detailed explanation for how to do that without corrupting a game would be GREAT! (And yes, I am actually hacking a minesweeper)

like image 411
Eugen1344 Avatar asked Dec 07 '22 23:12

Eugen1344


1 Answers

You can't increase the size of a section without invalidating the following ones (typically because it invalidates offsets and addresses in those sections). This remains possible but it's extremely error prone and doesn't worth the hassle when you have a simpler solution.

Typically, you juste need to add a section at the end of the PE and jump there from the code section. There is usually a little bit of space at the end of the code section (code cave) so you can place your JMPs (or a little code stub) there to redirect to the new section. You can also add other new sections for data or new resources or whatever you want.


Note: I'm using two tools: CFF explorer as a PE browser; an hex editor.

This file is quite particular so it is a little bit harder than usual to add a new section.

Let's start!

Below is an hex view of the array of IMAGE_SECTION_HEADER:

Section headers

Usually there is some room to add a new section but in this particular case, there's none... The last section header is immediately followed by something.

Judging by the content, this is probably a bound import directory, which is confirmed in CFF explorer (offset of the bound directory is 0x248):

Bound import directory

Bound import directory are of no use today, especially with ASLR, so we can zero out the whole directory (its size is 0xA8 bytes as indicated in the previous screenshot):

Zeroed bound import directory

You can also zero out the Bound Import directory RVA in the Data Directories although this is not strictly required:

enter image description here

Now, it's time to add the new section.

Add a new section

Minesweeper comes with 3 sections by default, so increment the Number of sections from 3 to 4:

Increment number of sections

Go to the sections headers and add a new section (you can do it directly in CFF explorer; I named mine, .foobar, be wary that section names are at most 8 characters and don't need to end with a NULL byte):

New section

You need to choose two numbers:

  • The raw size of the new section (I picked 0x400) ; it must be a multiple of FileAlignment (which is 0x200 in this case).

  • The virtual size of the new section (I picked 0x1000); it must be a multiple of SectionAlignement (which is 0x1000 for this binary).

Now we" need to calculate the two other members, Virtual Address and Raw Address.

Virtual Address

Let's take an example with the first and second section.

The first section starts at virtual address 0x1000 and has a virtual Size of 0x3A56. The next section virtual address must be aligned on SectionAlignement (0x1000) so the calculation is (using python here):

>>> def round_up_multiple_of(number, multiple):
    num = number + (multiple - 1)
    return num - (num % multiple)

>>> hex(round_up_multiple_of(0x1000 + 0x3a56, 0x1000))
'0x5000'

Which gives 0x5000 which is right (.data section starts at virtual address 0x5000).

Now, where our last section should start?

.rsrc section starts at 0x6000 and has a size of 0x19160:

>>> hex(round_up_multiple_of(0x6000 + 0x19160, 0x1000))
'0x20000'

So it must start at virtual address 0x20000. Put that number in Virtual Address.

Raw address

(Typically this is not needed as all sections are already aligned the last section must start right at the end of the file, but we'll do it).

As a reminder, the raw address is an address in the file (not in memory).

Let's start with an example (first and second section):

The first section raw address is 0x400 and its raw size 0x3c00. FileAlignement is 0x200, thus:

>>> hex(round_up_multiple_of(0x400 + 0x3c00, 0x200))
'0x4000'

The second section should start on the file (its Raw address) at 0x4000 which is right.

Thus for our new section, the calculation is:

  • .rsrc section starts in the file at 0x4200
  • .rsrc section size on file is 0x19200
  • FileAligment is 0x200

The calculation is as follow:

>>> hex(round_up_multiple_of(0x4200 + 0x19200, 0x200))
 '0x1d400'

Our last section starts at the raw address 0x1d400 in the file which is confirmed with an hex editor:

Last section location

Final steps

One last step is required, the calculation of the SizeOfImage field in the Optional header. According to the PE specification the field is:

The size (in bytes) of the image, including all headers, as the image is loaded in memory. It must be a multiple of SectionAlignment.

Hence the calculation can be simplified as: VirtualAddress + VirtualSize of the last section, aligned on SectionAlignment (0x1000):

>>> hex(round_up_multiple_of(0x20000 + 0x1000, 0x1000))
'0x21000'

New size of image

Now, save all your modifications in CFF explorer and exit.

Adding room for the new section

The last step is to add the required bytes for the last section. As I choose a Raw size of 0x400, I insert 0x400 bytes at Raw Address (0x1d400) with an hex editor.

Save you file. If you followed all the steps it must work (tested on Win 10) as is and you can start the modified executable without any errors.

Try to experience with a different raw size for the new section if 0x400 is not enough.

Now you have a new empty section, the rest is up to you for modifying the code :)

like image 187
Neitsa Avatar answered Jan 16 '23 16:01

Neitsa