                       Cours de cracking n 7 par Flu[X]
                              un autre keygen

NIVEAU: Simple/Intermdiaire

outils
-SoftICE
-Brains
-W32Dasm [OPTIONNEL]
-DLL Demon v1.0    (http://members.aol.com/progency)

Bien, commenons par tlcharger la cible et l'installer. Dans le menu HELP il y a un
bouton REGISTER. Cliquez dessus et une fentre s'affiche...

Nous remarquons que le programme nous demande un nom et un serial, mais qu'il gnre aussi
un code, unique  chaque utilisateur.

OK, Commenons  tracer... Dans softice, tapez un BPX HMEMCPY. Entrez un nom et un serial
bidon, puis tapez sur Entre. SoftIce devrait se manifester. Appuyez une fois sur F5, et
commencez  suivre le code... tapez F12 jusqu' ce que vous arriviez dans DLL Demon. Vous
arrivez rapidement au code suivant:

:00461AC3 8B45F4                  mov eax, dword ptr [ebp-0C]
:00461AC6 8D4DF8                  lea ecx, dword ptr [ebp-08]
:00461AC9 B201                    mov dl, 01
:00461ACB E8FC5B0000              call 004676CC    <- cration de la cl mono-utilisateur 
:00461AD0 8B55F8                  mov edx, dword ptr [ebp-08]
:00461AD3 58                      pop eax
:00461AD4 E8B721FAFF              call 00403C90
:00461AD9 745C                    je 00461B37
:00461ADB 8D55FC                  lea edx, dword ptr [ebp-04]
:00461ADE 8B83F8010000            mov eax, dword ptr [ebx+000001F8]
:00461AE4 E84BEBFBFF              call 00420634
:00461AE9 8B45FC                  mov eax, dword ptr [ebp-04]
:00461AEC 50                      push eax
:00461AED 8D55F4                  lea edx, dword ptr [ebp-0C]
:00461AF0 8B83F4010000            mov eax, dword ptr [ebx+000001F4]
:00461AF6 E839EBFBFF              call 00420634
:00461AFB 8B45F4                  mov eax, dword ptr [ebp-0C]
:00461AFE 8D4DF8                  lea ecx, dword ptr [ebp-08]
:00461B01 33D2                    xor edx, edx
:00461B03 E8C45B0000              call 004676CC    <-Cration de la cl pour une license de Site 
:00461B08 8B55F8                  mov edx, dword ptr [ebp-08]

Premire remarque, les deux CALLs renvoient  la mme adresse... cette routine est utilise plus
d'une fois, donc...

traons donc dans le premier CALL:

  Cration d'une cl pour utilisateur unique
  ==========================================

Nous arrivons au code suivant

:004676CC 55                      push ebp
:004676CD 8BEC                    mov ebp, esp
:004676CF 83C4BC                  add esp, FFFFFFBC
:004676D2 53                      push ebx
:004676D3 894DF4                  mov dword ptr [ebp-0C], ecx
:004676D6 8855FB                  mov byte ptr [ebp-05], dl
:004676D9 8945FC                  mov dword ptr [ebp-04], eax
:004676DC 8B45FC                  mov eax, dword ptr [ebp-04]
:004676DF E850C6F9FF              call 00403D34
:004676E4 33C0                    xor eax, eax
:004676E6 55                      push ebp
:004676E7 6813784600              push 00467813
:004676EC 64FF30                  push dword ptr fs:[eax]
:004676EF 648920                  mov dword ptr fs:[eax], esp
:004676F2 33DB                    xor ebx, ebx
:004676F4 8B45FC                  mov eax, dword ptr [ebp-04]
:004676F7 E884C4F9FF              call 00403B80
:004676FC 85C0                    test eax, eax
:004676FE 7E13                    jle 00467713
:00467700 BA01000000              mov edx, 00000001

Cette partie du code prpare la chane de caractre pour une utilsation ultrieure. Nous
pouvons noter que le code unique est ajout  la fin du nom...

Exemple: Si nous avons     :    name: JoeBob     Code: 122351
notre nouvelle chane sera :    JoeBob122351


* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00467711(C)
|
:00467705 8B4DFC                  mov ecx, dword ptr [ebp-04]
:00467708 0FB64C11FF              movzx ecx, byte ptr [ecx+edx-01] <-lit le caractre en cours
:0046770D 03D9                    add ebx, ecx                     <-ajoute la valeur ascii  EBX
:0046770F 42                      inc edx                          <-positonne le pointeur au
                                                                     caractre suivant
:00467710 48                      dec eax                          <-diminue le compteur de
                                                                     lettres restant  traiter 
:00467711 75F2                    jne 00467705                     <-rpte tant qu'il reste des
                                                                     lettres  traiter 

Les lignes ci-dessus sont vraiement simples... toutes les valeurs ascii de notre chane sont
ajoutes les unes aux autres, et stockes dans EBX.

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004676FE(C)
|
:00467713 807DFB00                cmp byte ptr [ebp-05], 00       <-teste si il s'agit d'une 
                                                                    license multi-utilisateurs
                                                                    (cette fois, c'est non)
:00467717 7475                    je 0046778E
:00467719 8B45F4                  mov eax, dword ptr [ebp-0C]
:0046771C 50                      push eax

* Possible StringData Ref from Code Obj ->"DSU"
                                  |
:0046771D B828784600              mov eax, 00467828
:00467722 8945BC                  mov dword ptr [ebp-44], eax <-met "DSU" dans un "buffer"
:00467725 C645C00B                mov [ebp-40], 0B
:00467729 8BC3                    mov eax, ebx                <-notre "addition" est mise 
                                                                dans eax
:0046772B B90D000000              mov ecx, 0000000D           <-Met Dh (13 dcimal) dans ecx
:00467730 99                      cdq                         <-Converti Double -> Quad
:00467731 F7F9                    idiv ecx                    <-divise Eax par Ecx (13 dcimal)
:00467733 83C259                  add edx, 00000059           <-ajoute 59h au reste
:00467736 8955C4                  mov dword ptr [ebp-3C], edx <-stocke la valeur de EDX
:00467739 C645C800                mov [ebp-38], 00
:0046773D C645CC2D                mov [ebp-34], 2D            <-2Dh = caractre "-" 
:00467741 C645D002                mov [ebp-30], 02
:00467745 895DD4                  mov dword ptr [ebp-2C], ebx <-Stocke notre "somme ascii" 
:00467748 C645D800                mov [ebp-28], 00
:0046774C 8BC3                    mov eax, ebx                <-met notre "somme ascii" dans eax
:0046774E 2503000080              and eax, 80000003           <-"somme ascii" AND 80000003h
:00467753 7905                    jns 0046775A
:00467755 48                      dec eax
:00467756 83C8FC                  or eax, FFFFFFFC
:00467759 40                      inc eax

Une petite explication de ce code...
D'abord, nous pouvons voir que toutes les licenses mono-utilisateur commencent par "DSU".
Ensuite, un coup d'oeil  la partie mathmatique.

La somme des valeurs ascii explique plus haut est utilise. Cette valeur est divise par
13 (soir D en hexa). Quand vous utilisez la fonction (opcode) IDIV, la partie entire de la 
division est stockes dans EAX, et le reste est mis dans EDX. Par exemple:

Disons que EAX soit gal  33 (dcimal), aprs un IDIV, EAX=2 et EDX=7 car :
2*13 + 7 = 33 (dans ce cas, on n'utilse pas de virgule... revoyez vos cours de math sur les 
nombres entiers si ncessaire...)

Donc le code ci-dessus additionne toutes nos valeurs ascii, divise le rsultat par 13, et
rajoute 59 (en hexa, pas en dcimal) au reste. De plus, il prend notre addition de valeurs
ascii et applique une opration logique AND avec la valeur hexa 80000003. 

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00467753(C)
|
:0046775A 8945DC                  mov dword ptr [ebp-24], eax  <-Stocke le rsultat du AND
:0046775D C645E000                mov [ebp-20], 00
:00467761 C645E42D                mov [ebp-1C], 2D             <-ajoute "-"  la chane
:00467765 C645E802                mov [ebp-18], 02
:00467769 8BC3                    mov eax, ebx                 <-"somme ascii" dans eax
:0046776B B903000000              mov ecx, 00000003            <-met 3 dans ecx 
:00467770 99                      cdq
:00467771 F7F9                    idiv ecx                     <-divise par 3
:00467773 8945EC                  mov dword ptr [ebp-14], eax  <-rsultat envoy dans la chane
:00467776 C645F000                mov [ebp-10], 00
:0046777A 8D55BC                  lea edx, dword ptr [ebp-44]
:0046777D B906000000              mov ecx, 00000006

Donc, nous avons l'algorithme de base pour la cl mono-utilisateur:

RAPPEL
=====
NOM & Serial combins en 1 chane
X= somme de toutes les valeurs ascii de la chane combine

PUIS...

Serial# =  DSU + (reste(X/13)+59h) + "-" + X + (X AND 80000003h) + "-" + entier de (X/3)


    Cration d'une cl multi-utilisateurs (license de Site)
    =======================================================

Traons donc dans le second CALL cette fois...

Cette partie du code ajoute le code unique  notre nom...
pour le license multi-utilisateur, le programme ne se sert QUE de notre nom. Le code unqiue
est purement et simplement ignor !

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00467711(C)
|
:00467705 8B4DFC                  mov ecx, dword ptr [ebp-04]
:00467708 0FB64C11FF              movzx ecx, byte ptr [ecx+edx-01] <-caractre en cours
:0046770D 03D9                    add ebx, ecx                     <-ajoute l'ascii  EBX
:0046770F 42                      inc edx                          <-pointeur sur car. suivant
:00467710 48                      dec eax                          <-diminue nombre de lettres
                                                                     restant  traiter 
:00467711 75F2                    jne 00467705                     <-continue tant qu'il reste
                                                                     des lettres

Mme cas que pour la license mono, on ajoute toutes les valeurs ASCII les unes aux autres, le
rsultat est dans EBX.

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004676FE(C)
|
:00467713 807DFB00                cmp byte ptr [ebp-05], 00       <-license multi ?
:00467717 7475                    je 0046778E                     <-oui, alors on saute


* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00467717(C)

:0046778E 8B45F4                  mov eax, dword ptr [ebp-0C]    
:00467791 50                      push eax
:00467792 B84C784600              mov eax, 0046784C
:00467797 8945BC                  mov dword ptr [ebp-44], eax <-Stocke "DS" dans le Buffer
:0046779A C645C00B                mov [ebp-40], 0B
:0046779E 8BC3                    mov eax, ebx                <-"somme ascii" dans EAX
:004677A0 B909000000              mov ecx, 00000009           <- mets 9 dans ECX
:004677A5 99                      cdq
:004677A6 F7F9                    idiv ecx                    <-Divise par 9
:004677A8 83C243                  add edx, 00000043           <-Ajoute 43 hexa au reste de la
                                                                division
:004677AB 8955C4                  mov dword ptr [ebp-3C], edx <-et stocke le dans le buffer
:004677AE C645C800                mov [ebp-38], 00
:004677B2 C645CC2D                mov [ebp-34], 2D            <- ajoute "-" au serial
:004677B6 C645D002                mov [ebp-30], 02
:004677BA 895DD4                  mov dword ptr [ebp-2C], ebx <-stocke la "somme ascii"
:004677BD C645D800                mov [ebp-28], 00
:004677C1 8BC3                    mov eax, ebx                <-"somme ascii" dans EAX
:004677C3 B905000000              mov ecx, 00000005           <-met 5 dans ECX
:004677C8 99                      cdq
:004677C9 F7F9                    idiv ecx                    <-Divise par 5
:004677CB 8955DC                  mov dword ptr [ebp-24], edx <-mets le reste dans le buffer
:004677CE C645E000                mov [ebp-20], 00
:004677D2 C645E42D                mov [ebp-1C], 2D            <-ajoute un "-" au buffer
:004677D6 C645E802                mov [ebp-18], 02
:004677DA 85DB                    test ebx, ebx
:004677DC 7903                    jns 004677E1
:004677DE 83C303                  add ebx, 00000003

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004677DC(C)
|
:004677E1 C1FB02                  sar ebx, 02                 <-similaire  SHR (Shift Right)
:004677E4 895DEC                  mov dword ptr [ebp-14], ebx <-rsultat du SAR dans le Buffer
:004677E7 C645F000                mov [ebp-10], 00
:004677EB 8D55BC                  lea edx, dword ptr [ebp-44]
:004677EE B906000000              mov ecx, 00000006

Ainsi, l'algorithme de base pour la license multi-utilisateurs est le suivant:

RAPPEL
======
X= Somme des valeurs ascii de notre nom (cette fois, pas le serial)

PUIS...

cl multi =  "DS" + (reste de (X/9)+43h) + "-" + X + reste de (X/5) + "-" + X SHR 2

Et voici le source de mon keygen... Je sais, je suis nul en tant que programmeur en pascal,
mais a marche !

===Dbut du Code===

var
 name:string;
 secondc:integer;
 serialn:string;
 eax,ecx,edx:longint;
 pos:integer;

begin


 writeln('DLL Demon v1.0 Keygen');
 writeln('Flu[X]/PC98');
 writeln('12/21/98');
 writeln(' ');
 write('Enter Name : ');
 readln(name);
 write('Enter Serial Number : ');
 readln(serialn);
 writeln('');
 write('Site License Key: ');

  {Generate Site License Key}
 pos:=1;
 ecx:=0;
 while pos <= length(name) do
 begin
  ecx:= ecx+ord(name[pos]);
  pos:=pos+1;
 end;
 eax:=ecx;
 edx:=0;
  while ecx >=9 do
  begin
   ecx:=ecx-9;
  end;
  ecx:=ecx+$43;
  write('DS',ecx,'-',eax);
  ecx:=eax;
  while ecx >=5 do
  begin
   ecx:=ecx-5;
  end;
  write(ecx,'-');
  ecx:=eax;
  ecx:=ecx SHR 2;
  writeln(ecx);
  write('Single User Key : ');


  {Single User Generation}
  name:=name+serialn;
  pos:=1;
  ecx:=0;
  while pos <= length(name) do
  begin
   ecx:= ecx+ord(name[pos]);
   pos:=pos+1;
  end;
  eax:=ecx;
  while ecx >=13 do
  begin
   ecx:=ecx-13;
  end;
  ecx:=ecx+$59;
  write('DSU',ecx,'-',eax);
  ecx:=eax;
  ecx:= ecx AND $80000003;
  write(ecx,'-');
  ecx:=eax;
  edx:=0;
  while ecx >=3 do
  begin
   ecx:=ecx-3;
   edx:=edx+1;
  end;
  writeln(edx);

end.


===FIN DU CODE===


J'espre vous retrouver dans mon cours n 8
Comme d'habitude si vous utilisz dfinitivement un programme, PAYER-LE ! Cet essai est  but
ducationnel seulement ! Les programmeurs ont besoin de votre soutien !

Flu[X]/PC98
http://tuts98.cjb.net
pcflux@hotmail.com

French Translation
HarvestR
http//surf.to/HarvestR (ou http://harvestr.cjb.net)
harvestr@cedric.org

