My Solution To SantMat's ReverseMe #3

Author: Amante4

Date: October 15, 2000

http://www.ImmortalDescendants.org

 


***************************
* Introduction
***************************

This time I'm going to reverse Santmat's latest Reverseme. Reading the 
readme that comes with it you'll see the job is quite easy, until you
come to the restrictions section. The restrictions are quite clear. 
We can only use a hex editor to achieve our goal. 

Note: You can download the whole package, including my modified exe at:

http://www.immortaldescendants.org/database/santmat/solutions/amante-rm3.zip

***************************
* Tools Needed
***************************

I used 2 different hex editors. HVIEW is much better for adding code
and I use UltraEdit for everything else.

1) Hexeditor - HVIEW
2) Hexeditor - UltraEdit32
3) Knowledge of PE Header

***************************
* The Essay
***************************

Looking at the challange we must do the following:
1. You must add a new section to the file by way of editing the PE header/Optional Header.

2. You must add the message box function to the file by adjusting the import table.

3. You must alter the entry point of the file to point to the message box code that is
within the new section.

4. After the execution of the message box, your code must jump back to the original 
entry point of the file. - So the program can exit nicely using the already imported
ExitProcess ;)

5. IMPORTANT: You are only allowed to change the "PE Header/Optional Header" area of the
file and the area of the new section you add. You can't change any other sections.
Especially the import area.

6. FINALLY, You are only allowed to use hex/code editors(example: HIEW), you can use Wdasm or IDA, but 
I don't see what good they can do. You are not pe editors like procdump or the other numerous ones, 
or my IID King.

7. You must do it all by hand, that is what I am trying to get at here. You must do it
all manually. No help but your brain and an editor of some kind, for changing the
hex/code.

OK let's start. First we're going to add another section to the file. We can use a PE-Editor (just to look
of course) and see that the current exe has 3 sections each with a raw size of 200 bytes. What I'm going to 
do is copy the last section, .data, Onto the end of the file and adjust the PE header to reflect this. This
data that I copy will become our new section. We see that the .data section has a raw offset of 0x800. Going to 
offset 0x800 in the file in UltraEdit we see this:

This is the entire .data section. Now what I'm going to do is copy it and paste it onto the end of the file. I find the easiest way to do this is to
put the cursor on the last byte of the file and then do Edit->Hex Insert/Delete, then insert 1 hex byte. Then you can select the .data section
and copy it, then come down to the newly added byte at offset 0xa00 and paste from there. You'll end up having an extra byte left over
at offset 0xc00 which you will need to delete. Now we don't want was there to begin with so go ahead and manually zero (00) out the data
in this section. You should now have a new section copied that looks like this:

Of course, you'll see that the new section starts at 0xa00 and ends at 0xbff

Ok now to fix up the PE header to accomodate this new section being added, we'll need to do the following:

1) Increase the number of sections
2) Increase Image Size
3) Add a new entry to the Section Table

Finding these places in the PE file is always a challenge. I've found it nice to use a document by FatBoyJoe that show's the
offsets in the PE header. You can find that document here: http://www.immortaldescendants.org/database/essays/fboyjoe/exe_hdr.html
First, we'll change the number of sections. This value is a WORD in size and is offset in 6 from the PE Signature. Here is the original
data that is in the PE header:

Here you see the PE signature at offset 0xb0, and so at 0xb6 will be number of sections. As you can see it is currently
0x03 0x00 or 0x0003.  You need to remember the reverse nature of addresses etc... when dealing with Intel formats. OK
so it's pretty easy to figure out that we need to change the 0x03 to a 0x04 to add another section like so:

So we now have changed number of sections to 4. Next we're going to increase the image size. This is an easy thing to forget
to do and will cause strange behavior on NT/2000 if you don't change it. Once again looking at the PE editor, we see that each
section has Section alignment of 0x1000. We also see that currently we have an image size of 0x4000. Since we added 1 section
that must be at least 0x1000 long we will need to add 0x1000 to 0x4000 to get 0x5000. Looking at the PE document, we see that
size of image is located at offset 0x50 from the start of the PE signature. So we've got 0x00b0 + 0x50 = 0x100. Looking at 0x100
in the file we see:

Sure enough, we see 0x00004000 at offset 0x100. Remember that this is a DWORD quantity and the reversal of the bytes. So now
we'll change this to 0x00005000 like so:

OK, and now for the last thing before moving to the next part, is to add a new entry to the Section Table for the section we just added.
We know that the Section Table starts at 0xf8 past the PE signature. Which is 0x00b0 + 0xf8 = 0x1a8. It is also notable to mention
that it is an array that looks like this:

+0 8byte ANSI name 
+8 dword misc (actual size)
+C dword virtual address (an rva to where it should be mapped)
10 dword sizeofrawdata 
14 dword pointerToRawData (file based offset)
18 dword pointerToRelocations
1C dword PointerToLinenumbers
20 word NumberOfRelocations
22 word NumberOfLineNumbers
24 dword Characteristics
    - some of the flags in this are ;-
    0x00000020 contains code
    0x00000040 contains initialized data
    0x00000080 contains uninitialized data
    0x00000200 contains comments
    0x02000000 can be discarded
    0x10000000 This section is shareable. 
    0x20000000 This section is executable. 
    0x40000000 This section is readable. 
    0x80000000 The section is writeable.

Looking at the original Section Table at 0x1a8 we see this:

We can see that there are 3 entries, 1 for each section that we have. Now let's figure out what values we need to have
for our new section:

+0 8byte ANSI name ------> hmmm we've got 8 bytes to play with so I chose .amante
+8 dword misc (actual size) - Well the whole section is 0x200 bytes so lets just use 0x200 to say we're using this whole section.
+C dword virtual address (an rva to where it should be mapped) -----> since .data was mapped to 0x3000 let's map ours to 0x4000
10 dword sizeofrawdata -----> will be 0x200 here
14 dword pointerToRawData (file based offset) -----> remember we added new section at 0xa00 RVA
18 dword pointerToRelocations -----> There are none so 0x00000000
1C dword PointerToLinenumbers -----> Once again none so 0x00000000
20 word NumberOfRelocations -----> None so 0x00
22 word NumberOfLineNumbers -----> None so 0x00
24 dword Characteristics -----> Let's just use the same as .data section so 0xc0000040

We can just add onto the end of the original Section Table our new entry which looks like this:

Before we start the next part let's double check to make sure we've done the right thing so far. Looking at a PE
editor just to make sure our edits are correct so far we see the following:

So we see that the Size of Image is now 5000 and we've got a new section called .amante with the correct sizes etc...

For the next steps we need to add some code to the new section we just added. We need to call MessageBoxA
and by looking at the imports this program has, it only imports ExitProcess from Kernel32. The reverseme restricts
playing around with the imports section or using any special tools to import this missing API. We must import it by hand
by creating a new Import Address Table in the section we just created. We know that MessageBoxA is imported
from User32.dll. Now lets gather some info from our taget. We know that in the PE header, in the Image Data directory,

there is a pointer to our original Import Table. So at offset 0x80 from our PE signature, there resides a pointer and a size of
our import table. so we get 0xb0 + 0x80 = 0x130. Looking at 0x130 we see:

So our IAT is at 0x00002008 and has a size of 0x00000028. A thing to remember is that the address here is a VA and not a RVA.
We will need to change this info later, but for now let's quickly take a look at the data at VA of 0x2008 and then add our own
IAT in the newly created section. OK so the .rdata section is where our import info is located. We can tell this by looking at our PE
editor and seeing that the .rdata section has a Virtual Offset of 0x2000 and it's RVA is at 0x600 so looking at 0x608 should be our
import info:

Refreshing your memory an I_I_D  looks like this:

Import Directory
+0 DWORD OriginalFirstThunk;
4 DWORD TimeDateStamp;
8 DWORD ForwarderChain;
c DWORD Name;
10 DWORD FirstThunk;

So at 0x608 you've got the OriginalFirstThunk Pointer to 0x2030 or 0x630 RVA
Both TimeDateStamp and ForwarderChain are 0's
Name at 0x614 points to the dll name at 0x2046 "KERNEL32.dll"
and First Thunk at 0x618 points to 0x2000

What I'm going to do since we can't touch this data is to copy this part into our new section like so:

So you can see it's the same exact data that was there before just copied down to our new section starting at 0xa00.
The data in the first I_I_D at 0x608 has to stay pointed to the data up at VA 0x2030 etc.. This is because the program
calls ExitProcess by the FirstThunk array in the original import area. So in order for that to still work this will need to point there.
OK, what I'm going to do now is add another I_I_D right after the one at 0x608 for KERNEL32.dll. This new entry
will be for our new API in USER32.dll. I really don't care about the data after 0xa1c since it's duplicated in the other section
that we're pointing to and there is no need to preserve it. So lets go ahead and create a new I_I_D for USER32.dll and import
MessageBoxA. Looking at our modified I_I_D we get:

And now we need to change the Image Data Directory to point to our new I_I_D and update it's size since we've added an extra one.
We need to point it now to 0x4008 and add 20 more bytes to the size to get 0x3c. Here is the updated I_D_D:

Now we need to add the code to do what Santmat wants.

First we'll add a string for our dialog box message to the area just below our newly constructed Import Table. Santmat want's
us to pop up a message box that says: "I am a LaMe rEvErSeR! :P" So I added the string like so:

You can see I added the string at 0xa90. I left some space between the Import table I just added and this for no good reason.
actually I had added a bunch more stuff to the import table on my first go at this re-me so I didn't want to change my code
to reflect any movement since I'm lazy. Anyways we've added the string and now we'll add code to the new section just below the string
like so:

00404090 aIAmALameRevers db 'I am a LaMe rEvErSeR! :P',0 ; DATA XREF: start+4o
004040A9 db 0 ; 
004040AA db 0 ; 
004040AB db 0 ; 
004040AC db 0 ; 
004040AD db 0 ; 
004040AE db 0 ; 
004040AF db 0 ; 
004040B0 
004040B0 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
004040B0 
004040B0 
004040B0 public start
004040B0 start proc near
004040B0 push 0 ; uType
004040B2 push 0 ; lpCaption
004040B4 push offset aIAmALameRevers ; lpText
004040B9 push 0 ; hWnd
004040BB call ds:MessageBoxA ; MessageBoxA: 
004040C1 jmp loc_401000
004040C1 start endp

As you can see, I added the code needed to pop up a messagebox with this saying then it jumps back to our original entry point and
exits gracefully. Just so you can see the hex code for this I've included it below:

And the final thing is to point the entry point of the program to this new code at 0x40b0. We know that this offset is at 0x28
past the PE signature which is 0xb0 + 0x28 = 0xD8. This was 0x1000 like this:

And now it needs to be 0x40b0 like this:

You should now have a fully working program that satisfies the requirements of the reverseme.

One note I'd like to make is to be careful with UltraEdit when pasting stuff around. Pasting causes byte insertion
and if you're not careful to remove those extra bytes your file will be in trouble. 

***************************
* Final Thoughts
***************************

Well another good reversing session that was easy upon looking at it, but turned out to be rather hard. It's alot
manual editing with a hex editor and makes you learn the PE structures a bit more in depth. It was well worth the
time I spent doing the reverseme. Another note is these kinds of essays I've always found hard to write. As you can
see I've gone picture crazy in this one. I just really hate trying to describe how to hex edit something, so I figured a
few pictures are worth a few thousand words. :)

You can get a hold of me either on EFNet IRC on #immortaldescendants or via email at amante4@immortaldescendants.org

Shouts out to all the Immortal Descendants and everyone I know.

Over and Out for now,

Amante4