Karpoff Spanish Tutor

Programa:

Image Wolf 1.04 Build 005


 

PROTECCION:

Name / Serial.

Objetivo:

Hacer un Keygen.

Descripcion:

Parece que busca en la Red, archivos gráficos o de video.

Dificultad:

Aficionado.

DOWNLOAD:

http://www.trellian.com/bin/iwolf104.exe

Herramientas:

Softice, Masm.

CRACKER:

CaoS ReptantE

  FECHA:

06/09/2001

 

 INTRODUCCION

Bueno, ya estamos aquí de nuevo. Este será probablemente el último tuto de CaoS ReptantE sobre keygens, y aún es posible que después vuelva a las tinieblas de donde salió... Hoy nos enfrentamos a un programa que hubiera podido resultar muy complicado para encontrar el sistema de generación del serial, si no fuera por unos pocos fallos tontos del programador. Veremos como una buena idea, queda malograda por esos fallos. La buena idea consiste en que para obtener el serial se basa, además de en el nombre con el que queremos registrarnos, en los primeros caracteres del propio serial que introducimos. Esto significa que si esos caracteres no son los correctos, el número que encontraremos, y con el que trataremos de registrarnos, no servirá para nada. ┐Cuál es el fallo entonces? Que la comparación de esos caracteres se hace de una manera descarada y por si fuera poco, antes de generar el número, cuando sería mucho mejor hacerlo después de haber generado el número, y con un poco más de discreción. De manera que, aunque como de costumbre el código que genera el serial está metido entre toneladas de basura, hasta el más despistado se entera de que los tres primeros caracteres del serial son "IW-".

 

 AL ATAKE

Una vez cargado el SoftIce, ejecutaremos el programa y trataremos de registrarnos. Introduciremos nuestro nombre (en mi caso: "CaoS ReptantE") y un número de registro chungo. Antes de darle a OK, hacemos ctrl-D para entrar en el SIce y establecemos un breakpoint: bpx getdlgitemtexta. F5 para continuar y OK. Salta el SIce, F5 nuevamente para que lea la segunda ventana de texto y F12 que nos lleva a:  

:0040BFF6 6A52                    push 00000052

Ahora buscaremos en la memoria nuestro serial chungo mediante la instrucción s 30:00 l ffffffff 'serial_chungo' y la instrucción s para continuar buscando. Nos aparece el número en dos posiciones de la memoria. A continuación, introduciremos la instrucción bpr inicio_dirección_obtenida final_dirección_obtenida r para cada una de las direcciones halladas para pillar al programa cuando lee nuestro serial. Pulsamos F5 para continuar, e iremos alternando F10 para tracear con paciencia ya que el camino esta lleno de basura y F5, hasta llegar a:

:0040CAE4 0FBE02                  movsx eax, byte ptr [edx]
:0040CAE7 83F849                  cmp eax, 00000049
:0040CAEA 7523                    jne 0040CB0F

Aquí vemos la comparación entre el primer carácter de nuestro serial chungo e "I". (49h)

:0040CAEF 0FBE5101                movsx edx, byte ptr [ecx+01]
:0040CAF3 83FA57                  cmp edx, 00000057
:0040CAF6 7517                    jne 0040CB0F

Vemos ahora la comparación entre el segundo carácter y "W". (57h)

:0040CAF8 6A2D                    push 0000002D
:0040CAFA 8B450C                  mov eax, dword ptr [ebp+0C]
:0040CAFD 50                      push eax
:0040CAFE E85D230100              call 0041EE60

Como nos mosquea ver 2D (código de "-"), entramos en el call y vemos:

:0041EE79 3807                    cmp byte ptr [edi], al
:0041EE7B 7404                    je 0041EE81

Comparación entre el tercer carácter y "-". ┐No os habíais dado cuenta de que se efectuaban esas comparaciones? No importa. El programador lo ha previsto y os da una segunda oportunidad ;-)

:0040CD5C 0FBE08                  movsx ecx, byte ptr [eax]
:0040CD5F 83F949                  cmp ecx, 00000049
:0040CD62 750C                    jne 0040CD70

:0040CD67 0FBE4201                movsx eax, byte ptr [edx+01]
:0040CD6B 83F857                  cmp eax, 00000057
:0040CD6E 7407                    je 0040CD77

Aunque no lo indico, también vuelve a comprobar el guión, por si acaso :-D Le damos a F5 y continuamos:

:0041EE0B 8B01                    mov eax, dword ptr [ecx]

Traceamos a partir de aquí y vemos que estamos en un bucle en el que se van moviendo cosas. Y una de las cosas que se mueven es nuestro serial chungo (en EDX), que se copia en otra dirección (EDI)

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0041EE1E(C), :0041EE38(U)
|
:0041EE01 8917                    mov dword ptr [edi], edx

Ahora ampliaremos nuestro campo de búsqueda mediante la instrucción bpr inicio_nueva_dirección final_nueva_dirección r. Continuamos con F5 y vemos que verifica de nuevo el guión y substituye su código ASCII (2D) por 00. Nuevamente F5 y caemos en:

:0040CBC6 0FBE11                  movsx edx, byte ptr [ecx]
:0040CBC9 83FA52                  cmp edx, 00000052
:0040CBCC 7502                    jne 0040CBD0

Aquí comprueba si el primer carácter del serial es "R". Esta es una de las incógnitas que le quedan al programa, la otra es que genera otro serial correcto además del que vamos a encontrar. Si alguien quiere entretenerse, ya sabe como... :-) F5 una vez más y:

:0040CBEE 0FBE11                  movsx edx, byte ptr [ecx]
:0040CBF1 83C209                  add edx, 00000009

Toma el código ASCII del primer carácter de nuestro serial ("I" = 49h) y le suma 9 (52h)
(A partir de aquí sólo voy a poner las instrucciones necesarias para entender la generación del serial, porque sino, esto se puede convertir en un galimatías)

:0040CBF7 8A84057CFFFFFF mov al, byte ptr [ebp+eax-00000084]

En esta posición de memoria, se han situado las cuatro primeras letras de nuestro nombre (en mi caso "CaoS"). Ahora tomamos el código de la primera de ellas ("C" = 43h).

:0040CBFE F6EA                    imul dl
:0040CC03 88840D7CFFFFFF          mov byte ptr [ebp+ecx-00000084], al

Ha multiplicado 43h por 52h (1576h) y ha puesto 76 en el lugar que ocupaba la "C". Este proceso se repite con los códigos de las otras tres letras y luego se vuelve a efectuar con el código del siguiente carácter del número ("W" = 57h) al que se le suma 9 (60h) y se multiplica por los resultados obtenidos en el primer proceso:

C  a  o  S      43   61   6F   53
   x 52h         76   12   8E   96
   x 60h         40   C0   40   40

:0040CC47 8B4508                  mov eax, dword ptr [ebp+08]
:0040CC4A 034588                  add eax, dword ptr [ebp-78]

En EAX tenemos la dirección de la cadena "CaoS ReptantE"

:0040CC4D 0FBE08                  movsx ecx, byte ptr [eax]
:0040CC50 83C109                  add ecx, 00000009

Tenemos ECX = 4Ch ("C" = 43h, + 9 = 4C)

:0040CC56 8A84157CFFFFFF          mov al, byte ptr [ebp+edx-00000084]
:0040CC5D 32C1                    xor al, cl
:0040CC62 88840D7CFFFFFF          mov byte ptr [ebp+ecx-00000084], al

Ha tomado el primero de los cuatro números obtenidos anteriormente (40) y lo ha "xoreado" con 4Ch, a continuación ha puesto el resultado (0C) en el lugar que ocupaba el número. Este proceso se repite, primero con los otros tres números y luego con cada letra de las que forman el nombre.

                 40   C0   40   40
 XOR 4Ch         0C   8C   0C   0C
....
....
 XOR 4Eh         74   F4   74   74

:0040CC6D 8B957CFFFFFF mov edx, dword ptr [ebp+FFFFFF7C]
:0040CC73 8955FC mov dword ptr [ebp-04], edx

Ha colocado el número obtenido en otro lugar. A continuación hace algunas comparaciones de las que tomaremos nota para hacer el keygen.

:0040CC76 837DFC00                cmp dword ptr [ebp-04], 00000000
:0040CC7A 7D08                    jge 0040CC84
:0040CC7C 8B45FC                  mov eax, dword ptr [ebp-04]
:0040CC7F F7D8                    neg eax
:0040CC81 8945FC                  mov dword ptr [ebp-04], eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040CC7A(C)
|
:0040CC84 837DFC00                cmp dword ptr [ebp-04], 00000000
:0040CC88 7507                    jne 0040CC91
:0040CC8A C745FC01000000          mov [ebp-04], 00000001

Si el número es igual a cero, lo hace igual a uno.

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0040CC88(C), :0040CCA3(U)
|
:0040CC91 817DFC0F270000          cmp dword ptr [ebp-04], 0000270F
:0040CC98 7D0B                    jge 0040CCA5
:0040CC9A 8B4DFC                  mov ecx, dword ptr [ebp-04]
:0040CC9D 6BC90A                  imul ecx, 0000000A
:0040CCA0 894DFC                  mov dword ptr [ebp-04], ecx
:0040CCA3 EBEC                    jmp 0040CC91

Aquí tenemos otro fallo que nos ahorrará trabajo. Compara el número con 270Fh, que es igual a 9999, con lo que nos está diciendo que vamos bien y que deberemos pasar este número a decimal (a veces es conveniente, cuando aparece uno de esos números cabalísticos, buscar su equivalencia en decimal). Si es inferior, lo va multiplicando por diez hasta que es igual o mayor. Me parece que se ha equivocado, ha puesto jge, cuando tenía que haber puesto jg :-D

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0040CC98(C), :0040CCBC(U)
|
:0040CCA5 817DFC3F420F00          cmp dword ptr [ebp-04], 000F423F
:0040CCAC 7E10                    jle 0040CCBE
:0040CCAE 8B45FC                  mov eax, dword ptr [ebp-04]
:0040CCB1 99                      cdq
:0040CCB2 B90A000000              mov ecx, 0000000A
:0040CCB7 F7F9                    idiv ecx
:0040CCB9 8945FC                  mov dword ptr [ebp-04], eax
:0040CCBC EBE7                    jmp 0040CCA5

Aquí compara el número con F423Fh (999999) y si es mayor, lo divide por diez. Aquí lo ha hecho bien :-) Ha dividido nuestro número (7474F474h) por Ah cuatro veces hasta conseguir el número 2FB36h que es igual a 195382. Así pues, ya hemos conseguido nuestro serial.  

Bien, ya tenemos todos los mimbres para hacer el cesto :-) y podemos hacer el keygen. Para ello echaremos mano, como en otras ocasiones, del Masm32. Necesitaremos crear dos archivos: el de recursos rsrc.rc y el del código, al que llamaremos por ejemplo IWolf.asm. Del primero no voy a comentar nada, pues es prácticamente igual al de otros keygens que hemos hecho, como por ejemplo el del Power Archiver; y del segundo sólo comentaré el procedimiento operacion que es donde generaremos el serial, porque la parte restante también la hemos visto en tutos anteriores.

.386

.model flat,stdcall

option casemap:none

include c:\masm32\include\windows.inc
include c:\masm32\include\user32.inc
include c:\masm32\include\kernel32.inc
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib

.const

IDD_DIALOG          EQU 1000
IDC_NAME            EQU 1001
IDC_SERIAL          EQU 1002
IDC_GEN             EQU 1003
IDC_EXIT            EQU 1004

DlgFunc PROTO :DWORD,:DWORD,:DWORD,:DWORD
Operacion PROTO

.data

nombre db 64 dup(0),0
numero db 4 dup(0),0
serial db 9 dup(0),0
nada db 20 dup(0),0
Icono db "keygen",0
Iconimage db "keygen",0
minombre db "CaoS ReptantE",0
menosde4 db "íMínimo 4 caracteres!",0
hInstance dd 0
hIcon dd 0
hWnd dd 0

.code

start:

      invoke GetModuleHandle,NULL
      mov hInstance,eax
      invoke DialogBoxParam,hInstance,IDD_DIALOG,NULL,addr DlgFunc,NULL
      invoke ExitProcess,NULL

DlgFunc proc hDlg:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD

.if uMsg==WM_INITDIALOG
      mov eax,hDlg
      mov hWnd,eax
      invoke LoadIcon,hInstance,addr Icono
      mov hIcon,eax
      invoke SendMessage, hDlg, WM_SETICON,1,hIcon
      invoke SetDlgItemText,hDlg,IDC_NAME,ADDR minombre
.elseif uMsg==WM_CLOSE
      invoke EndDialog,hDlg,NULL
.elseif uMsg==WM_COMMAND
      mov eax,wParam
      mov edx,eax
      shr edx,16
      .if dx==BN_CLICKED
         .if ax==IDC_EXIT
            invoke SendMessage,hDlg,WM_CLOSE,0,0
         .elseif ax==IDC_GEN
            invoke GetDlgItemText,hDlg,IDC_NAME,ADDR nombre,80
            invoke lstrlen,ADDR nombre
            invoke Operacion
            .if eax==1
               invoke SetDlgItemText,hDlg,IDC_NAME,ADDR nada
               invoke SetDlgItemText,hDlg,IDC_SERIAL,ADDR menosde4
            .else
               invoke SetDlgItemText,hDlg,IDC_SERIAL,ADDR serial
               invoke SetDlgItemText,hDlg,IDC_NAME,ADDR nombre
            .endif
            ret
         .endif
      .endif
.endif
ret
DlgFunc endp

Operacion proc

            .if eax < 4
               mov eax,1
               ret
            .endif
            pushad

Comprobamos que el nombre no tiene menos de cuatro letras y guardamos los registros, por lo que pueda ser...

            mov ebx, offset nombre
            mov ecx, offset numero
            xor eax, eax
bucle1:     mov dl, byte ptr [ebx+eax]
            mov byte ptr [ecx+eax], dl
            inc eax
            .if al < 4
               jmp bucle1
            .endif

Tomamos los códigos ASCII de las cuatro primeras letras del nombre y los ponemos en numero.

            push ecx
bucle2:     mov eax, 52h
            mov dl, byte ptr [ecx]
            .if dl==0
               jmp seguir1
            .endif
            imul dl
            mov byte ptr [ecx], al
            inc ecx
            jmp bucle2

Después de guardar la dirección de numero, multiplicamos los cuatro números que teníamos por 52h (código de "I" = 49, más 9)

seguir1:    pop ecx
            push ecx
bucle3:     mov eax, 60h
            mov dl, byte ptr [ecx]
            .if dl==0
               jmp seguir2
            .endif
            imul dl
            mov byte ptr [ecx], al
            inc ecx
            jmp bucle3

Recuperamos la dirección de numero, la volvemos a guardar y multiplicamos los cuatro números por 60h (código de "W" = 57, más 9)

seguir2:    pop ecx
            push ecx
bucle4:     mov al, byte ptr [ebx]
            .if al==0
               jmp seguir3
            .endif
            add al, 9
            xor esi, esi
bucle4a:    mov dl, byte ptr [ecx+esi]
            xor dl, al
            mov byte ptr [ecx+esi], dl
            inc esi
            .if esi < 4
               jmp bucle4a
            .endif
            inc ebx
            jmp bucle4

Ahora hemos "xoreado" los cuatro números con cada uno de los códigos de las letras de nuestro nombre.

seguir3:    pop ecx
            mov edi, dword ptr [ecx]
            cmp edi, 0
            jge salto1
            neg edi
            cmp edi, 0
salto1:     jnz menor
            mov edi, 1

Si el número es negativo lo vuelve positivo, y si es cero lo iguala a uno. Ahora tenemos nuestro serial en EDI.

menor:      .if edi < 270Fh
               mov eax, 10
               xor edx, edx;
               imul edi
               mov edi, eax
               mov dword ptr [ecx], edi
               jmp menor
            .endif

Si el número es menor que 9999 (270Fh), lo multiplicamos por 10. (tendría que ser menor o igual)

mayor:      .if edi > 0F423Fh
               push ecx
               mov ecx, 10
               xor edx, edx
               mov eax, edi
               idiv ecx
               pop ecx
               mov edi, eax
               jmp mayor
            .endif

Si el número es mayor de 999999 (F423Fh), lo dividimos por 10.

            mov esi, offset serial
            mov byte ptr [esi], 49h
            inc esi
            mov byte ptr [esi], 57h
            inc esi
            mov byte ptr [esi], 2Dh

Ahora en el campo serial, hemos puesto los códigos ASCII de "IW-". Vamos a pasar el número hexadecimal obtenido, a decimal. Esto se hace dividiendo el número hexadecimal por 10 y poniendo el resto de la división en el lugar de las unidades, luego se divide el cociente por 10 y el resto se pone en el lugar de las decenas y se continua así hasta que el cociente es menor de 10 y se coloca como cifra más significativa del serial.
Si el número obtenido es igual a 9999, le sumaremos 4 a ESI para que apunte a las unidades; si es menor de 100000 (186A0h) le sumaremos 5, y si es igual o mayor le sumaremos 6.

            .if edi == 270Fh
               add esi, 4
               jmp seguir4
            .endif
           .if edi < 186A0h
               add esi, 5
            .else
               add esi, 6
            .endif

seguir4:    mov eax, edi
            mov ecx, 10
otro:       cmp eax, ecx
            jb fin
            xor edx, edx
            idiv ecx
            add dl, 30h
            mov byte ptr [esi], dl
            dec esi
            jmp otro
fin:        add al, 30h
            mov byte ptr [esi], al

Ya tenemos el serial del tipo IW-nnnnnn, yo no he conseguido ningún número de cuatro o cinco cifras, pero por lo visto, la posibilidad existe. Ahora, recuperaremos los registros y regresamos.

      popad
      ret
Operacion endp

end start

Misión cumplida :-) He aquí el resultado.  

 Os recuerdo una vez más que debéis pagar los programas que utilicéis regularmente y que estos tutos deben servir solamente para aprender. Luego no le digáis al juez: "Yo no quería, pero CaoS ReptantE me incitó a delinquir..." ;-)

Por último quiero saludar a mis buenos amigos Act MagO y Pr@fEsOr X. También a Karpoff, Silver Storm, KuaTo_ThoR, vLuGo, ByTESCRK y last but not least: DeK_OiN.

Si queréis alguna aclaración sobre mis tutos, mi dirección de e-mail es: caos_reptante@hotmail.com

 

Karpoff Spanish Tutor: Pagina dedicada a la divulgacion de informacion en Castellano, sobre Ingenieria Inversa y Programacion. Email "Colabora con tus Proyectos"

www.000webhost.com