Bueno, esto va a intentar ser un pequeo tutorial de como cracker, y hacer un
 key generator del APIspy 32 v2.4.
No me excedere mucho en las explicaciones, porque es un coazo escribir tanto,
y ademas deberiais ir siguiendo el codigo por nuestra cuenta. La verdad es que
quizas me han quedado algo escuetas las explicaciones del codigo, pero es mejor
ir descubriendo que hace cada cosa por vuestra cuenta.No es mi objectivo explicar
lo basico asi que no explicare como deberiais instalar el SoftICE ni que hace un XOR ,
etc... Aun asi creo que me ha quedado comprensible.

Necesitaremos:

 Para el crack : el SoftICE, algo para descomprimir el ejecutable, como por
                 ejemplo el ProcDump32 o el W32Intro, y un editor hexadecimal
                 como el Hiew pej.

 Para el keygen: el SoftICE, conocimientos de algun lenguaje de programacion,
                 y paciencia.

 Para cualquier cosa: Cualquier disco de Heavy Metal.


Donde conseguirlos: http:\\www.crackstore.com  http:\\protools.cjb.net


Empezemos:


Enchufamos el APIS32.
Vemos que nos saca una kk de nag screen diciendonos que no estamos registrados,
(puff, empezamos con mala leche :).


Salimos y enchufamos el SoftICE , entramos en el APIS32 y vamos al boton de
registro, metemos cualquier cosa y antes de aceptar presionamos CTRL+D y entramos
en el SoftICE. Una vez dentro ponemos bpx getdlgitemtexta y bpx getwindowtexta,
volvemos a salir del SoftICE tecleando 'x'. Le damos al botoncito y (pop), ya estamos
ahi,es la primera llamada a getdlgitemtexta, asi que le damos a F11, y nos volvera 
a poner la segunda llamada (hay dos campos) le damos a F11 y ya estamos.
Todo parece ir bien. Normalmente nos encontrariamos el inicio de las rutinas
de proteccion justo despues, pero como el programa esta escrito en un lenguaje
visual (visual C++ 5.0) nos podemos ir preparando para pasar basura.
Bueno despues de unos cuantos miles de instrucciones y unos cientos de ret y retf
llegamos al siguiente trozo de codigo.

0137:0040176A CALL 004046A0
              MOV [0040CE74],EAX

Esta es una manera de comprobar la salida de la funcion menos normal que el
clasico TEST EAX,EAX; JNZ _lejos, pero deberia llamarnos la atencion.
Asi que tecleamos 't' y nos metemos dentro.

Pasando pasando llegamos aqui:

          .
          .
          .

0137:004046B1 CALL 004049D0
              ADD ESP,0C
              CMP EAX,10
              JLE

0137:004046D7 CALL 004049D0
              ADD ESP,0C
              CMP EAX,05
              JLE

Parece claro que esta llamando a una rutina para comprobar la longitud de
nuestro numero y nuestro nombre, y que han de ser >= de 0x10 (16) y 0x05 (5)
respectivamente para que todo siga su curso.

Si todo ha ido bien seguidamente realizara una serie de instrucciones que
modificaran nuestro numero truncandolo en funcion de su longitud, como al
final resultara indiferente la longitud de este no me parare en ellas, solo
dire que para un numero de 18 caracteres la transformacion sera la siguiente:

 pej   bx4B688z0cF0jcL4d0 seria bx4B688zcF0jcL4d
       XXXXXXXX?YYYYYYYY? seria XXXXXXXXYYYYYYYY

 Podriamos substituir las ? por lo que quisieramos, ya que el programa se
 comeria esos valores. En este caso estan substituidos por ceros.

Y llegariamos al comienzo de la chicha del programa.
            -----><----------------------------------------------------------
0137:00404744 PUSH EDI  <<------------------                                |
              CALL 00404930                |                                |
              MOV BL ,CL                   |                                |
              ADD ESP,04                   |                                |
              ADD CL ,50                   |                                |
              ADD EDI,02                   |                                |
              XOR AL, CL                   |                                |
              INC BL                       |                                |
              MOV [ESI-01], AL             |                                |
              MOVE BYTE PTR [ESI], 00      |                                |
              INC ESI                      |                                |
              CMP BL, 08                   |                                |
              JB 00404744   ----------------                                |
                                                                            |
En [EDI] tenemos nuestro numero que es pasado a una funcion, asi que vamos  |
a destriparla, ya que parece importante, antes de seguir.                   |
                                                                            |
CALL 00404930                                                               |
  |                                                                         |
  |                                                                         |
  --->> 0137:00404930 MOV ECX,[ESP+04] ;OFFSET DE NUMERO = PUSH EDI ---------
                      MOV AL, [ECX]    ;AL=primer caracter de pareja
                      CMP AL, 39       ;es numero?
                      JLE 0040493E
                      ADD AL, C9       ;sino le sumo 0xC9
                      JMP 00404940
        0137:0040493E ADD AL, D0       ;si, es numero, asi que le sumo 0xD0(=-0x30)
        0137:00404940 MOV CL, [ECX+01] ;cargo segundo caracter de pareja
                      CMP CL, 39       ;es numero?
                      JLE 00404951
                      SHL AL, 04       ;muevo 1er caracter 4 bits a la izda 
                      SUB CL, 37       ;le resto 37 al segundo caracter
                      OR  AL, CL       ;hago un or de los dos
                      RET
        0137:00404951 SHL AL, 04       ;si, es numero, asi que muevo 4 bits a
                                       ;la izda el primer caracter
                      SUB CL, 30       ;le resto 0x30 al segundo
                      OR  AL, CL       ;hago un or de los dos
                      RET

Esta funcion coge caracteres de nuestro numero de dos en dos y los transforma
en un solor valor que almacena en AL. Para dos numeros es  facil de ver,
ya que pej para 9853... cogeria de memoria el 9 y el 8 (en ASCII 0x39 y 0x38)
y los transformaria hasta quedar en un valor, 0x98.

0x39 + 0xD0 = 0x09  SHL 0x09, 04 = 0x90 |
                                        | OR 0x90, 0x08 = 0x98
0x38 - 0x30 = 0x08                      |

Una vez vista esta funcion, seguimos.

BL tiene un valor inicial de 0

0137:00404744 PUSH EDI  <<------------------     
              CALL 00404930                |      ;funcion transforma parejas                            
              MOV CL ,BL                   |                                
              ADD ESP,04                   |                                
              ADD CL ,50                   |                                
              ADD EDI,02                   |                                
              XOR AL, CL                   |                                
              INC BL                       |                                
              MOV [ESI-01], AL             |                                
              MOVE BYTE PTR [ESI], 00      |                                
              INC ESI                      |
              CMP BL, 08                   |                                
              JB 00404744   ----------------                                

Lo que hace este trozo de codigo es un XOR entre el valor que devuelve la
funcion transforma parejas y el valor 0x50+BL (con BL entre 0 y 7) y lo
almacena en [ESI-01], para ello hace cada vez un PUSH EDI y llama a la funcion.
Cada paso incrementa en dos EDI y en uno BL, y realiza ocho pasos.
Al terminar tendremos nuestro numero truncado de 16 digitos en uno "preprocesado"
de 8.
El funcionamiento es el siguiente:

        pej 9836152478892345  16 caracteres (podrian ser letras)

        cogeria los dos primeros 9 y 8 0x39 y 0x38
        quedarian transformados en 0x98
        le haria un XOR con 0x50+BL (==0x50)
        y lo almacenaria en algo que llamamos numero "preprocesado"

        cogeria los dos segundos 3 y 6 0x33 y 0x36
        quedarian transformados en 0x36
        le haria un XOR con 0x50+BL (==0x51)

        y asi hasta terminar


Y seguimos..

              PUSH 0040C6B4     ;nuestro numero truncado
              PUSH 0040C6A0     ;nuestro numero truncado "preprocesado"
              CALL 00404960     ;la chicha de la transformacion

En la llamada a 00404960 se realizan una serie de transformaciones matematicas
sobre nuestro numero "preprocesado" hasta convertirlo en la llave final.
No me parare en esa funcion, ya que no hay nada que entender, simplemente
efectua sobre cada caracter del numero "preprocesado" una serie de multiplicaciones
y divisiones, que no nos interesan. Tan solo para hacer el keygen nos sera
necesario tracear dentro de esta funcion, y solo para llevar esas transformaciones
al lenguaje de nuestro generador. Ademas el funcionamiento basico se ve bien en el
programa en C adjunto. Simplemente es un bucle anidado en otro que cambia
cada caracter del numero "preprocesado" para convertirlo en el caracter del
numero final.

Una vez transformado el numero "preprocesado" en la llave final, es cuando
trunca nuestro nombre en el caracter octavo. Si el nombre es menor de ocho
caracteres lo concatena consigo mismo y lo trunca en el octavo.

Y llegamos al fin de todo esto. La solucion salta a nuestros ojos.


                    ---------------------------------------------------
                    |                                                  |
                   \/                                                  |
0137:004047F5 MOV AL, [ECX]     ;coge caracter de nombre truncado      |
        .                                                              |
        .                                                              |
        .                                                              |
0137:00404810 MOV DL, [ECX+0A]  ;coge caracter de numero final         |
              XOR EDX,EAX       ;hace un XOR de los dos                |
              ADD EBP,EDX       ;suma el resultado en EBP              |
        .                                                              |
        .                                                              |
        .                                                              |
                                                                       |
        ----------------------------------------------------------------

Hace un bucle ( lo siento no se donde meti las notas sobre las direcciones
del bucle, y no tengo ganas de volver a mirarlo :( ) 8 veces.
En ese bucle va haciendo un XOR entre el nombre y el numero final, sumando
el resultado de cada XOR a EBP.

Al final comprobamos si EBP es cero, y si lo es ponemos AL a 1 (SETZ AL)
Esto que quiere decir?
Pues esto viene porque el resultado tendria que ser similar a este:

nombre                    Perico palotes
nombre truncado           Perico p
numero                    AABBCCDD?EEFFGGHH?
numero truncado           AABBCCDDEEFFGGHH
numero "preprocesado"      M N O P Q R S T 
numero final               P e r i c o   p

Es decir, para que EBP sea igual a 0, el XOR de los valores tendra que ser 0 ,
luego los dos valores deberan ser iguales. => nombre==numero final.

Como no habremos acertado EBP sera distinto de 0 luego deberemos parchear el
codigo, para que introduzca un 1 en AL.


0137:0040481E TEST EBP,EBP   
              POP ESI
              POP EBP
              SETZ AL
              POP EBX
              POP ECX
              RET


Tecleamos CODE ON en el SoftICE.
Nos aparecera esto.

       5E        POP ESI
       5D        POP EBP
       0F94C0    SETZ AL
       5B        POP EBX
       59        POP ECX

Como el SETZ AL ocupa tres bytes deberemos substituir esos tres bytes, una
manera seria asi:

                POP ESI
                POP EBP
                NOP
                NOP
                INC EAX
                POP EBX
                POP ECX

Pero como hay algunos programas que buscan NOP seguidos y cascan, lo podemos
substituir por algo un pelin mas elegante:

                POP ESI
                POP EBP
         40     INC EAX
         48     DEC EAX
         40     INC EAX
                POP EBX
                POP ECX
              
Es entonces cuando raudos y veloces acudimos al editor hexadecimal para parchear
el codigo buscando 5E5D0F94C05B59 para substituirlo por 5E5D4048405B59, pero
he aqui que no lo encontramos, y nos empezamos a preguntar acaso lo he apuntado
mal?. Noooo, lo que pasa es que el ejecutable esta comprimido con Petite 1.2
asi que utilizamos alguno de los unpackers citados al principio del tutorial
y parcheamos despues. Seguidamente introducimos un nombre y un numero y ya esta.

Pero si como yo, no tienes ningun unpacker a mano en este momento, ya puedes
ponerte a hacer un keygen ( aunque sea un coazo :).
Ademas incluyo el codigo del mio en C de forma que no sea muy dificil de seguir.

Hala hasta el proximo tutorial.
Si tienes dudas, preguntas, te aburres o sabes un chiste bueno, mandame un mail.

                                         Shadowmaker.

                                         Shadowmaker@mixmail.com
