Como crear un Keygen By: ^pain^

Iniciado por ANTRAX, Febrero 20, 2010, 02:52:22 AM

Tema anterior - Siguiente tema

0 Miembros y 3 Visitantes están viendo este tema.

¿Cómo hacer generadores de código?
                     -===========================-

Introducción
------------
No me responsabilizo del uso de esta información.
Este tutorial, es sólo para conocimiento educativo.

Hola, en este tutorial, tengo la intención de enseñarte como realizar
un bueno y sencillo generador de códigos, del programa llamado W3Filer 32 V1.1.3.
W3Filer es un buen y útil "bajador" Web...
Doy por supuesto que conoces el programa.


Doy por hecho que sabes:
A. Como usar un depurador (en este caso, SoftIce).
B. Como crackear, de forma general (encontrando rutinas de protección, parcheándolos, etc...).
C. Como usar un desensamblador (Este conocimiento puede ayudar).
D. Ensamblador.
E. Programar en Turbo Pascal (tm).

Herramientas necesarias:
A. SoftIce 3.00/01 o posterior.
B. WD32Asm. (No obligatorio).
C. El programa W3Filer V1.13 (Si no viene en este paquete),
puede ser encontrado en No tienes permitido ver los links. Registrarse o Entrar a mi cuenta creo.
D. Turbo Pascal (alguna versión).

Bueno, suficiente blah blah, sugiero crackear...
Ejecuta W3Filer 32.
Una pantalla molesta surge, y, demanda el registro; Ahora,
Observamos que este programa tiene algún tipo de número de serie (el mío es 873977046),
Sugiero mantener éste en mente, apuesto a que lo encontraremos de nuevo mientras
estamos en el depurador.

Bien, ahora, sugiero que pongas tu nombre y un código de registro ficticio...
establece un BP en GetDlgItemTextA, y, pulsa OK.
Entramos dentro de GetDlgItemTextA, sugiero encontrar la rutina de registro...
Te ahorraré el trabajo, la rutina de registro es ésta:

:00404DB2 8D95A8FAFFFF            lea edx, dword ptr [ebp+FFFFFAA8]
:00404DB8 52                      push edx          ---> Tu nombre de usuario.
:00404DB9 E80B550000              call 0040A2C9     ---> Rutina de registro.
:00404DBE 83C408                  add esp, 00000008 ---> no sé exactamente que es.
:00404DC1 85C0                    test eax, eax     ---> Identificador booleano, 0 si
:00404DC3 7D17                    jge 00404DDC      ---> el registro falla, 1 si
                                                         OK.

Bien, entremos en CALL 40A2C9, y veamos que hay dentro:
(Por favor lee mis comentarios del código).

* Referenced by a CALL at Addresses:
|:00404DB9   , :00407F76   
|
:0040A2C9 55                      push ebp
:0040A2CA 8BEC                    mov ebp, esp
:0040A2CC 81C4B0FEFFFF            add esp, FFFFFEB0
:0040A2D2 53                      push ebx
:0040A2D3 56                      push esi
:0040A2D4 57                      push edi
:0040A2D5 8B5508                  mov edx, dword ptr [ebp+08]
:0040A2D8 8DB500FFFFFF            lea esi, dword ptr [ebp+FFFFFF00]
:0040A2DE 33C0                    xor eax, eax
:0040A2E0 EB16                    jmp 0040A2F8

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040A2FB(C)
|
:0040A2E2 0FBE0A                  movsx ecx, byte ptr [edx] ----> Aquí comienza la parte interesante.
:0040A2E5 83F920                  cmp ecx, 00000020         ----> ECX es el carácter actual del nombre del usuario, Hmm, 20h=' '...
:0040A2E8 740D                    je 0040A2F7               ----> Veamos,
:0040A2EA 8A0A                    mov cl, byte ptr [edx]    ----> ¡Generalmente, todo este bucle lo que hace, es copiar
                                                                  el nombre de usuario desde [EDX], a [ESI], SIN los espacios!
                                                                  (¡Manténlo en mente!).           
:0040A2EC 880C06                  mov byte ptr [esi+eax], cl
:0040A2EF 42                      inc edx
:0040A2F0 40                      inc eax
:0040A2F1 C6040600                mov byte ptr [esi+eax], 00
:0040A2F5 EB01                    jmp 0040A2F8

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040A2E8(C)
|
:0040A2F7 42                      inc edx

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0040A2E0(U), :0040A2F5(U)
|
:0040A2F8 803A00                  cmp byte ptr [edx], 00
:0040A2FB 75E5                    jne 0040A2E2 ----------------> Este es el salto , tenemos lo que hace,
                                                                 Sugiero inspeccionar el código...
                                               
:0040A2FD 56                      push esi     --------> El nombre de usuario es introducido, para
                                                         pasar a mayúscula sus caracteres.                                                       

* Reference To: USER32.CharUpperA, Ord:0000h
                                  |
:0040A2FE E80F330000              Call User!CharUpper ---> Después, nuestro nombre está en mayúsculas.
:0040A303 56                      push esi   -----> Nuestro nombre está en mayúsculas aquí.

* Reference To: cw3220mt._strlen, Ord:0000h
                                  |
:0040A304 E86F300000              Call 0040D378 ---> Esta es la longitud de nuestro nombre.
:0040A309 59                      pop ecx       
:0040A30A 8BC8                    mov ecx, eax  ---> ECX=Longitud.
:0040A30C 83F904                  cmp ecx, 00000004 ---> Longitud>=4 (OBLIGATORIO).
:0040A30F 7D05                    jge 0040A316    ---> Veamos esta dirección...
:0040A311 83C8FF                  or eax, FFFFFFFF
:0040A314 EB67                    jmp 0040A37D

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040A30F(C)
|
:0040A316 33D2                    xor edx, edx
:0040A318 33C0                    xor eax, eax
:0040A31A 3BC8                    cmp ecx, eax
:0040A31C 7E17                    jle 0040A335 ---> (No importante, es otro chequeo inútil).

===================================================================================
============ DE AQUÍ PARA ADELANTE EL CÓDIGO IMPORTANTE, PON ATENCIÓN =============
===================================================================================

Una cosa antes de continuar, EDX = 00000000h así accedemos a las siguientes intrucciones.

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040A333(C)
|                               
:0040A31E 0FBE1C06                movsx ebx, byte ptr [esi+eax] ---> EBX <--- Carácter del nombre de usuario, offset EAX.
:0040A322 C1E303                  shl ebx, 03  -----> Hmm, shl al carácter por 03h...(Recuérdalo).
:0040A325 0FBE3C06                movsx edi, byte ptr [esi+eax] ---> Ahora EDI <---Carácter del nombre de usuario  , offset EAX.
:0040A329 0FAFF8                  imul edi, eax   -----> ¡multiplica el carácter por el offset del carácter en el nombre de usuario! (Recuérdalo).
:0040A32C 03DF                    add ebx, edi    -----> Suma el resultado a EBX (Era el caparazón (Ding Dong =)).
:0040A32E 03D3                    add edx, ebx    -----> ¡¡¡EDX=EDX+EBX!!! - ¡¡¡Esto es el corazón de esta rutina de registro!!!
:0040A330 40                      inc eax         -----> Aumenta EAX en uno (siguiente carácter).
:0040A331 3BC8                    cmp ecx, eax   
:0040A333 7FE9                    jg 0040A31E     ----> Si ECX<EAX entonces, dejamos el bucle.

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040A31C(C)
|
:0040A335 A120674100              mov eax, dword ptr [00416720] ---> HMMMMMM, ¿¿¿¿¿Qué es esto?????
:0040A33A C1F803                  sar eax, 03  ---------> ¡ESPERA! Teclea en SIce '? EAX'
                                                          ¿No es el número de EAX familiar para nosotros? ;-)
                                                          Si todavía no entiendes, que, ¡es nuestro NÚMERO
                                                          DE SERIE! (¡PORFAVOR, tómate tu tiempo, y verifícalo
                                                          por ti mismo - no te fíes de mí!). OK, ahora sabemos,
                                                          qué  SHR's EAX por 03 (SAR es casi idéntico a SHR).
:0040A33D 03D0                    add edx, eax ---------> Hmm, añade el resultado del bucle, al número de serie shr por 03h
:0040A33F 52                      push edx     -------> Continuemos. (En este punto, te puedo decir, el número de registro, está
                                                        en EDX - sólo que el número de serie está en HEX --> Así es como accedemos a él).

* Possible StringData Ref from Data Obj ->"%lx"
                                  |
:0040A340 685EF54000              push 0040F55E
:0040A345 8D95B0FEFFFF            lea edx, dword ptr [ebp+FFFFFEB0]
:0040A34B 52                      push edx

* Reference To: USER32.wsprintfA, Ord:0000h
                                  |
:0040A34C E8E5320000              Call 0040D636  -------> Esto, hace HEX2STR (Toma el valor de EDX, y lo pone en una cadena en hexa).
:0040A351 83C40C                  add esp, 0000000C
:0040A354 8D8DB0FEFFFF            lea ecx, dword ptr [ebp+FFFFFEB0] -----> ¡Escribe 'd ecx' - Es el número de reg! Es suficiente para nosotros, el resto del
código, es para comparar el código reg correcto con el nuestro.
:0040A35A 51                      push ecx

* Reference To: USER32.CharLowerA, Ord:0000h
                                  |
:0040A35B E8B8320000              Call 0040D618
:0040A360 8D85B0FEFFFF            lea eax, dword ptr [ebp+FFFFFEB0]
:0040A366 50                      push eax
:0040A367 FF750C                  push [ebp+0C]

* Reference To: cw3220mt._strcmp, Ord:0000h
                                  |
:0040A36A E875300000              Call 0040D3E4
:0040A36F 83C408                  add esp, 00000008
:0040A372 85C0                    test eax, eax
:0040A374 7405                    je 0040A37B
:0040A376 83C8FF                  or eax, FFFFFFFF
:0040A379 EB02                    jmp 0040A37D

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040A374(C)
|
:0040A37B 33C0                    xor eax, eax

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0040A314(U), :0040A379(U)
|
:0040A37D 5F                      pop edi
:0040A37E 5E                      pop esi
:0040A37F 5B                      pop ebx
:0040A380 8BE5                    mov esp, ebp
:0040A382 5D                      pop ebp
:0040A383 C3                      ret


              Haciendo el keygen actual
              ~~~~~~~~~~~~~~~~~~~~~~~~~
Ahora, después de haber explicado como el programa calcula el código de registro,
puedes escribir tu propio generador, sin mirar el código, o mirar el código
(en Turbo Pascal - lo siento por todos los amantes del C ;-) La próxima vez).
Así pues, aquí está el fuente de mi keygen:

------------------- Cortar por aquí -----------------------------------------

Program W3FilerKeygen;
var
   Key,SerialNum,EB,ED,digit:Longint;
   I,x:Byte;
   Name,KeyHex:String;
begin
   Writeln('  W3Filer32 V1.1.3 Keymaker');
   writeln('Cracked by ^pain^ ''97 / Rebels!');
   Write('Your Name:');      { Lee el nombre }
   readln(Name);             
   Write('Serial Number:');
   readln(SerialNum);        {¡Sí, necesitamos el número de serie para los cálculos!}
   Key:=0;
   x:=0;
   For I:=1 to length(Name) do
   begin
      Name:=upcase(Name);
      If Name<>' ' then begin
       eb:=ord(Name) shl 3;  {EB = Name Shl 03h}
       Ed:=ord(Name);        {ED = Name}
       ed:=ed*(x);              {ED=ED*Offset}
       inc(x);                 
       eb:=eb+ed;               {Suma ED a EB}
       Key:=Key+EB;             {Suma EB a KEY}
      end;
   end;
   Key:=Key+(SerialNum shr 3);  { Suma SerialNum shr 03h a Key}

   { Desde aquí, ésto es HEX2STRING --> Estoy bastante seguro de que es
     auto explicativo, sino - ¡ves y aprende de nuevo la base de los números! ;-)}
   KeyHex:='';
   repeat
      digit:=Key mod 16;
      key:=key div 16;
      If digit<10 then KeyHex:=Chr(Digit+ord('0'))+KeyHex;
      If digit>10 then KeyHex:=Chr(Digit-10+ord('a'))+KeyHex;
   until key=0;
   writeln('Your Key:',KeyHex);
   writeln('                 Enjoy!');
end.

--------------------- Cortar por aquí ---------------------------------------

Este tutorial fue escrito por ^pain^ / [mEXELiTE '97], Espero que disfrutes
leyéndolo, siempre intento mejorar mi técnica de escritura =).

Hmm, Me gustaría darle las gracias a los siguientes: (Sin ningún orden especial)

Blast Soft,Teraphy,J0b,Qapla,+ORC,Fravia,Charley,GhostRdr,Odin,kOUGER
Niabi,Acpizer,Klagosong,Mystic Rioter,rANDOM,riDDLER (¡Regresa hombre!
te NECESITAMOS),yoshi,JosephCo,Leddy,Krazy_N,Vizion,Gunnar_,Volcanic,
Fant0m,Caruso,|PSA|,razzi,ThePharao,|KAIRN| + A todos de #cracking y en
#cracking4newbies, y naturalmente - a todos los que olvido. ;)

------------ Terminado - ^pain^ --------------------------------------