lunes, 11 de enero de 2021

DOS cracking series VII ~ (otro) cracking de un juego DOS con DOSBox debugger (analisis dinamico)

Vamos a hacer un descanso con un articulo introductorio.

Es un crack que hice hace algun tiempo para Breach 2, un juego de estrategia por turnos desarrollado por Omnitrend Software en 1990.

La proteccion es sencilla. Es suficiente con modificar un salto condicional a chico_bueno por un salto incondicional.

Ejecutamos el juego, y cuando nos pregunta por la clave entramos al debugger de DOSBox (ALT+PAUSA).

Para intentar caer lo mas cerca posible del punto donde el juego comprueba la clave introducida, ponemos un breakpoint a la INT 9 (INT de teclado de la BIOS). DOSBox debugger -> BPINT 9

Reanudamos la ejecucion (F5), y en el juego pulsamos Intro. Entonces saltara el debugger. Nos situamos en la primera instruccion de la INT 9 (debugger -> INTHAND 9) y vamos ejecutando instruccion por instruccion (F10).

Por alguna razon que no he analizado, al llegar a la instruccion IRET de la INT 9, podemos retornar a dos puntos distintos del codigo, segun la clave sea correcta o no. Bueno, vamos a probar con "la otra" INT de teclado: INT_16 (interrupcion de teclado del DOS). Salimos del juego y volvemos a empezar. debugger -> BPINT 16 y las cosas parecen mas favorables, ya que cuando retornamos con IRET, estamos en el mismo punto del codigo tanto si introducimos una clave correcta como incorrecta.

Bien, seguimos ejecutando paso a paso (F10) y bueno, si llegamos a algun CALL y, tras pulsar F10, el juego nos salta con el mensaje de "clave invalida", entonces significa que el chequeo de claves esta dentro de dicho CALL. Entonces saldremos de DOSBox y volveremos a empezar, y al llegar a ese CALL, en vez de pulsar F10 pulsaremos F11 para entrar en el. Esta es la parte aburrida, pero no tardamos en llegar al meollo de la cuestion: un bucle repeat-until donde se comprueba la clave introducida con la correcta, caracter a caracter. La condicion que rompe el bucle es:
339:FC50 3BCE   cmp cx,si       ;¿hemos comprobado todos los caracteres de la clave?
339:FC52 77D4 ja FC28 ($-2c) ;NO: seguir con el siguiente caracter
339:FC54 ... ;buen sitio para poner un breakpoint
Cuando estamos en "cmp cx,si", CX=num_chars_por_comprobar. Justo despues viene el salto condicional "ja FC28", que rompera el bucle cuando no queden caracteres por comprobar.

Si queremos avanzar hasta cuando se haya comprobado toda la clave, un buen sitio para poner un breakpoint es la primera instruccion que se ejecuta justo despues de salir del bucle. En esta ejecucion seria -> BP 339:FC54. Reanudamos la ejecucion con F5 y unas pocas instrucciones despues llegamos al punto en que el codigo comprueba si la clave entera ha sido correcta o no. El flujo de ejecucion se divide en dos caminos.
CS:FC60 263987A21C  cmp es:[bx+1CA2],ax ;¿chico bueno o chico malo?
CS:FC65 7443 je FCAA ($+43) ;chico_bueno (crack: JMP ~ EB 43)
CS:FC67 ... ;chico_malo

Si la clave es correcta -> al juego en si -> seguir ejecucion en CS:FCAA
Si no lo es -> poner mensaje de clave incorrecta y volver a pedir la clave, aqui no juega nadie hasta que la clave sea buena, y si fallas X veces, salir al DOS -> seguir ejecucion en CS:FC67
El salto condicional "je FCAA" se cumple para chico_bueno (clave introducida = clave correcta). Por lo tanto, para que chico_malo pueda jugar tambien, la solucion simple es modificar el salto condicional por un salto incondicional. Es decir, modificar "JE +43h" por "JMP +43h". Es decir, modificar los bytes "74 43" por "EB 43". En esta ejecucion seria -> SM 339:FC65 EB 43

Si seguimos la ejecucion paso a paso con unos cuantos F10, veremos que entramos al juego en si.

No nos hemos topado con ninguna comprobacion adicional, asi que parece que solo tenemos que modificar un byte para que el juego acepte cualquier clave como valida. :)

Abrimos BREACH2.EXE con un editor hexa y buscamos la cadena "263987A21C7443". Y... no la encontramos.

Resulta que el codigo en tiempo de ejecucion (en memoria) es distinto al codigo en el archivo ejecutable, pero no pasa nada, podemos seguir relajados, no hara falta hacer ningun cargador/TSR que modifique el codigo en tiempo de ejecucion. + Info 03. Haciendo un cargador (loader) para crackear un juego DOS en tiempo de ejecucion (I) y 04. Haciendo un cargador (loader) para crackear un juego DOS en tiempo de ejecucion (II)

El ejecutable esta empaquetado (comprimido) y cuando lo ejecutamos se desempaqueta (descomprime) en memoria. Asi que vamos a descomprimir el archivo. La herramienta UNP.EXE [1] es una buena primera opcion. No puede desempaquetar todo, pero es bastante todoterreno. Desde DOSBox:
UNP BREACH2.EXE
Y ya tenemos el ejecutable descomprimido. Volvemos a abrirlo con un editor hexa y buscamos la cadena "263987A21C7443", que ya si encontramos. La sustituimos por "263987A21CEB43" y ya esta. Ya hemos crackeado el juego. :)

PD: cuidado con el comando SM en dosbox-x. Si en debugger escribimos:
SM segment:offset CF
dosbox-vanilla escribira el byte CF (iret), pero dosbox-x escribira 0 ó 1, en funcion del valor del flag de carry (CF). Hay una colision entre el nombre de algunos flags (AC, AF, CF y DF) y los valores en hexa.

Para solucionarlo yo lo que hice fue eliminar unas pocas lineas del codigo fuente de dosbox-x, y dejar un pequeño parche en Vogons [2]

En versiones posteriores de dosbox-x, se añadio la posibilidad de escribir los bytes entre "" para forzar que la cadena se tome como valores hexa.

Feliz cracking.

[1] http://unp.bencastricum.nl/ UNP Executable file expander: uncompresses files compressed with DIET, EXEPACK, LZEXE, PKLITE and many other file compression utilities. UNP also allows you to convert files from COM to EXE and vice versa, optimize EXE headers, remove overlay data from EXE files and more.
[2] https://www.vogons.org/viewtopic.php?p=806403#p806403 evitar colisiones entre nombre de flags y valores hexa en comando SM en dosbox-x (patch)
---
01. Cracking de un juego DOS con IDA (analisis estatico)
02. Cracking de un juego DOS con DOSBox debugger (analisis dinamico)
03. Haciendo un cargador (loader) para crackear un juego DOS en tiempo de ejecucion (I)
04. Haciendo un cargador (loader) para crackear un juego DOS en tiempo de ejecucion (II)
05. Dandole al debugger para arreglar un bug en un juego DOS
06. Programando un TSR para interceptar, en una aventura grafica/conversacional, los comandos que introduce el jugador (y cambiarlos al vuelo)
07. esta entrada que estas leyendo

Related Posts by Categories



0 comentarios :

Publicar un comentario

Nota: solo los miembros de este blog pueden publicar comentarios.