CrackMe tutorial for Cruehead's Crueme 1.0
By Merkuur / CiA

Hi reversers, 

In this tutorial I will explain the method I used to find valid codes
for Cruehead's nice crackme. I think I was the 5th cracker to actually
complete it. Cruehead released the source code for his crackme after
that, which is just as well - I won't have to copy a lot of asm into
this text :).

Put a breakpoint on hmemcpy and run the program, entering any code.
Sure enough, you break in. Step around, and you will eventually get
to the place were the check on your code is performed, namely, at 00401B73.
Single-step inside this code, and watch what happens... You will quickly
see that the entered password is at ebx, and that the code performs
operation on the data at ebx, ebx+4, and ebx+8. So the entered code must
be 12 chars long. You should then analyze the code, understand what it 
does. I've summed it up for you below:
 
 - 2 values are computed from the 3 ints at ebx, ebx+4 and ebx+8. These
   values are stored in edi and esi. I've converted the asm code performing
   the computation to C, from the 3 int values p1, p2, p3. If you understand
   asm better than C then you'll be at home with the disassembled listing.

	unsigned int eax, i, j;
	unsigned int length=12; /* the code length */
	esi=0; edi=0;           /* resulting values in edi, esi */
	for (i=0;i<0xFF;i++) {
	   for (j=0;j<0xFF;j++) {
	      eax = (p1+p3+0x0012AB20)*length;
	      eax = eax ^ (p2+0x048FF4EA);
              eax = eax ^ (p3-p1-0xBC309A);
              edi = edi + (eax | 0x029359E2);
              edi = edi & 0x15263748;

              eax = (p1-p3-0x127FB9)/length;
              eax = eax ^ (p2-0x048FF4EA);
              eax = eax ^ (p1+p3+ 0xBC0533);
              esi= esi+ (eax & 0x029359E2);
              esi = esi | 0x596A7B8C;
           }
           edi = edi + 0x911;
           esi = esi - 0x911;
        }


 - the following code is executed:
	:00401C51 add edi, EFFDE3AF
	:00401C57 jne 00401C8E         ; bad code !
	:00401C59 add esi, A4948D23
	:00401C5F jne 00401C8E         ; bad code !
	:... good code !

   so edi+EFFDE3AF and esi+A4948D23 must be 0, which means that we must have:
   edi = 10021c51, esi = 5b6b72DD


Allright... Now the tough part is, what must the p1, p2, p3 values be if we
want to satisfy the final check ? it is not practical to work back from 
edi = 10021c51 and esi = 5b6b72DD, first because there are 255x255 operations
to revert, and, more importantly, because the operations involved are not 
reversible (edi = edi & 0x15263748 for instance...). Therefore... Bruteforce
is the way to go... 

Unfortunately the key we want to bruteforce is a 3-int thing... even when
limited to printable chars, it's still something like a 84 bits key... 
Trying to test all possible values will take ages !!! So what I did is, try
a key (like ABCDEFGHIJKL), write down edi and esi. Change one bit in the key,
and repeat the process... What I found is, changing a single bit in the key
doesn't change the resulting edi and esi much. So the idea is, starting from
a random key, try to change bits in it so that the resulting edi and esi
values get "closer" (in terms of number of matching bits) to the desired 
values (10021c51 and 5b6b72DD). Actually the number of matching bits in 
the resulting edi and esi values can be thought as an "evaluation of the
interest" of the initial key. The more matching bits, the closer you are
from a valid key. Whenever you have found a "evaluation of interest" function,
(also called a "survival criterion") you can use a GENETIC ALGORITHM in order
to find a key that minimizes this function.

A genetic algorithm is an iterative process that mimicks the natural evolution
process ("only the best ones survive"). For this crackme we would consider
our 12 chars key to be a living creature, made of 12 genes. Starting from 
a random set of creatures, we compute the "survival criterion" of each. Then,
we iterate the following:
  - "Natural selection" process: keep some of the best scoring creatures, 
     and get rid of the others.
  - "Reproduction" process: generate new creatures, by mixing the genes from 
    the best ones. Hopefully this will result in new ones that will have an 
    even better score.  
  - "Mutation" process: in order to allow the apparition of new interesting 
    genes that were not present in the initial population, randomly modify 
    some genes in a few creatures. 

Repeat this sequence for several generations of creatures, and eventually, 
there will be one that has the best possible selection criterion. In the
case of the crackme, it is a key that generates the wanted values for edi/esi.


You will find a C program that performs all these operations in this package.
On my P100 it finds valid codes in a few minutes. If someone ever writes an
assembler version please send it to me, I would love to see it.

Happy reversing,

Merkuur


