Karpoff Spanish Tutor

Programa:

Kyodai v10.21


 

PROTECCION: Empacado & Serial
Objetivo: Desempacar con SICE, sacar serial válido y hacer KeYgEn
Descripcion: Divertido juego oriental
Dificultad: Intermedia/Avanzada
DOWNLOAD: http://kyodai.com
Herramientas: SoftIce, Win32Dasm, ProcDump & Tasm 5.0
CRACKER: Mr Burns   FECHA: 02/10/2000

 

 INTRODUCCION

Hola de nuevo a todos. He decidido hacer este tutorial del Kyodai sabiendo que ya hay suficientes por aburrimiento una tarde de Domingo a las 17:40 de la tarde. Y... porque este es mi primer tutorial sobre cómo hacer un keygen (en ASM). Asi que creo que deberíamos empezar ya.

 

 AL ATAKE

Para empezar instalamos el programa con tranquilidad sabiendo que es shareware y que nos pedira una puta clave :-)

Una vez instalado abrimos el programa y lo estudiamos un poco (joder!! que buena pinta tiene el condenado es chulo!!!) y miramos en el menu: Help/Register y observamos que nos pide el Nombre y número de serie. Bueno pues vamos a introducir los datos:

Nombre: Mr_Burns

Serial: 1234567890

Le damos al "OK" y.... nos aparece una ventanita que pone "Lo siento nº incorrecto. Por favor compruebe que lo escribio tal y como le fue entregado". "Caguen..." pues a mi me ha molado mazo y me lo quiero quedar asi que lo voy a CRaCKeaR!!


Empezare metiendole mano con el Win32Dasm y... joe!! que se me ha colgado!! Bueno no pasa nada lo voy a cargar en el Loader sel SofIce (SICE) y... pues tp tira!!! Pufff!! Esto me hace sospechar que este programa esta empakado!!!


Bueno para ello usare mi querido ProcDump. Entro en el PE Editor y abro el kyo1021.exe (no el kyodai.exe!!), entro en Sections y observo dos cosas:

1º En .CODE (caracteristics) aparece C0000040. Eso significa que el programa no es ejecutable!!! Y que yo sepa deberia tener E0000020 (ejecutable). Bueno, pues eso, lo cambiamos.

2º Aparece una cadena por ahi que pone Aspack. Eso a mi me suena a Compresor!!


Despues de esto lo que voy a hacer es descomprimir el programa con el Aspack, la ultima version porque este programa es nuevo, y... no tira!!! Eso quiere decir que no tenemos esa version. Lo que significa que habra que hacerlo a mano (jejeje esto se pone interesante asi que me voy a por un cafetito :-))

----------Desempacar el fichero con el SoftIce----------

Corremos el Loader del Sice y vemos que ahora SI! que tiran esas ruletitas :-) Entramos y vemos que la direccion es un poco rara (5A1001) y observamos:

PUSHAD

CALL 00XXXXXX

JMP 00XXXXXX

[...]

POPAD

Esta es una tipica estructura de un fichero empacado y/ó encriptado. Lo que nosotros estamos buscando es POPAD ya que despues de eso el programa ya esta desempacado. Asi que adelante, a tipear F10 como cerdos hasta encontrarlo (lo que yo os aconsejo es que cuando veais un salto que os lleve hacia arriba introduzcais "G address siguiente al salto" para que no tengais que tragaros todos los bucles que hay). Despues de muchos cuelgues del SICE y de muchos F10 encontramos un POPAD en la dirección 59E4F1. Lo que ahora haremos es S 59E4F1 L FFFFFF 61 (61 = POPAD en hexadecimal) y apretamos F5. Si sales del Sice y entras en el programa ALELUYA!!! la instruccion encontrada es la correcta, en caso contrario, deberas buscar otro POPAD y realizar la misma operacion :-(


Bueno coninuamos y vemos que despues de varios tipeos de F10 aparece un RET en 59E501 y que ese RET nos lleva a otra dirrecion la cual parece mas normal (499CD4 <-- Anota esta dirección!!!) . Bueno, vamos bien, ahora debemos volver a ese RET y tipear: A 59E501 y JMP EIP, [Esc] y despues F5. Joe!! ha salido del SICE y no ocurre nada!! Lo que en realidad ha pasado es que el programa ha sido cargado y desempacado y corrido en memoria gracias a ese JMP EIP que genera un bucle infinito que nos ayuda a desempacar el fichero :-)


Lo que ahora hacemos es entrar de nuevo en el ProcDump y en la lista inicial vemos que aparece el path donde teneis instalado el kyodai, bueno eso es que el programa esta cargado en memoria asi que vamos a guardarlo, para ello lo seleccionamos con el boton derecho y seleccionamos "Dump (Full)" poniendo como name "kyo_Mr.exe" (por ejemplo) una vez guardado lo descargamos de la memoria con la opcion "Kill". Despues cargamos de nuevo con "PE Editor" el programa "Kyo_Mr.exe" (el cual esta ya desempacado) y observamos "Entry Point" e "Image Size". Lo que ahora debemos hacer es tomar la dirección a la que nos llevaba el ultimo RET: 499CD4 (recordad que os dije que la apuntarais) y el valor de "Image Size" y restarlo: 499CD4 - 400000 = 00099CD4. Esta ultima cifra debemos sutituirla por el "Entry Point" para que el programa desempacado pueda funcionar ya que si corrieramos el fichero sin hacer esto cada vez que lo corrieramos se quedaria cargado en memoria.

----------Detectar el numero de serie----------

Una vez desensamblado el fichero (siempre nos referiremos al desempacado Kyo_Mr.exe) corremos el fichero e introducimos los datos de nuevo:

Nombre: Mr_Burns

Serial: 1234567890

Le damos a "REGISTRAR" y nos aparecera la ventanuca esa de que no estamos registrados. La recordamos. Corremos el Win32Dasm y desensamblamos el Kyo_Mr.exe que es el que esta desempacado. Buscamos en "Reference String" la cadena que tenemos (pero hemos de buscar la cadena en ingles, es decir, "Sorry, wrong password...". Le damos dos veces y aparecemos en 4648BC. Subimos un poco y vemos que hay un salto condicional en 464886, asi que vamonos para alla. Alli observamos que dos lineas mas arriba hay un call, la cual puede que sea la genere la password. Y podemos ver tambien que si no saltase alli nos apareceria otra cadena "Thanks again ! Your are now registered.". Nosotros no vamos a crear el parche sino el keygen por ello entraremos en la call para ver lo que hay... vemos una lista de "nosecuantos" nombres ¿? Que sera eso¿?! Bueno no nos interesa. Lo importante es lo del principio:

* Referenced by a CALL at Addresses:
|:0046487F , :0048664A , :0048C326 , :0048CBDE , :0048D575
|:0048DE10 , :0048E059 , :0048E626 , :0048F501 , :00490E32
|:00495149
|
:0047966C 55 push ebp
:0047966D 8BEC mov ebp, esp
:0047966F 6A00 push 00000000
:00479671 53 push ebx
:00479672 56 push esi
:00479673 8BF0 mov esi, eax
:00479675 33C0 xor eax, eax
:00479677 55 push ebp
:00479678 680F9A4700 push 00479A0F
<-- Guarda la lista de nombres que viene mas adelante en el codigo (ni idea de que es eso)
:0047967D 64FF30 push dword ptr fs:[eax]
:00479680 648920 mov dword ptr fs:[eax], esp
:00479683 33DB xor ebx, ebx
:00479685 8B864C2B0500 mov eax, dword ptr [esi+00052B4C]
<-- Guarda en EAX mi nombre: Mr_Burns
:0047968B E8D4A5F8FF call 00403C64
<-- Calcula la longitud del nombre y la compara con 8 (creo)
:00479690 85C0 test eax, eax
:00479692 0F8E0C030000 jle 004799A4
<-- Si no posee 8 caracteres salta a error
:00479698 8D4DFC lea ecx, dword ptr [ebp-04]
:0047969B 8B964C2B0500 mov edx, dword ptr [esi+00052B4C]
<-- Guarda en EDX mi nombre: Mr_Burns
:004796A1 8BC6 mov eax, esi
:004796A3 E860B4FFFF call 00474B08
<-- Genera el serial correcto!!!!!!
:004796A8 8B45FC mov eax, dword ptr [ebp-04]
<-- Guarda en EAX el serial correcto!!!!!
:004796AB 8B96502B0500 mov edx, dword ptr [esi+00052B50]
<-- Guarda en EDX el serial que yo introduje: 12345
:004796B1 E8BEA6F8FF call 00403D74
<-- Compara EAX con EDX
:004796B6 0F85E8020000 jne 004799A4
<- Si no son iguales salta a error
:004796BC 8B864C2B0500 mov eax, dword ptr [esi+00052B4C]

Como podemos comprobar, encontrar el serial correcto es cosa de niños xDDD. Por si os habeis perdido, en 4796A8 esta el serial ccorrecto, lo unico que debeis hacer es d eax y os aparecera el serial. Como esto me resulto demasiado facil quise hacer el KeYgEn ya que descbri la rutina que genera el serial, asi que apor ella:

* Referenced by a CALL at Address:
|:004796A3
|
:00474B08 55 push ebp
:00474B09 8BEC mov ebp, esp
:00474B0B 83C4F4 add esp, FFFFFFF4
:00474B0E 53 push ebx
:00474B0F 56 push esi
:00474B10 57 push edi
:00474B11 33DB xor ebx, ebx
:00474B13 895DF4 mov dword ptr [ebp-0C], ebx
:00474B16 8BF9 mov edi, ecx
:00474B18 8955F8 mov dword ptr [ebp-08], edx
:00474B1B 8945FC mov dword ptr [ebp-04], eax
:00474B1E 8B45F8 mov eax, dword ptr [ebp-08]
:00474B21 E8F2F2F8FF call 00403E18
:00474B26 33C0 xor eax, eax
:00474B28 55 push ebp
:00474B29 68E34B4700 push 00474BE3
:00474B2E 64FF30 push dword ptr fs:[eax]
:00474B31 648920 mov dword ptr fs:[eax], esp
:00474B34 8B45F8 mov eax, dword ptr [ebp-08]
:00474B37 E828F1F8FF call 00403C64
<-- Todo lo de arriba no es importante para el KeYgEn
:00474B3C 8B55F8 mov edx, dword ptr [ebp-08]
<-- EDX = Nombre (Mr_Burns)
:00474B3F 0FB64402FF movzx eax, byte ptr [edx+eax-01]
<-- EAX = Ultima letra de nuestro nombre (s)
:00474B44 8B55F8 mov edx, dword ptr [ebp-08]
<-- EDX = Nombre
:00474B47 0FB612 movzx edx, byte ptr [edx]
<-- EDX = Primera letra del nombre (M)
:00474B4A 03C2 add eax, edx
<-- EAX + EDX = EAX


:00474B4C B90A000000 mov ecx, 0000000A
<-- ECX = 10
:00474B51 99 cdq
<-- NPI (Ni Puta Idea!, pero nos da igual nos nos hace falta)
:00474B52 F7F9 idiv ecx
<-- Divide con signo EAX / ECX y el resto queda en EDX
:00474B54 83C230 add edx, 00000030
<-- Añade a EDX (resto) 30h


:00474B57 8BC7 mov eax, edi
:00474B59 E82EF0F8FF call 00403B8C
:00474B5E 8B45F8 mov eax, dword ptr [ebp-08]
<-- EAX = Nombre
:00474B61 E8FEF0F8FF call 00403C64
<-- Calcula la longitud del nombre
:00474B66 8BF0 mov esi, eax
<-- ESI = La longitud del nombre (8)
:00474B68 83EE02 sub esi, 00000002
<-- Le resta 2 (esto es porque los dos primeros bytes contienen datos de la meoria reservada)
:00474B6B 7C39 jl 00474BA6
<-- Si es menor salta a error
:00474B6D 46 inc esi
<-- Sino, incrementa ESI
:00474B6E BB02000000 mov ebx, 00000002
<-- EBX = 2

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00474BA4(C)
|
:00474B73 8B45F8 mov eax, dword ptr [ebp-08]
<-- EAX = Nombre
:00474B76 0FB64418FE movzx eax, byte ptr [eax+ebx-02]
<-- EAX = Primera letra del nombre (M)
:00474B7B 8B55F8 mov edx, dword ptr [ebp-08]
<-- EDX = Nombre
:00474B7E 0FB6541AFF movzx edx, byte ptr [edx+ebx-01]
<-- EDX = Siguiente letra del nombre (r)


Hagamos aqui una pausa para indicaros la "inteligencia" del programador: observad que en
474B6E EBX = 2 y que en 474B76 a EBX le resta 2. Y despues, en 474B7B le resta 1. Esto es una autentica estupidez ya que se podia haber ahorrado tantas molestias poniendo:

474B6E EBX = 0

474B76 movzx eax, byte ptr [eax+ebx]

474B7B movzx edx, byte ptr [edx+ebx+01]

Si esto es un intento de despistar a gente como nosotros, usease, crackers.... SE HA LUCIDO!!!!!!!!! No se como pueden denominarse a si mismos programadores!!!!!!!!!!!


:00474B83 03C2 add eax, edx
<-- EAX = EAX + EDX


:00474B85 B90A000000 mov ecx, 0000000A
<-- ECX = 10
:00474B8A 99 cdq
<-- NPI
:00474B8B F7F9 idiv ecx
<-- Divide con signo EAX / ECX y el resto queda en EDX
:00474B8D 83C230 add edx, 00000030
<-- EDX + 30h


:00474B90 8D45F4 lea eax, dword ptr [ebp-0C]
:00474B93 E8F4EFF8FF call 00403B8C
:00474B98 8B55F4 mov edx, dword ptr [ebp-0C]
:00474B9B 8BC7 mov eax, edi
:00474B9D E8CAF0F8FF call 00403C6C
:00474BA2 43 inc ebx
<-- Incrementa EBX en 1
:00474BA3 4E dec esi
<-- Y decrementa ESI en 1
:00474BA4 75CD jne 00474B73
<-- Si son diferentes salta (BUCLE!)

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00474B6B(C)
|
:00474BA6 8B45F8 mov eax, dword ptr [ebp-08]
<-- EAX = Nombre
:00474BA9 E8B6F0F8FF call 00403C64
<-- Calcula la longitud del nombre
:00474BAE 83F808 cmp eax, 00000008
<-- La compara con 8
:00474BB1 7D15 jge 00474BC8
<-- Si es mayor o igual bien
:00474BB3 8BCF mov ecx, edi
<-- Sino.... ERROR!!!
:00474BB5 8B45FC mov eax, dword ptr [ebp-04]
:00474BB8 8B80DC050000 mov eax, dword ptr [eax+000005DC]


Despues de haber estudiado la rutina que genera el serial no damos cuenta de que extremadamente simple!!!! :-D Veamos: El primer byte contiene la suma de la primera y ultima letras del nombre; y el resto es la suma de un letra con la siguiente. como os habia dicho extremadamente simple!!!


Me gustaria decir que el codigo que hay entre
474B4C-474B54 y 474B85-474B8D no tiene nada que ver con la generacion del serial. Lo que quiero decir es que esta parte del codigo, las cuales son iguales, lo unico que hacen es convertir el resultado de la suma en un numero decimal. Lo pillais¿? Bueno os lo explicare mas adelante :-)


Ahora que sabemos como funciona la rutina de generacion del serial, empezemos el KeYgEn. Yo como el lenguaje que mas controlo es Ensamblador, lo voy a hacer en este lenguaje, pero no descarteis hacerlo en cualquier otro, tan solo hace falta un poco de imaginacion e ingenio :-)


Aqui os presento el codigo, el cual ire comantando para aquellos que no esten muy metidos en la materia:

;Kyodai 10.21 KeYgEn
;CoDeD bY Mr Burns
;DaTe: 22-09-2000

.MODEL SMALL ;Indica que el ejecutable va a ser un COM
.CODE ;Segemnto del codigo
.386 ;Funcones de 386
ORG 100h ;Desplazamiento 100h=256d respecto al origen del segmento

Start: jmp LetsRock ;Saltamos al codigo, dejamos los datos a un lado

Intro db 10,13,'Kyodai 10.xx KeYgEn CoPYaLL 2000 CoDeD bY Mr Burns',10,13
db 10,13,'eNTeR YouR NaMe: $'
NameOut db 20,0
Name2 db 20 DUP(0)
SerialOut db 10,13,'THe PaSSWoRD iS: '
Pass db 20 DUP(0)
EndPass db 10,13,'$'
TempPass db 20 DUP(0)
TempPassEnd db 0
NoName db '***eRRoR*** THe NaMe MusT Be MoRe THaN 8 LeTTeRS :(',10,13, '$'
Pass2 db 20 DUP(0)
SizeName db 0

LetsRock:
mov ah,09h ;Escribe texto por pantalla
lea dx,Intro
int 21h

mov ah,0Ah ;Recoge el Nombre
lea dx,NameOut
int 21h

LongName:
mov al,byte ptr [NameOut+1] ;AL = Long del Nombre
cmp al,8 ;Lo compara con 8
jge CalculateSerial ;Si es MAyor o Igual salta

BadName:
mov ah,09h ;Sino hay un error
lea dx,NoName
int 21h

mov ah,4Ch ;Y sale del programa
int 21h

CalculateSerial:
xor eax,eax ;Limpia los registros
xor ebx,ebx
xor ecx,ecx
xor edx,edx

mov al,byte ptr [NameOut+1] ;AL = Longitud del nombre
mov byte ptr [SizeName],al ;SizeName = AL

lea esi,Name2 ;ESI apunta al nombre
lea edi,Pass2 ;EDI apunta al serial

movzx ebx,byte ptr [SizeName] ;EBX = SizeName = AL X-D
mov al,byte ptr [esi+ebx-1] ;AL = Ultima letra del nombre
mov cl,byte ptr [esi] ;CL = Primera letra del nombre
add eax,ecx ;Se suman y se guarda en EAX
mov ecx,0Ah ;ECX = 10
xor edx,edx ;EDX = 0
idiv ecx ;Divide EAX / ECX y el resto queda en EDX
add dl,30h ;A¤ade al resto 48
mov byte ptr [edi],dl ;Lo mete en la pass
inc edi ;Incrementa el puntero del pass en 1

xor ebx,ebx ;EBX = 0
xor eax,eax ;EAX = 0
xor edx,edx ;EDX = 0

SecondPart:
mov al,byte ptr [esi+ebx] ;AL = Primera letra del nombre
mov dl,byte ptr [esi+ebx+1] ;DL = Segunda letra del nombre
cmp dl,0 ;¨El nombre se acaba?
je TheEnd ;Si = Escribirlo por pantalla
add eax,edx ;NO = Se suman y se guarda en EAX
mov ecx,0Ah ;ECX = 10
xor edx,edx ;EDX = 0
idiv ecx ;Divide EAX / ECX y el resto queda en EDX
add dl,30h ;A¤ade al resto 48
mov byte ptr [edi+ebx],dl ;Mueve el resto al serial
inc ebx ;Incrementa EBX
jmp SecondPart ;Salta al comienzo (Bucle)

TheEnd:
mov byte ptr [edi+ebx-1],0 ;Poner un 0 (binario) al final del serial

lea esi,Pass2 ;ESI apunta al pass
lea edi,Pass ;EDI apunta donde va a ir el pass

Serial:
movsb ;Mover de ESI a EDI byte a byte
cmp byte ptr [esi],00h ;Comparar el pass con 0
jne Serial ;si no lo es continua (Bucle)


Print:
mov ah,09h ;Saca el Serial por pantalla
lea dx,SerialOut
int 21h

mov ah,4Ch ;Sale del programa
int 21h

; end Start ;Terminamos el KeYgEn :)


Pues eso es todo!!!!! Con esto hemos hecho un sencillo keygen para el kyoday!!!! xDDDDD

DESPEDIDAS Y DEMAS :-(


Bueno, esto hay sido todo. espero que os halla servido de ayuda este tutorial para saber un poquito mas de cracking ;-) Se que este KeYgEn puede ser mejorado, si crees que tu puedes hacerlo mejor... ADELANTE!!!! te animo a que lo hagas mejor y me lo comentes (y no me lo restriegues por la cara :-] )

Me he dado cuanta de el gran tamaño de este tutorial pero creo que en necesario ya que he intentado explicar un poco las causas y el porqué de todos los pasos que he realizado ya que es asi como me gustaria encontrame un tutorial a mi :-)


Como siempre digo en mis tutoriales, si deseais hablar conmigo buscad en:

NiCK

SeRViDoR

CaNaL

Mr_Burns

irc.irc-hispano.org

CRaCKeRS

[MoRDReD]

irc.chat.org

TnTCRaCKeRS & WkT


O por el contrario si tan solo deseas mandarme un e-mail:
mr_burns@go.to

Pues eso ha sido todo.... pero antes quiero saludar a toda la gente que se dedica a este campo del "Andergraund" (Underground), a toda la gente del IRC y del canal #Palencia (que es donde yo vivo!!!!) y al canal #CRaCKeRS, especialmente a: [The_Pope], Shotgan, BiRKiN, SeRoCuLTo, JoTaKe, Ni2, [Aura, Sirvenom, [Xasx], Xasx[out], [XasxZzZzZ] etc etc etc (xDDDDDDDDD)..... y que no quede nuestro nuevo BoT MOVSB (creado por Shotty, que ha realizado un gran trabajo ;-))

 

 

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