As I was on #Cracking4Newbies
last time, someone asked me for a KeyGEN-Tutorial for this program. Normally I don't write
anything on request - but this is an exception since the request came from a very good,
old friend who had re-started cracking a few weeks before. This tutorial isn't really
difficult and I think everyone will understand it (at least I hope).
First of all click on "Registrieren" and enter some fake registration
details. I've enterd PIRATED COPY as name, CR@CKING TUTORI@L as company name and 12345
as registration number.
The first important thing I noticed was that everything I enterd is in uppercase. Now we
need to set up the necessary breakpoints. So enter SoftICE and set a BPX to HMEMCPY. Now
leave SoftICE and press "Registrieren". Since there were 3 Edit Boxes, skip the
first two ones. Then press F12 till you're looking at the following code snippet:
:004535E3 MOV EDX,[EBP-04]
:004535E6 MOV EAX,00472788
:004535EB CALL 0040343C
:004535F0 XOR EAX,EAX
:004535F2 MOV [00472898],EAX
:004535F7 DWORD PTR [0047289C],00000001
; set up for calculation
:00453601 DWORD PTR [004728A4],00000001
:0045360B MOV EAX,[00472780]
; move name to EAX
:00453610 CALL 00403560
; get length of name
:00453615 CMP EAX,06
; length of name <= 6
:00453618 JLE 0045369F |
As you could read in the
above code, our name must NOT be <= 6 chars ... so it must be (at least) 7 chars long.
Since we know this, we can go on with the code tracing:
:0045361E MOV EAX,[00472780]
; move name to EAX
:00453623 CALL 00403560
; get length of name
:00453628 MOV ESI,EAX
; move length of name to ESI
:0045362A TEST ESI,ESI
; is length of 0?
:0045362C JLE 00453681
:0045362E DWORD PTR [0047289C],00000001
; set up counter
:00453638 PUSH 004728A8
:0045363D MOV ECX,00000001
; ECX = 1
:00453642 MOV EDX,[0047289C]
; move counter in EDX
:00453648 MOV EAX,[00472780]
; move name in EAX
:0045364D CALL 00403764
:00453652 MOV EAX,[004728A8]
:00453657 MOV EDX,[004728A4]
:0045365D MOVZX EAX,BYTE PTR [EDX+EAX-01]
; get char of name
:00453662 IMUL DWORD PTR [0047289C]
; multiply with counter
:00453668 MOV [004728A0],EAX
:0045366D MOV EAX,[004728A0]
:00453672 ADD [00472898],EAX
; add result of multiplication
:00453678 INC DWORD PTR [0047289C]
:0045367E DEC ESI
; decrease number of loops left
:0045367F JNZ 00453738
; did complete name |
As you could read in the
above assembler source, the routine takes a char from the name, multiplies it (EAX) by the
loop number and adds the values of all loops together. Now we understood another important
part of our KeyGEN, so go on with the tracing.
:004535F7 DWORD PTR [0047289C],00000001
; set up for calculation
:00453681 IMUL EAX,[00472898],000007B0
; multiply result by 7B0h
:0045368B MOV [00472898],EAX
:00453690 MOV EDX,00472790
:00453695 MOV EAX,[00472898]
:0045369A CALL 004029C8
:0045369F CMP DWORD PTR [00472788],00
; code enterd?
:004536A6 JZ 00453751
:004536AC LEA EAX,[EBP-08]
:004536AF MOV EDX,00472790
:004536B4 CALL 0040350C
:004536B9 MOV EAX,[EBP-08]
; move enterd code to EAX
:004536BC MOV EDX,[00472788]
; move real code to EDX
:004536C2 CALL 00403670
; compare
:004536C7 JNZ 00453751 |
What you can read out from
the above assembler code? Well, our result from the previous calculation is multiplied by
7B0h. That's it. The company name is never used for the calculation.
So the complete code calculation works like the following:
1) get char from name
2) multiply that char by number of loop (counter)
3) add result of multiplication to a variable
4) repeat step 1-3 until there's no char left
5) multiply the variable by 7B0h
Now code your KeyGEN in your favourite programming language - like C++.
Already tried cracking my 2nd CrackMe?
// This is the C++ Source Code of my KeyGEN. I hope you like it.
// I've compiled it using Symantec C/C++ 6.11
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
unsigned long EAX, R47289C, R472898;
char name[100] = {0};
printf(" ____ __ __\n");
printf(" / _/_ _ __ _ ___ ____/ /____ _/ /\n");
printf(" _/ // ' \\/ ' \\/ _ \\/ __/ __/ _ `/ /\n");
printf("/___/_/_/_/_/_/_/\\___/_/ \\__/\\_,_/_/\n");
printf(" ____ __ __\n");
printf(" / __ \\___ ___ _______ ___ ___/ /__ ____ / /____\n");
printf(" / /_/ / -_|_-</ __/ -_) _ \\/ _ / _ `/ _ \\/ __(_-<\n");
printf("/_____/\\__/___/\\__/\\__/_//_/\\_,_/\\_,_/_//_/\\__/___/\n\n");
for (;;){
printf("\nPostgebühren 98
1.12 KeyGEN - d0NE bY TORN@DO in '99\n");
printf("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n");
printf("Name:
");
gets(name);
if (strlen(name)<7)
{
printf("ERROR:
NAME can't be less than 7 chars long!");
return 0;
}
else break;
}
EAX = 0;
R472898 = 0;
// convert name to uppercase
for (R47289C=1; R47289C<=strlen(name); R47289C++)
name[R47289C-1] = toupper(name[R47289C-1]);
// part 1 of calculation
for (R47289C=1; R47289C<=strlen(name); R47289C++)
{
EAX = name[R47289C-1]; // get char of name
EAX = EAX * R47289C; // multiply by number of
loop
R472898 = R472898 + EAX; // add result (EAX) to variable
}
// part 2 of calculation
EAX = R472898 * 0x7B0;
// print out the registration number
printf("Registration Number: %lu", EAX);
return 0;
} |
Another target has been
Reverse Engineerd. Any questions
(no crack requests)?
|