In This article we will learn Adding a section to PE binary.
Introduction to Adding a section to PE binary:
Let’s take a look at expanding PE binaries manually. I was working on a project in 2004 when we were asked to add some interoperability to the program. Some of the issues we ran into were that we needed space to make the necessary adjustments and it was decided that we would make the changes inline through assembly. The method we used then is now called code caving. The idea is to create a space where you add your code, and when the program runs, it jumps to your piece of code and executes, then returns to the original piece of code. The app is basically only limited by your imagination as you can simply create a space, add malicious code or any other modification, then jump on it, run it and jump back.
There is a lot of information to cover, so please read it again and don’t get mad if it doesn’t make sense right away. This is a very deep topic!
The executable used in the example will be on the one I downloaded from the famous R4ndom on his site backup; As always, don’t do this in a production environment. Use a VM! I will be using WxHexEditor to make changes. You can use whatever you want.
URL for binary provided by R4ndom:
So the procedure to do this is quite simple.
- Find IMAGEBASE; Many things will depend on this.
- Round the VIRTUAL_SIZE of the last section header to the SECTION_ALIGNMENT found in (IMAGEBASE+0x128)
- Add a snippet to the PE header
- Change the number of stubs Usually to (IMAGEBASE+ 0xF6)
- Change the image size definition in the PE header usually to (IMAGEBASE+0x140)
- Add a section on the new RAW Offset.
Here’s a sample of what the snippet looks like, we reverse binary for little endian.
I think if I break it down like this it will be easier to read and may provide some understanding. We will add this later.
|2E 74 65 73 74 00 00 00||.test (ASCII)|
|00001000||Size of Raw data|
|0000B000||Pointer to Raw data|
|00000000||Pointer to Relocations|
|00000000||Number of Relocations|
|0000||Pointer to Line Numbers|
|0000||Number of Line numbers|
Find the base of the image:
Note that virtual sizes should be equal to or larger than the raw size. This has to do with data that is initialized in memory on load, it will have to be stored virtually.
Items we will want to have: IMAGEBASE this will usually be 00400000; The PE header will have this defined at 0x124 bytes per header. NumberOfSections is usually located at 0xF6 IMAGEBASE Virtually. Otherwise it will be 0xF6. Know the items Section headers.
Round off the last part.
In this case, it’s the last section. RSRC If we look at IMAGEBASE+128 to find SECTION_ALIGNMENT Is the relocation of all sections. It’s important to know for this scenario because it shows what we can get around in terms of adding sections and what sections should be aligned to.
An easy way to do this is to open OllyDBG and open your binary and click on “M” for the memory map and click on the section of the binary that has the PE header. Once you double click there, you will be redirected to the PE HEADER labeled “MZ” in hex.
As I said above, SECTION_ALIGNMENT is IMAGEBASE+128. It usually and typically has a size of 0x1000. The size value lets us know what we can conveniently add about size as a section.
Since it is 0x1000, we can conveniently add 0x1000(4096) bytes to it. We can of course add more, but it gets a bit complicated when some bytes are padded and the image is rounded. It will also mix some of the analysis of the sections created by the tools. Not to mention 0x1000 (4096 bytes) isn’t much, but it’s enough to get you a lot.
LAST PART DEFINED:
.RSRC Dump – original:00400000..00400FFF
Name = “.rare” 00400268 |. 20020000 DD 00000220;
VirtualSize = 544. 0040026C |. 00B00000 DD 0000B000;
VirtualAddress = 0B000 00400270 |. 00100000 DD 00001000;
SizeOfRawData = 4096. 00400274 |. 00A00000 DD 0000A000;
PointerToRawData = 0A000 00400278 |. 00000000 DD 00000000;
This is the visual hexadecimal representation of the section defined above.
Just change the highlighted part to 0010 for 0x1000
Now we need to go up and add to NumberOfSections (0xF6) There are 4 sections in this binary. We will need to change it to 5 because we are adding a section. If we were to add two sections, we would make 6, and so on. Let’s note the last section header just because we’ll need to take those numbers and add to them for the next section.
Add a snippet to the PE header:
So it can be a bit tricky in a hex editor because hex is not easy for humans to read. If you really want to know, pin headers are 0x28 in size, so; it’s not too hard. Here is the header image (From Stud_PE).
Things to calculate if you want to do it yourself.
- The virtual size should be greater than or equal to the raw size; This is the space that is allocated.
- The virtual offset is increased by the size of the virtual size
- Raw Size is how much hard writable space you have.
- Raw Offset will be incremented based on the size of the raw offset.
Let’s define the items that are needed in the section. These items are defined by Microsoft. If you want to read the spec, I’ll add a link at the end for you to read if you want.
|2E 74 65 73 74 00 00||Test; Name of Section (ASCII)|
|00 00 00 00||Pointer to Relocations|
|00 00 00 00||Pointer to Line Numbers|
|00 00||Number of Relocations|
|00 00||Number of Line numbers|
Here is a picture of what it should look like:
Increase the number of defined sections:
This is a simple one byte change. Just go to IMAGEBASE+F6 or simply in the Hexeditor to Offset F6 and add to it.
In this case, just change from 4 to 5, because then we will have 5 sections in our binary system.
Resize the image to fit the added size. It is usually located at (IMAGEBASE+0x140). If you don’t, the binary will be larger than the PE header says and won’t be able to run because it won’t be a properly formatted PE file.
In this case we are adding 0x1000(4096) bytes, change it from C to D.
Add bytes to the raw section:
Since we’ve specified that we’re adding because of image0x1000(4096) bytes so far, we’ll add just that. This is easy using the Hex Editor (link below) WxHexEditer.
Just right click and click paste and paste 4096 (0x1000) bytes.
Plus that’s absolutely it!
Now I understand that this is very hard to do manually, and since there are 5 steps to do, there are at least 5 big places for mistakes. You can use a tool called Stud_Pe to easily add a section.
This is not required for the tutorial, but if you want to see the binary difference of everything we changed.
- Adding section to your pe-easy way
- PE explorer file repair
- Backdooring PE files windows
- Microsoft Download PEcoff
- Wx Hex Editor