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