xorl %eax, %eax

Funny crackme

with one comment

Well, it’s Saturday night and I still don’t have internet connection. However, I found a few crackmes on a flash drive. Here I’ll write my solution to “Harry Potter Crackme by Shalamandra” since I don’t have anything better to do. Now that you’re reading this is probably Monday but anyway. This crackme should not take you more than 10 minutes since it’s just a tiny application with no special protection. The algorithm seems pretty simple… It goes like this:

1) Print some stuff on the console
2) Read a string
3) Do some rearrangements
4) Compare it with an existing one using strcmp()
5) If they contain the same string, print the congrats message else terminate

Of course you can just patch the final jump of step 5 which you can see here (from IDA Pro):

.text:00401723                 mov     [esp+88h+var_84], eax
.text:00401727                 mov     [esp+88h+var_88], edx
.text:0040172A                 call    strcmp
.text:0040172F                 test    eax, eax
.text:00401731                 jnz     short loc_401749

And loc_41749 is the location of the function which prints out the error message which you can see below:

harry potter crackme

But this is not allowed if you read the provided NFO file. The author explicitely states:

Rules:
Find the correct serial.
No patching allowed.

Which I found it nice since this is a really easy one and allowing patching will just made it a completely lame crackme. So, let’s have a look at the known string passed on strcmp(). This can be found easily by setting two breakpoints at the two arguments passed by the stack to the strcmp() library routine at addresses 0x00401723 and 0x00401727 (I did this using OllyDbg). The known string is this:

EAX=0022FF50, (ASCII "I am Lord Voldemort")

Which is stored in a character array on the stack. Now that we know this we can start reversing this funny rearrangement algorithm. It’s extremely easy to spot and reverse it since it’s composed by exactly 38 (19 x 2) MOV instructions and the above string has length of 19 bytes not including the NULL termination. Anyway, here is the substitution:

.text:00401694                 movzx   eax, [ebp+var_3B]
.text:00401698                 mov     [ebp+var_68], al
.text:0040169B                 movzx   eax, [ebp+var_45]
.text:0040169F                 mov     [ebp+var_67], al
.text:004016A2                 movzx   eax, [ebp+var_43]
.text:004016A6                 mov     [ebp+var_66], al
.text:004016A9                 movzx   eax, [ebp+var_44]
.text:004016AD                 mov     [ebp+var_65], al
.text:004016B0                 movzx   eax, [ebp+var_36]
.text:004016B4                 mov     [ebp+var_64], al
.text:004016B7                 movzx   eax, [ebp+var_3F]
.text:004016BB                 mov     [ebp+var_63], al
.text:004016BE                 movzx   eax, [ebp+var_47]
.text:004016C2                 mov     [ebp+var_62], al
.text:004016C5                 movzx   eax, [ebp+var_42]
.text:004016C9                 mov     [ebp+var_61], al
.text:004016CC                 movzx   eax, [ebp+var_39]
.text:004016D0                 mov     [ebp+var_60], al
.text:004016D3                 movzx   eax, [ebp+var_3D]
.text:004016D7                 mov     [ebp+var_5F], al
.text:004016DA                 movzx   eax, [ebp+var_41]
.text:004016DE                 mov     [ebp+var_5E], al
.text:004016E1                 movzx   eax, [ebp+var_40]
.text:004016E5                 mov     [ebp+var_5D], al
.text:004016E8                 movzx   eax, [ebp+var_38]
.text:004016EC                 mov     [ebp+var_5C], al
.text:004016EF                 movzx   eax, [ebp+var_3A]
.text:004016F3                 mov     [ebp+var_5B], al
.text:004016F6                 movzx   eax, [ebp+var_37]
.text:004016FA                 mov     [ebp+var_5A], al
.text:004016FD                 movzx   eax, [ebp+var_46]
.text:00401701                 mov     [ebp+var_59], al
.text:00401704                 movzx   eax, [ebp+var_3E]
.text:00401708                 mov     [ebp+var_58], al
.text:0040170B                 movzx   eax, [ebp+var_3C]
.text:0040170F                 mov     [ebp+var_57], al
.text:00401712                 movzx   eax, [ebp+var_48]
.text:00401716                 mov     [ebp+var_56], al
.text:00401719                 mov     [ebp+var_55], 0

It performs NULL termination on the last instruction. Anyway, I know that most of you will find this boring and to be honest if I had internet connection I’ll probably found it boring too but right now I had nothing better to do than writing this. Anyway, the substitution goes like this:

Original Position       New Position
---------------------------------------
        0                   18
        1                    6
        2                   15
        3                    1
        4                    3
        5                    2
        6                    7
        7                   10
        8                   11
        9                    5
       10                   16
       11                    9
       12                   17
       13                    0
       14                   13
       15                    8
       16                   12
       17                   14
       18                    4

So, if you like that source code reconstruction ideas when doing crackmes I believe the above source code should be looking something like this:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


int
main(void)
{
   char *usr_str, str[20] = {"I am Lord Voldemort"};

   printf("Print the cool ASCII art\nEnter the serial: \n");
   gets(usr_str); // Yeah... an overflow...
   char *tmp_buf = strdup(usr_str);
   // and a missing return value check...

   usr_str[0]  = tmp_buf[13];
   usr_str[1]  = tmp_buf[3];
   usr_str[2]  = tmp_buf[5];
   usr_str[3]  = tmp_buf[4];
   usr_str[4]  = tmp_buf[18];
   usr_str[5]  = tmp_buf[9];
   usr_str[6]  = tmp_buf[1];
   usr_str[7]  = tmp_buf[6];
   usr_str[8]  = tmp_buf[15];
   usr_str[9]  = tmp_buf[11];
   usr_str[10] = tmp_buf[7];
   usr_str[11] = tmp_buf[8];
   usr_str[12] = tmp_buf[16];
   usr_str[13] = tmp_buf[14];
   usr_str[14] = tmp_buf[17];
   usr_str[15] = tmp_buf[2];
   usr_str[16] = tmp_buf[10];
   usr_str[17] = tmp_buf[12];
   usr_str[18] = tmp_buf[0];
   usr_str[19] = 0;


   if (!strcmp(usr_str, str))
      printf("You're awesome!\n");
   else
      printf("Ultra fail!\n");

   free(tmp_buf);
   return 0;
}

This is a completely crappy C code but it’s an abstract demonstration of the crackme (which was written in C++ by the way). Now, that you have everything just find the serial. :P
Here is a screenshot from the crackme:

harry potter crackme

Nice one to spend a couple of minutes. :)

Written by xorl

March 30, 2009 at 12:36

One Response

Subscribe to comments with RSS.

  1. Heh I did this one a couple days ago. It was nothing special. I did like the big logo at the top though.

    Rik

    April 14, 2009 at 05:50


Leave a comment