Reconstructing an executable

DON'T post new tutorials here! Please use the "Pending Submissions" board so the staff can review them first.
Post Reply
ebrizzlez
Kage
Kage
Posts: 732
Joined: 31 Mar 2007, 16:00
17
Location: Hidden in a Buffer Protection.
Contact:

Reconstructing an executable

Post by ebrizzlez »

Reconstructing an executable
into a high level interpretation of a disassembled file


In this applied guide, our main goal is to apply reverse engineering to real life situations. Today we will be analyzing a crackme I coded in assembly and will disassemble the file and reconstruct it into a C-style code, and compile our own version.
The tools required for today is just good old Ollydbg, a ring3 debugger or an user interface debugger, and optional is a C/C++ compiler.



Wait! What is Ollydbg and ring3 ? I don't have a ring. ='[ Well no need to worry, if you don't know what these terms are. I'll review them just in case you forgot or don't know exactly what they are.


OllyDbg – is a ring3 debugger also known as a user-mode interface debugger. Basically OllyDbg is a tool that allows us to see the inner-workings of a target application. OllyDbg makes more of an effort as a debugger and provides a strong and easy interface and allows extensible plugins to be added, as well as provides built-in hex-editor features and tons more nifty stuff.

Ring3/Ring0 Debugger – Basically there are two types of debuggers out there, there are the strong powerful Ring0 debuggers, which are also known as kernel debuggers, than theres user-mode aka ring3 debuggers. The main difference between these debuggers is, the operating system interaction. With a Ring0 debugger you get to analyze the operating systems interaction with the program, and can see library functional calls from DLLs. Ring0 are very powerful but provide tons of draw-backs, ring0 debuggers are advance debuggers and mainly used for driver development programming. Ring3 are more commonly used to analyze one particular executable file and reverse engineer a file. Most crackers out there, widely use a Ring3 Debugger like Olly because it provides easier use, but old school crackers and more knowledgeable power users or operates prefer Ring0 debuggers such as SoftICE.

Compiler – A compiler is a nifty tool for programmers to link an object file into a machine executable code or program. Programming with a compiled language such as C requires a programmer to type in its source code, the source code is then compiled into an object file, which has symbols and information ready , but cannot be executed by the operating system yet. The object file is then linked, and built into an executable by a linker.

What we would be doing today, is taking OllyDbg and ripping apart the inner-workings of a program. We'll see how the program is constructed, and we will interpret this into a higher level language such as C. Little knowledge of C is expected because we will reconstruct the target executable into C



First we start off by opening up the target executable into OllyDbg
.
Image


This is the code view of Olly. And as you can see this is our main program. Right away you can see we start off execution with an API call. OllyDbg is kind enough to leave us comments about what it thinks about the following code.
As we can see on the far right a call to the API MessageBoxA is being made. The call is shown as followed:
CALL <JMP.&user32.MessageBoxA> . If we check our Win32 Programmers Reference Guide on this symbol we get the following:
“The MessageBox function creates, displays, and operates a message box. The message box contains an application-defined message and title, plus any combination of predefined icons and push buttons.”
Whats more important is its parameters, which are constructed as follows:

Code: Select all

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
   );	
If we take a look, Olly comments the first line of code, a PUSH, which shows we are pushing the functions parameters into the stack so we can call the function later on. Olly notes the on its comment that

Code: Select all

Style = MB_OK	
Lets explain something about the stack, In todays style computers, there is something called little-edian format and big-edian . Basically little-edian says that everything is placed in reverse order. From the higher significance of bits to the lower. The stack is formatted in first-in-last-out aka FILO format. That means the first parameter to be push'd in, will be pop'd last. You can view the stack as a stack of plates. The first plate you place on the desk, will be the last one you take down if you add other plates to your stack.

As you can if the first placed first, it would wind up ending up on the botton of the stack being the last value. Such as the above figure. So so far our parameters look as the following:


int MessageBox(

HWND hWnd, // handle of owner window
LPCTSTR lpText, // address of text in message box
LPCTSTR lpCaption, // address of title of message box
MB_OK // style of message box
);


If referred to our documentation we can also see that MB_OK is the default flag, and contains an ok push botton and just displays texts:
“MB_OK The message box contains one push button: OK. This is the default.”
Now reading the next line in Olly and we can see its the next set of parameters for our function call to the API MessageBox.

Code: Select all

00401002 PUSH crackme1.00403000  ;|Title = "CrackMe by fAIL!"
00401007 PUSH crackme1.0040306C ;|Text = "This is a Crackme coded by fAIL! IN ….”
0040100C   |.PUSH 0                                     ; |hOwner = NULL
So as we can see the next values are given away to us by Olly, the Title parameter is set to the string “CrackMe by fAIL!” the actual text of the messagebox call is “This is a Crackme coded by fAIL! In ...”. And the parent handle owner is set to the value NULL which is equal to 0. So now we can actually fill in the rest of the parameters of our file.

Code: Select all


int MessageBox(

    NULL,	
   “This is a Crackme coded by fAIL! iN pure ASM. ^^ Enjoy”,	
   “CrackMe coded by fAIL!”	
    MB_OK 	
   );	

At this point we have completely reconstructed the first API call of our application. So we can start mapping out our source code as the following:

Code: Select all

#include <windows.h>	// for our WinAPI call to MessageBoxA
int main() 
 {

//Our first reconstructed API call takes the given four parameters.
MessageBox(NULL,”This is a Crackme coded by fAIL! IN pure ASM. ^^ Enjoy”,”Crackme coded by fAIL!”,MB_OK); 


}
Now we need to analyze the tricky part of the program, I say tricky because OllyDbg doesn't give us a mapped out API call, so we need to look more into the following lines. The following is a dead-code listing of the next lines executed in Olly.

Code: Select all

00401013  |   .  A1 A3304000   |   MOV EAX,DWORD PTR DS:[4030A3]
The following code doesnt say much. But if we take a look into whats actually going on we can make more sense of it. Ignoring the first two columns which are first the related virtual address and the opcode we notice the line with the mnemonic MOV.

Reference from the Intel Opcodes and Mnemonics manual we define the mnemonic MOV as:
MOV – Move Byte or Word
Usage: MOV dest,src
Modifies flags: none

Copies byte or word from the source operand to the destination operand. If the destination is SS interrupts are disabled expect on early buggy 808x CPUs. Some CPUs disable interrupts if the desintation is any of the segment registers. “
The MOV operation in this case is using the EAX register. You can think of registers as local variables. So obviously this line we are assigning a local variable a value. That value is being pointed to the data segment, address space 4030A3. We could search the address and find its value or we can use Olly to help us find the value of EAX after being assigned by the MOV mnemonic.
Image

In between the hex-edior and our debugger view is a small box that shows the value of both 004030A3 and the value of EAX after being assigned a value. We can also look on the right hand corner and see in the Registers panel that EAX is assigned the value 00000000 which is equal to the value 0. [Appended zeros are added as address space, but aren't really required when reconstructing our binary file.
Since the EAX is being assigned to a pointer pointing to data in a remote location, we can assume that this value, address space DS:[4030A3] is not initialized in our main() function but initialized outside as a global value. So the c-equivalent would be: int eax = 0;
The next line introduces us to another, but more simply mnemonic, the CMP mnemonic.

Code: Select all

	00401018    .  83F8 00          CMP EAX,0
“ CMP – Compare
Usage: CMP dest,src
Modifies flags: AF CF OF PF SF ZF
Subtracts source from destination and updates the flags but does not save result. Flags can subsequently be checked for conditions. “
In our case the value of EAX is being compared to the integer 0. Knowing that EAX is in fact zero, the compare returns as true. So the comparison is set to true and the zero flag is set to one which is equal to saying true. Compares can be thought as or implemented as if's statements in C.
In our case, we implement this as: if(eax == 0){executenextline}

Code: Select all

	0040101B    . /75 0C            JNZ SHORT reconstr.00401029
	
The next line is where everything comes into place. The famous JMP mnemonic. Enough is explained by the name, the next line actually is a family memember of JMP, JNZ [Jump-Not-Zero]. This refers to the Zero flag, which is set to the value 1, and since the value one is not zero than the jump is made. This means the following code goes inside our if statement.
If we take the jump we can see the next call is an API call to the MessageBoxA function, and we've seen this before so we can skip going over how to construct this and we'll just map it as:
if(eax==0){MessageBox(insertparametershere);}
But what if we, or a hacker, somehow change the value if our int eax, than we need a else statement for those conditions. In the else statement we will refer to the next line of JNZ because if validated false, than the computer just executes the next line of code, which would be:

Code: Select all

	0040101D    . /EB 1F            JMP SHORT reconstr.0040103E
Another jump to a remote location. This time we land in another MessageBox call but it seems to be the desired messagebox call we want, so in order to hack this program, we need to change the value of int eax to 1.
After the MessageBox call, you notice another jump to the following code:

Code: Select all

0040101F   POP EAX                             ;kernel32.7C817077
00401020   PUSH 0
00401022   PUSH 0                               ; /ExitCode = 0
00401024   CALL <JMP.&kernel32.ExitProcess>     ; \ExitProcess
	
As we can see the value EAX is being popped off the stack so its not being used anymore. And the value 0 is being pushed onto the stack which indicates that a function will be terminated, and surely enough the API call ExitProcess is invoked, with the ExitCode = 0 meaning sucessful, we can also replace this obscurity just by returning 0.
Now lets put the pieces together and see what we get ;]

http://code.suck-oold.com/182 -- code cased in pastebin section to save room in post.

Explanation and implementation

Lets explain the following code, although theres not much to say if you know some C coding already. We start off with the #include <windows.h> header because the MessageBoxA api call is from the windows library, thus we include the library so we can call the function MessageBox() [the appened A just denotes for ASCII character code set, while MessageBoxW denotes for wide-character code set, MessageBoxA is preset default.]
Now we move onto the next line, which is a global integer named eax: int eax = 0; This variable is initialized as global because it allows for easier modification, any function call can modify its value, but if the variable eax belongs to the function main() than the variable will be out of scope after the main() function exits. This also gives it its own special allocation in memory at a separate special segment as we saw before.
Next we call our main function int, just for convenience, we could've used the WinAPI call to main() and disabling the use of the commandline showing, but its not necessary. You could however, replace int main with:

Code: Select all

int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nFunsterStil)
But thats unnecessary as stated before, its the concept, not a complete replication. When the program first runs, it makes a call to the MessageBox function and displays a welcome screen. We fill in the parameters that we found in Olly in backwards order because of the way the stack works, last-in-first-out (LIFO Order).
Next this is where making the variable eax global is a very important role and provides a horrible coding choice for programming. Now the program checks to see if eax is equal to the value 0, and since we first initialized eax as 0 , than the statement is true. But since its a global value, another function may accidental modify it if you forget that the value has already been initialized, or, a hacker can easily locate its memory address since its stored away in a special segment and modify the value to a non-zero character, for example modify its value to 1 so the statement turns false.
This is where program protection comes into play, such a program scheme where if a registered user is given a boolean evaluation, if the user is legit, set variable to 1, if not than set variable to 0, provides poor coding choices. These values are easily modified in memory and thus provide no protection.
For this program, if the eax value is not set to 0, than you jump to the goodboy message, which says you successfully modified the program against its will. Such a scheme provides simple obscurity thats easily crackable even to the neophytes of the reverse engineering scene. Higher obscurity is advised , such as string encryption and executable protection. Such topics will be covered in other issues, as for now, I am out.

// written by EbRiZZlez.




Download Links:
Pdf Verision:

Code: Select all

http://rapidshare.com/files/254034800/Output.zip.html
MD5: 5B3ED8C78DA1274FD6DE2BC116F3694B

PrePacked Reversing Kit (Self Extracting):

Code: Select all

http://rapidshare.com/files/254032555/cracktools.exe.html
MD5: C0250C309A9A9DFBB65FC77588A3EBA6

/*Note: dont mind the grammar errors , tut was made at 5 in the morning. ^^ */

contact iNFO:
ebrizzlez @ hotmail [dot] com
-- yahoo account is locked currently, and for unknown reasons, I am trying my best to find out why its locked, but nothing so far. :x
[img]http://i81.photobucket.com/albums/j205/ebrizzlez/4lsint1.jpg[/img]

ebrizzlez
Kage
Kage
Posts: 732
Joined: 31 Mar 2007, 16:00
17
Location: Hidden in a Buffer Protection.
Contact:

Post by ebrizzlez »

thanks. :wink:
[img]http://i81.photobucket.com/albums/j205/ebrizzlez/4lsint1.jpg[/img]

User avatar
ph0bYx
Staff Member
Staff Member
Posts: 2039
Joined: 22 Sep 2008, 16:00
15
Contact:

Post by ph0bYx »

Very nice very nice!
Off topic: ah those OllyDebug images... They always turn me on :D

User avatar
Gogeta70
^_^
^_^
Posts: 3275
Joined: 25 Jun 2005, 16:00
18

Post by Gogeta70 »

Now THAT is a tutorial! Maybe one for the suck-o pdf?
¯\_(ツ)_/¯ It works on my machine...

ebrizzlez
Kage
Kage
Posts: 732
Joined: 31 Mar 2007, 16:00
17
Location: Hidden in a Buffer Protection.
Contact:

Post by ebrizzlez »

you want me to send you a download link to the odt (openoffice document) file?
[img]http://i81.photobucket.com/albums/j205/ebrizzlez/4lsint1.jpg[/img]

User avatar
Stavros
ΜΟΛΩΝ ΛΑΒΕ
ΜΟΛΩΝ ΛΑΒΕ
Posts: 1098
Joined: 02 Jan 2006, 17:00
18
Location: Mississippi, U.S.A.

Post by Stavros »

Now this is what a tutorial is supposed to be. I believe this should be the hallmark that other tutorials should be compared to on this site. Very, very good job Ebrizzles. If a new PDF comes out this should definitely be in it.

ebrizzlez
Kage
Kage
Posts: 732
Joined: 31 Mar 2007, 16:00
17
Location: Hidden in a Buffer Protection.
Contact:

Post by ebrizzlez »

well don't plan to update it so soon, on my spare time I want to compile a series of reverse engineering tutorials, but applied reverse engineering implementation, rather than just cracking tutorials. so stay in for more. :wink:

and thanks. ^^
[img]http://i81.photobucket.com/albums/j205/ebrizzlez/4lsint1.jpg[/img]

Post Reply