10101010101010
010101010101000010100
10100101
10101010100101010
10101000010010110
00101000101000010

-SantMat's reverseme #3-
solution of the reverseme
~by tank_~

10101000100011111001
101000110010101100
1000100001111111011
10001000011111101010
1000111000101100100
1001111110001000100

If you can't do it the right way, pretend you did and do it your way!

Section:
Contents:
1.Tools used

Hiew (for modifying the exe's instructions/opcodes)
PeBuild (for peeking inside the exe)
OpGen (for getting the right calls/jmps in the exe)
Api reference (for the coding part of the reverseme)

2.Initial approach (Introduction)

Let's see what we have on our hands first... hmm a PE-structure based reverseme. That means we have to know the structure of a PE file (windows exe file) very well (at least that's what they tell us). Now, we know that a PE file has some crappy info we're not concerned about at its beggining, then the PE header, than a certain number of sections that contain our data/ code/ resources. The PE header is divided into the Image File Header and the Image Optional Header (not really optional, but that's what they called it... :) ) Let's take a look at the two header definitions from WINNT.H:

WINNT.H
typedef struct _IMAGE_FILE_HEADER { USHORT Machine; USHORT NumberOfSections; ULONG TimeDateStamp; ULONG PointerToSymbolTable; ULONG NumberOfSymbols; USHORT SizeOfOptionalHeader; USHORT Characteristics; } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; typedef struct _IMAGE_OPTIONAL_HEADER { // // Standard fields. // USHORT Magic; UCHAR MajorLinkerVersion; UCHAR MinorLinkerVersion; ULONG SizeOfCode; ULONG SizeOfInitializedData; ULONG SizeOfUninitializedData; ULONG AddressOfEntryPoint; ULONG BaseOfCode; ULONG BaseOfData; // // NT additional fields. // ULONG ImageBase; ULONG SectionAlignment; ULONG FileAlignment; USHORT MajorOperatingSystemVersion; USHORT MinorOperatingSystemVersion; USHORT MajorImageVersion; USHORT MinorImageVersion; USHORT MajorSubsystemVersion; USHORT MinorSubsystemVersion; ULONG Reserved1; ULONG SizeOfImage; ULONG SizeOfHeaders; ULONG CheckSum; USHORT Subsystem; USHORT DllCharacteristics; ULONG SizeOfStackReserve; ULONG SizeOfStackCommit; ULONG SizeOfHeapReserve; ULONG SizeOfHeapCommit; ULONG LoaderFlags; ULONG NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
Next, since we are going to deal with the import table, let's say a few words about it also. The import table is usually situated towards the beggining of a section (usually .rdata), and its structure is based on the following structure definition:
            
typedef struct tagImportDirectory {
    DWORD    dwRVAFunctionNameList;
    DWORD    dwUseless1;
    DWORD    dwUseless2;
    DWORD    dwRVAModuleName;
    DWORD    dwRVAFunctionAddressList;
} IMAGE_IMPORT_MODULE_DIRECTORY, * PIMAGE_IMPORT_MODULE_DIRECTORY; 
            
Also take a look at the exe (with your hex editor let's say). Notice that the only imported function is Kernel32!ExitProcess. That means we'll have to alter the import table somehow.
And, the api definition for the function we need to import, and then call:
int MessageBox(
    HWND hWnd,	// handle of owner window
    LPCTSTR lpText,	// address of text in message box
    LPCTSTR lpCaption,	// address of title of message box  
    UINT uType 	// style of message box
);

That's about it for the info we need to start, the rest I'll tell you 'on the road'.
3.Essay
(steps)

Let's see what our goals are then for this reverseme: add a new section, modify the import table and add a little extra code that displays a messagebox (but all this 'manually'). The essay will be divided in three parts accordingly.
PART I
Take a look at the exe in PEBuild. See that it has 3 sections. We will add our own, called '.tank'. Therefore, we will modify at first the number of sections in the image file header (first locate the beggining of the PE header, there's a pointer to at at offset 0x3C). Go to 0xB6 to see the desired number(the number of sections in the exe). We see it is 0300=3. We will increment the value to 0400=4. Every single modify I make, make it using your favourite hex-editor. See the original and changed exe in fig #1 and fig #2.


Fig. #1: The original no. of sections


Fig. #2: The modified no. of sections


We have now changed the number of sections, let's add the actual section definition now. The sections table starts around 0x1A0 and ends at 0x21F. Therefore, we will add our section at 0x220. Now, a typical section looks like this: name(8 bytes), virtual size(4 bytes), virtual RVA(4 bytes), physical size(4 bytes), physical RVA(4 bytes), never mind(12 bytes), characteristics(4 bytes). A grand total of 40 bytes.
There you have it, so our new section will look something like this:
section .tank{
name='.tank';//8 bytes
VirtualSize=100;//4 bytes
VirtualRVA=4000;//4 bytes
PhysicalSize=200;//4 bytes
PhysicalRVA=A00;//4 bytes
Unused=0;//12 bytes
Characteristics=E0000020;//4 bytes
}
Now, why THOSE values? Here's why:
Virtual Size is how much of the exe our section occupies (not counting the ending zeros). I used 100 just to be sure, it's actually B0 in size.
Virtual RVA is where the section will be loaded into memory (Location of section in memory=Image Base+Virtual RVA). My Virtual RVA was determined by adding 1000 to the Virtual RVA of the previous section.
Physical Size. That is how much is allocated in the exe for our section (including ending zeos). 200 is fair enough.
Physical RVA. The address in the exe where our section begins. The original exe ended at 9FF, so our new section will start at A00.
Add those values in your hex editor as seen below (figure #4). Now, using your hex-editor, or whatever, add 200 bytes at the end of the exe.
Now we have finished adding a new section and part one of the essay also. :)


Fig. #3: The original sections table



Fig. #4: The modified sections table


PART II

Here's part two of our essay: we will try (and succeed :P) to add some imports to the import table (we need the MessageBoxA function, remember?), but without changing the original import table. At offset 0x130 we find the pointer to the original import table (fig. #5). Remeber it, then change it to 4000 (Virtual RVA of our section)(fig. #6). Now, take a look at 2008(virtual offset, actually 608 as physical offset)(the original import table), we will have to copy the first 20 bytes in our section, then add another 20 bytes for our import (User32!MessageBoxA) and finally 20 empty bytes to let the loader know the import table has finished. That means we will write the module/api information strting at 0xA3C=0x403C(virtual offset). Since we only import one api, it's gonna be 4 bytes in length (4 bytes=1 api), then 4 empty bytes, and again the same information (again 4 bytes the pointer to MessageBoxA, and 4 empty bytes). After these 32 bytes, we can write the name of our desired DLL (user 32.dll, followed by a zero byte - name of modules are zero terminated) at 0x404C=0x64C. That means our section (.tank) will start like this: 20 bytes for the original import table (copy them from 0x608), then our 20 bytes and final 20 bytes, all equal to 0. Now, our 20 bytes will look like this (respecting the tagImportDirectory structure defined earlier):
3C40 0000=0x403C --> pointer to information about which apis to load
0000 0000=0x0 --> useless
0000 0000=0x0 --> useless
4C40 0000=0x404C --> pointer to module name (user32.dll)
4440 0000=0x4044 -->again pointer to information about which apis to load, their addresses during runtime will be found starting at this address+imagebase (404044).
So the first api at 404044, the second (if it would have existed) at 404048 and so on... We only have one api, that means that call dword ptr [404044] is actually call MessageBoxA after the import table is properly loaded at startup. Now we need to know what to write at 403C(0xA3C) and 404C(0xA4C). We need to write there a pointer to the name of the api(s) we need to load. Therefore, after the name of the dll (user32.dll), write two zeros and then MessageBoxA (the two zeros are used as hints, don't ask). Do that at 0xA57=0x4057. Now, at 403C and 404C write 5740(=4057). Now if everything is ok, when you run the exe you should have a brand new api loaded at startup, simply waiting for you to call it.



Fig. #5: The original import table pointer



Fig. #6: The modified import table pointer

PART III


Fig. #7: The new section

Here's the final (and easiest) part of the essay, adding the extra code. Now, we need to call MessageBoxA with a text and a caption as main parameters. So, we need them somewhere in the exe (at A70 write'em). Now, we will add the code starting with AA0, which is 40A0 in memory, so we will need to modify the entry point RVA from 1000 (original) to 40A0 (our code start). Do that at 0x00D8, write A040(=40A0). Now we only need to add the code, as said at 0xAA0:
push 0 ;unused
push 0 ;unused
push 404090 ;caption
push 404070 ;text
push 0 ;unused
call d,[404044] ;Call MessageBoxA
jmp .401000 ;jmp to original entry point (Use OpGen to get the opcodes)
Assemble this in your favourite asm editor, and run it. Voila... it w0rks... kewl right!
See fig #7 for the new section of the exe.
As sad I am to go, my essay must end here, but remember... I'LL BE BACK!
4.Final words
Kewl thingie by SantMat, I did learn something (as he hoped), I learned a lot actually. I enjoyed every minute of the reverseme, it was one of the best reversemes I've ever seen (in spite of its simplicity). Read a tut on the PE file format if you want to fully understand what I wanted to say in this paper.

5.Greets
(Acknowledgements)

Greets go to:
SantMat, for writing the reverseme, and also
extasy, amante4, vissie, Iczelion, the guys at #Cracking4Newbies, #win32asm, the guys in ID (your database is really great), and everyone else I forgot.
6.Contact me
You can mail me with questions/problems/queries and so on at tank__@hotmail.com