The Ugly Way:

default

figureEmOut

crackmes.de—Notes

This is the first tutorial I am posting. I will be using OllyDbg. I am not sure if I should use screen shots. I am not that good with OllyDbg, and don't know if I will get more confused trying to explain how to get around in OllyDbg. I was thinking about finding the algo and just showing how to write a keygen. It would be more benificial if I can find a way to explain how I found it with Olly. So hang in there:

crackme#1.exe by microplant

The first thing to we want to do is find out more about the crackme. Run the program and we get this:


We need to keep our eyes out for anything that can be useful. Looks like it is asking for a username and serial. There is a register button. Lets put the username as: cracked , serial: 47806 . In a tutorial I read, can't remember author, he stated that 47806 in decimal is BABE in hex. He said he could find a BABE in code any day. Now lets hit the register button. We get:


We always need to pay attention to the message we get when our serial fails. We can use it to find a starting point when searching for the algorithm in one of our tools. Now that we have some info about the crackme, open it up in OllyDbg.

There are several windows that can be opened in Olly. I will only be using three for this tutorial. 1) CPU Window (View -> CPU or Alt+C). 2) Executable Modules (View -> Executable Modules or Alt+E). 3) Command line (Plugins -> Command line or Alt+F1). The newer versions of OllyDbg come with the command line plugin installed. If you don't have it, you can download it at the OllyDbg homepage. Here is a screen shot of the windows.


1) CPU Window. This is where we will be stepping through our code.
1B) Displays data as we step through code.
1C) Dumped data of our exe. You can see the badboy message we got here.
1D) Registers of CPU. The Zero flag is also useful to us.
1E) Stack and the data that is pushed to it.
2) Executable Window. Right now only interested in crackme#1.exe
3) Command line window. Type help for list of commands.

Earlier when we ran the program we saw that it has input boxes for us to fill in. When we hit the register button it checks to see if we entered the correct data. Most of the time when a message box asks us for data it uses an API call. This is good for us because we can set a breakpoint on these calls and be able to jump to a closer location of the algorithm. After it gets the data from the input box it has to compare it to the correct serial. When we jump to the code that captures our inputted data we know the comparing algo should be somewhere close. The most popular call we can break on is: GetWindowTextA and the next is GetDlgItemTextA. Both of these are used by a program to get data inputted by the user. I always check for GetWindowTextA first. So lets try this:

In the Executable Modules window you see the path to our crackme#1.exe. You can right click this path and choose (View Names or hit Ctrl+N). A new window will pop up:


When this window is highlighted we can type the name of the API Call we are looking for. Start typing GetWindowTextA. As you type the window will scroll down to the call we are looking for. We find that GetWindowTextA is used in this crackme. So lets right click that name and choose (Toggle break point on import). Now when we hit register the debugger should stop in the location of code that is receiving our data. Go ahead and close the View Names window. (We can rewind/restart our program any time by pressing or Ctrl+F2. We must reset our breakpoint each time we restart!)

Now that we have a break point set we can run the program inside OllyDbg. We can do this by pressing or F9. The crackme should now popup. It is being run inside Olly. It may popup behind Olly so keep an eye out on the task bar. Input the username: cracked, serial: 47806 and hit register. The breakpoint shows up in black and red on the top left of the CPU window. You can also see a call to GetWindowTextA on the bottom right in the stack area.


This is where my explanation may get a little ugly. I don't know all the details of what is going on. Now that we should be at a close point in the code to where the program checks our username and serial. We will step through the code. I will be using step over or F8. The plan is to hit F8 until we find something to do with our username or serial. I pressed F8 27 times and found "cracked" inside the EDI Register. It has also been popped to the stack.


We should be getting close now. We found the username we entered. Now we keep going and look for the serial we entered. Before we see our serial we should hit another breakpoint. The first call to GetWindowTextA was the username. If we hit F8 14 more times (41 in total) we hit the second breakpoint. You will know because the top left of the CPU window will have 77D6213C The black and red let us no it is a breakpoint. From this breakpoint we hit F8 27 more times (68 in total). We can see our serial is in ??????? Now we need to pay attention and look for anything that is going to hint towards our serial and its algorithm.

Now we need to press F8 13 more times (81 in total). We see cracked is in EAX. F8 one more time (82 in total) and 7 is in EAX. The program just calculated how many characters are in our username. F8 one more time (83 in total) and 7 is moved(copied) from EAX to EBX. Lets look at the line we are sitting on.

004011E6   . 83FB 05        CMP EBX,5
004011E9   . 7D 14          JGE SHORT crackme#.004011FF
004011EB   . 68 34404000    PUSH crackme#.00404034         ; /Arg2 = 00404034 ASCII "registration failed - try again :)"
004011F0   . 68 57404000    PUSH crackme#.00404057         ; |Arg1 = 00404057 ASCII "crackme #1"
004011F5   . E8 17090000    CALL crackme#.00401B11         ; \crackme#.00401B11

It is going to compare 7 (the length of our username) which is inside the EBX register with 5. If the username is less than five it will give us the bad boy message "registration failed - try again :)". Our username is 7 characters so we will jump past this bad boy message.

We should still be on line:
004011E6 . 83FB 05 CMP EBX,5

Hit F8 30 more times (113 in total) and we see cracked is placed in EAX. Hit F8 4 more times (117 in total) and notice 63 is placed in EAX. If you know your ASCII letters and numbers in hex, decimal, and binary it will benifit you. If not you can use a chart like this one. Doing so you will find out that the hex for the letter c is 63.

Hit F8 2 more times (119 in total) and 99 is placed into EAX. Using the same chart you can determine that 99 is the decimal equivalent to c. Could our serial be the decimal representation of our username? Lets keep going. If this is where the algo is being determined then we should be jumping back to the beginning of the algo pretty soon. It has to loop through each letter of the username.

We hit F8 5 more times (124 in total) and we will end up on this line.
004012E3 .^EB 8A JMP SHORT crackme#.0040126F

This is a jump. Actually this is the jump that will take us back to the beginning of the algo that determines our serial. We may not know this the first time we go through. So hit F8 1 more time (125 in total) and we will have jumped to the beginning of the algo.

Hit F8 13 more times (138 int total) and cracked is placed in EAX. Hit F8 4 more times (142 in total) and 72 is placed in EAX. 72 is hex for r (ascii). F8 2 more times (144 in total) and 72 is converted to the decimal 114 which is placed in EAX. F8 3 more times (147 in total) and the decimal version of the first two letter of our username will be joined together and placed in EDX = 99114.

F8 2 more times (149 in total) and we are on this line again.
004012E3 .^EB 8A JMP SHORT crackme#.0040126F

It will take us to the front of the algo once again. Take a look at where it is jumping? 0040126F ! Hit F8 1 more time (150 in total). We land at the front of the algo which is here:
0040126F > A1 E4484000 MOV EAX,DWORD PTR DS:[4048E4]

Look at the first part of the code: 0040126F . See how we jumped to this location? So now lets go through the full length of the username.

F8 13 times (163 in total) EAX = cracked
F8 4 times (167 in total) EAX = 61. 61 is hex for a.
F8 2 times (169) EAX = 97. 97 decimal for a
F8 3 times (172) EDX = 9911497
F8 3 times (175) we are back at beginning of algo.

F8 13 times (188) EAX = cracked
F8 4 times (192) EAX = 63
F8 2 times (194) EAX = 99
F8 3 times (197) EDX = 991149799 (c=99,r=114,a=97,c=99) 1st,2nd,3rd,4th charcters of username
F8 3 times (200) back at beginning of algo

0040126F > A1 E4484000 MOV EAX,DWORD PTR DS:[4048E4]

F8 13 times (213) EAX = cracked
F8 4 times (217) EAX = 6B
F8 2 times (219) EAX = 107
F8 3 times (222) EDX = 991149799107
F8 3 times (225) beginning of algo

F8 13 times (238) EAX = cracked
F8 4 times (242) EAX = 65
F8 2 times (244) EAX = 101
F8 3 times (247) EDX = 991149799101
F8 3 times (250) beginning of algo

F8 13 times (263) EAX = cracked
F8 4 times (267) EAX = 64
F8 2 times (269) EAX = 100
F8 3 times (272) EDX = 991149799107101100
F8 3 times (275) beginning of algo

We have gone through all the characters of the username. The code is going to jump out of the algo loop we were just in. We will keep stepping through code to see if anything else happens.

F8 2 times (277) and we land on this line:
00401279 . 3B05 D4484000 CMP EAX,DWORD PTR DS:[4048D4]
This line is going to compare the length of our username = 7 to the next inc of this loop = 8. Eight is higher so the zero flag is set. F8 1 more time (278) and we come to this line:
0040127F . 7C 64 JL SHORT crackme#.004012E5

This jump will be taken since the zero flag is set. We will go to 4012E5.

F8 1 more time (279) and we jump out of algo loop to:
004012E5 > FF35 C0404000 PUSH DWORD PTR DS:[4040C0]

If we look in the Display window under where we step through. (1B in the description of Olly windows diagram!) You will see:
DS:[004040C0]=00890048, (ASCII "991149799107101100")
Jump from 0040127F

This shows us that the ascii characters 991149799107101100 are located at DS:[004040C0] we can verify this by typing:
d ds:[004040c0]
in the command line prompt and hitting enter.

This will show:
00890048 39 39 31 31 34 39 37 39 99114979
00890050 39 31 30 37 31 30 31 31 91071011
00890058 30 30 00 00 00 00 00 00 00......

This will be displayed in the hex dump area. (1C of the Olly pic up top).

You can use the command line to view other areas. Remember our registers in the top right? EAX, ECX, etc.
Right now EDX = 008721C0. If you want to know what that address contains you can type this into the command line and hit enter:
d edx
(d = display) The result is:

008721C0  AB AB AB AB AB AB AB AB  ««««««««
008721C8  00 00 00 00 00 00 00 00  ........
008721D0  04 00 04 00 55 07 1A 00  ..U.
008721D8  34 37 38 30 36 00 AB AB  47806.««
008721E0  AB AB AB AB AB AB EE FE  ««««««îþ
008721E8  00 00 00 00 00 00 00 00  ........
008721F0  06 00 04 00 51 07 1D 00  ..Q.
008721F8  39 39 31 31 34 39 37 39  99114979
00872200  39 31 30 37 31 30 31 31  91071011
00872208  30 30 00 AB AB AB AB AB  00.«««««
00872210  AB AB AB FE EE FE EE FE  «««þîþîþ
00872218  00 00 00 00 00 00 00 00  ........
00872220  BC 01 06 00 EE 14 EE 00  ¼.îî.
00872228  60 FA 89 00 78 01 87 00  `ú‰.x‡.
00872230  EE FE EE FE EE FE EE FE  îþîþîþîþ
00872238  EE FE EE FE EE FE EE FE  îþîþîþîþ
00872240  EE FE EE FE EE FE EE FE  îþîþîþîþ

Amongst the jibberish we can find the serial we entered = 47806 as well as the one our crackme has generated so far = 991149799107101100

Lets look at current line we are on:
004012E5 > FF35 C0404000 PUSH DWORD PTR DS:[4040C0]

FF35 C0404000 This is the hex equivalent of:
PUSH DWORD PTR DS:[4040C0] which is the ASM or mnemonic/opcode (I think).
PUSH puts something on the stack. It is going to push DS:[4040C0] onto the stack. We already know our generated serial is in DS:[4040C0] because we used this command in the command line just a second ago:
d DS:[4040c0]

Hit F8 1 time (280) and the serial is popped onto the stack (1E in diagram). The stack now shows:
0012FFA4 00890048 ASCII "991149799107101100"

F8 1 time (281) and F is pushed to pushed to stack. This will be used as a count down from 15. Hit F8 2 times (283) EAX = 008721F8 ASCII "991149799107101100"

We are now on this line.
004012FA . E8 8E020000 CALL crackme#.0040158D

This line is going to call 0040158D. We could use F7 to step into this call and see what is going on. I will leave this for you to explore as this tutorial is already getting long. We will still be able to see what is happening without stepping into this call . This crackme is for beginners so lets hope a brain will keep us from having to step through each call. With more complicated algos you can be sure you will need to F7.

In short this call will keep the first 15 digits of the generated serial. Using the F that was pushed onto the stack earlier, as a count down to zero.

F8 1 more time (284) and EAX = 991149799107101 . Only the first 15 characters are left.

F8 7 times (291) and this is pushed to stack:
0012FFA4 00890048 ASCII "991149799107101"

F8 1 time (292) 5 is pushed to stack.
F8 2 times (294) and EAX = our 15 digit serial

We are now here:
00401330 . E8 58020000 CALL crackme#.0040158D

Once again we could F7 into this call to dig around, we won't.
F8 1 more time (295) and EAX = 99114 . It took the first 5 characters using the 5 we pushed to the stack earlier.

F8 1 more time (296) and we are here:
0040133A . E8 5D060000 CALL crackme#.0040199C

This call will add an - at the end after the first five characters of the username.
F8 1 more (297) and notice this is pushed to the stack.:
0012FFA4 00890048 ASCII "99114-"

Instead of trying to keep explaining all the F8s. Just keep stepping through and pay attention to what is going on inside Olly. Watch closely EAX and the Display window underneath where we step. The 15 digit serial is going to be split with "-" .

Pay attention and hit F8 32 times (329). Look at our registers
ECX 008721D8 ASCII "47806"
EDX 00872220 ASCII "99114-97991-07101"

004013D2 . E8 31050000 CALL crackme#.00401908
This is going to compare the first character of both serials. So hit F8 1 time (330).

Now we are:
004013D7 . 75 11 JNZ SHORT crackme#.004013EA
004013D9 . 68 34404000 PUSH crackme#.00404034 ; /Arg2 = 00404034 ASCII "registration failed - try again :)"
004013DE . 68 57404000 PUSH crackme#.00404057 ; |Arg1 = 00404057 ASCII "crackme #1"
004013E3 . E8 29070000 CALL crackme#.00401B11 ; \crackme#.00401B11
004013E8 . EB 0F JMP SHORT crackme#.004013F9
004013EA > 68 64404000 PUSH crackme#.00404064 ; /Arg2 = 00404064 ASCII "registration successfull - look out for a harder target now :)"
004013EF . 68 57404000 PUSH crackme#.00404057 ; |Arg1 = 00404057 ASCII "crackme #1"
004013F4 . E8 18070000 CALL crackme#.00401B11 ; \crackme#.00401B11

JNZ SHORT crackme#.004013EA
Will take us to "registration successfull - look out for a harder target now :)" if the zFlag is not zero.
If it is zero it will take us to "registration failed - try again :)"
Look at the zFlag and we see it is set to 1. Which means the zFlag is set. Which means it is zero. So hit F8 1 more time (331) and you will see that we went to the badBoy message. Hit F8 3 or 4 more times and we get


Keep in mind that the message may popup behind Olly. So you may have to choose it on the taskbar or use Alt+Tab.

We could use an ascii to decimal chart as our keygen. Instead lets write one. We know we have to take the username, with more than five characters and convert the ascii characters to decimal. We only need the first 15 decimal characters and need seperate them five at a time with -. We also know if we use "cracked" as the username we should get "99114-97991-07101" as our serial. Feel free to use any language you wish.

I choose darkBasic. Here is the code:
Rem Project: crackme_microplant
Rem Created: 12/27/2005 9:24:44 PM

Rem ***** Main Source File *****

_start:
cls
serial$ = ""
fullSerial$ = ""

input "Name: ", name$
numChars = len(name$)
if numChars <= 5 then print "WARNING: need more than 5 characters in name!"

dim serial$(numChars)

for i = 1 to numChars
serial$(i) = str$(asc(mid$(name$, i)))
fullSerial$ = fullSerial$ + serial$(i)
next i

leftSerial$ = left$(fullSerial$, 5)
midSerialPrep$ = left$(fullSerial$ , 10)
midSerial$ = right$(midSerialPrep$, 5)
rightSerialPrep$ = left$(fullSerial$, 15)
rightSerial$ = right$(rightSerialPrep$, 5)
finalSerial$ = leftSerial$ + "-" + midSerial$ + "-" + rightSerial$

print "Password: ", finalSerial$
print


repeat
input "Press r for new serial or escape to cancel ", redo$
if redo$ = "r" then goto _start
until escapekey()

I wrote this code a while ago and did not comment it. I have reformatted and don't have darkBasic installed on this computer any more. I don't want to add comments in because I can't test the compiled version. I also want to provide a openSource version of all the keygens, so here is a php version. I will comment this so you should be able to figure out what is going on in the darkBasic version also.

php version:
<html>
<body>
<form method="POST" action="crackme1_microplant_keygen.php">
<input type="text" name="username">
<input type="submit" value="generate">
</form>
</body>
</html>

<?php

//grab variables posted from form
$username = $_POST['username'];  //grabs username posted from form
$usernameLength = strlen($username);  //gets length of username

for ($i=0; $i<$usernameLength; $i++){             //loop for each character in username
  $uNameToDecimal .= ord($username{$i});  //replace each letter with two digit serial and concat var
}

$firstFiveSerial = substr($uNameToDecimal, 0, 5) . "-";
$secondFiveSerial = substr($uNameToDecimal, 5, 5) . "-";
$thirdFiveSerial = substr($uNameToDecimal, 10, 5);
$serial = $firstFiveSerial . $secondFiveSerial . $thirdFiveSerial;

echo $serial;

?>

So now that we have a working keygen, lets try another username. Let's try our generated serial as the username.
username: 99114-97991-07101
serial: 57574-94952-45575
running crackme#1.exe we find that this serail works also. Test out different names and see if they work? Here is another.
username: B!z@1r3
serial: 66331-22644-91145
This is what we want to see!

It's always a good idea to take a look at the readme that comes with alot of crackmes. Among other things you will find the rules for the crackme, author's name, difficulty level, etc.

Here is the readme.txt file that came with the crackme:
-------------------------------------------------------
////////////////////////////////////////////////
// crackme #1 - ultra-easy for real beginners //
////////////////////////////////////////////////

hi and welcome to my first crackme for crackmes.de
this one is dedicated to the real beginners, and can
be solved in a few minutes by average crackers
(even with the time to code a keygen !)
i tried to make it as easy as possible to let
beginners get the "high" to finaly solve a crackme
and to understand how the serial is beeing generated.

there is just one rule:

#1 only keygens allowed !

you will see why i only accept keygens and no name/key
combos :D

but now - have phun

microplant
-------------------------------------------------------

crackmes.de—Notes

figureEmOut

default