In 21th
essay I asked you if you were interested in other keygen tutorials - and as I could
easily from your mails, you were :-) - So here it is. I've chosen this target program from
Gregory Braun, because some time ago I lost my unfortunately too long PGP Password. Back
to the tutorial: This tutorial is not as simple as my 1st keygen tutorial I think -
however - most of you will understand it - at least with the help of my comments. BTW, you
just need to change a little 'hex-constant' to produce a keygen for other programs Gregory
Brown wrote. I don't want to stop him developing such great programs - so buy the program
if you really use it! Now let's start our Cracking Session:
First of all, enter some registration details - I used "Cracking
Tutorial" as User Name and "The Immortal Descendants" as Company Name and
12345 as Registration. Now we need to set the HMEMCPY-BPX and press the
"OK"-Button. SoftICE will pop up now. Since there were three input fields, we
can press CTRL-D twice - then it'll pop up as the data of the third input field is trying
to be read. Now just trace through the code till you come to the following code snippet:
:0040979D PUSH EDI
; PUSH Company Name
:0040979E PUSH ESI
; PUSH User Name
:0040979F CALL 00415440
; calculate real code
:004097A4 ADD ESP,08
:004097A7 CMP EAX,EBP
; compare codes
:004097A9 JZ 004097C9
; JMP if equal (registered) |
Now from the above commented
code snippet, we know that if we want to produce a KeyGEN, we need to trace the CALL at
40979F. So after you've enterd this, the following code snippet get's displayed:
:00415440 MOV EAX,[ESP+04]
:00415444 PUSH ESI
:00415445 MOV ESI,[00422834]
:0041544B PUSH EAX
; PUSH User Name
:0041544C OR ESI,00000378
:00415452 CALL 00415940
; calculate part of real code
:00415457 ADD ESP,04
:0041545A ADD ESI,EAX
; add ABCDFF8 to the calculated part of the real code
:0041545C MOV EAX,[ESP+0C]
:00415460 PUSH EAX
; PUSH Company Name
:00415461 CALL 00415940
; calculate part of real code
:00415466 ADD ESP,04
:00415469 ADD EAX,ESI
; add calculated part to EAX
:0041546B POP ESI
:0041546C RET |
As you can easily see from
the above code snippet, two CALLs calculate the real code - and then ABCDFF8 is added. Now
we need to trace into the CALL at 415252. Now you'll be confrontated with the following
code snippet:
:00415940 PUSH EBX
:00415941 PUSH ESI
:00415942 MOV ESI,[ESP+0C]
:00415946 PUSH EDI
:00415947 PUSH EBP
:00415948 XOR EDI,EDI
; EDI = 0
:0041594A PUSH ESI
; PUSH User Name
:0041594B CALL [KERNEL32!lstrlen]
; check length
:00415951 TEST ESI,ESI
:00415953 JZ 00415987
:00415955 TEST EAX,EAX
; enterd nothing?
:00415957 JZ 00415987
; if so, JMP
:00415959 MOV ECX,00000000
; ECX = 0
:0041595E JLE 00415987
:00415960 MOVSX EBX,BYTE PTR [ECX+EAX+00425050]
:00415968 MOVSX EBP,BYTE PTR [ESI+ECX]
:0041596C LEA EDX,[ECX+01]
:0041596F IMUL EBX,EBP
; multiply EBX by EBP
:00415972 MOVSX ECX,BYTE PTR [ECX+00425088]
:00415979 IMUL EBX,ECX
; multiply EBX by ECX
:0041597C IMUL EBX,EDX
; multiply EBX by EDX
:0041597F ADD EDI,EBX
; add calculated part
:00415981 MOV ECX,EDX
:00415983 CMP EDX,EAX
; did all characters?
:00415985 JL 00415A60
; if not, JMP
:00415987 MOV EAX,EDI
:00415989 POP EBP
:0041598A POP EDI
:0041598B POP ESI
:0041598C POP EBX
:0041598D RET |
The above code snippet is
the most important code snippet for the calculation of the real code. At 415960, something
is looked from [ECX+EAX+425050] and is moved into EBX. ECX is the counter, EAX the string
length and 425050?? Well, just do a "D 425050" and you'll get the following:
#serB&nz|mfM1/5(!sd$Mq.{s]+sFjtKpzSdtzoXqmb^Al@dv:s?x/
Now since the User Name must be at least 1 char long, the lookup 'string' is
[ECX+1+425050]. The lookup string is
serB&nz|mfM1/5(!sd$Mq.{s]+sFjtKpzSdtzoXqmb^Al@dv:s?x/
Now EDX is moved into the number of loops (counter) and 1 is added. So EDX contains
counter+1. Now at 415972, the ECXth char of the User Name is moved into EBP. Then EBX is
multiplied by EBP.
At 415972 [ECX+425088] is moved into ECX. Now before that ECX was the counter and
what's that 425088?? Well, just do a "D 425088" and you'll get the following:
|b!pz*ls;rn|lf$vi^Axpe)rx5aic&9/2m5lsi4@0dmZw94cmqpfhw
Now EBX is multiplied by ECX. Then EBX is multiplied by EDX (counter+1). Then the
calculated part is added to EDI. This is repeated until until EDX = EAX - until the
counter is the numbr of chars in the User Name.
After you've returnd from that CALL, you'll recognize that the Company Name is
PUSHed. Now the same goes with the Company Name. Now code your KeyGEN in your favourite
programming language - like C++.
// 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 <stdio.h>
int main()
{
const char table1[]="serB&nz|mfM1/5(!sd$Mq.{s]+sFjtKpzSdtzoXqmb^Al@dv:s?x/";
const char table2[]="|b!pz*ls;rn|lf$vi^Axpe)rx5aic&9/2m5lsi4@0dmZw94cmqpfhw";
const unsigned long constant = 0xABCDFF8;
unsigned long counter1, counter2, ebx, edi, esi;
char name[26], c_name[26] = {0};
printf(" ____ __ __\n");
printf(" / _/_ _ __ _ ___ ____/ /____ _/ /\n");
printf(" _/ // ' \\/ ' \\/ _ \\/ __/ __/ _ `/ /\n");
printf("/___/_/_/_/_/_/_/\\___/_/ \\__/\\_,_/_/\n");
printf(" ____ __ __\n");
printf(" / __ \\___ ___ _______ ___ ___/ /__ ____ / /____\n");
printf(" / /_/ / -_|_-</ __/ -_) _ \\/ _ / _ `/ _ \\/ __(_-<\n");
printf("/_____/\\__/___/\\__/\\__/_//_/\\_,_/\\_,_/_//_/\\__/___/\n\n");
for (;;){
printf("\nPassword Keeper 4.7 KeyGEN - d0NE bY TORN@DO in '99\n");
printf("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
printf("Name: ");
gets(name);
if (strlen(name)>26)
{printf("ERROR: The name can't be greater than 26 chars!\n"); return 0;}
printf("Company Name: ");
gets(c_name);
if (strlen(c_name)>26)
{printf("ERROR: The company name can't be greater than 26 chars!\n"); return 0;}
if ((strlen(name)<1)) return 0;
else break;
}
counter2=1;
edi=0;
ebx=0;
for (counter1=strlen(name); counter1<(strlen(name)*2); counter1++)
{
ebx = table1[counter1-1] * name[counter2-1];
ebx = ebx * table2[counter2-1];
ebx = ebx * counter2;
counter2++;
edi = edi + ebx;
}
counter2=1;
ebx=0;
esi=0;
for (counter1=strlen(c_name); counter1<(strlen(c_name)*2); counter1++)
{
ebx = table1[counter1-1] * c_name[counter2-1];
ebx = ebx * table2[counter2-1];
ebx = ebx * counter2;
counter2++;
esi = esi + ebx;
}
edi = edi + esi;
edi = edi + constant;
printf("Registration: %lu\n", edi);
return 0;
} |
Another target has been Reverse Engineerd. Any
questions (no crack requests)?
|