LibCrypt 2 al desnudo 2/2

Introducción

Bueno, espero que en el tiempo que ha pasado desde el anterior artículo hayáis estado practicando y estudiando un poco :).

Como ya os dije en este artículo vamos a tratar el LibCrypt 2 (en adelante LC2), la protección más utilizada en los juegos de PSX, pero paradójicamente también la más sencilla de romper. Para que os hagáis una idea, desde el Formula1 '99 y el Spyro 2 que utilizaron LC3, se puede decir que prácticamente todos los demás juegos protegidos aparecidos desde entonces han hecho uso del LC2, con la excepción del ultimísimo F1 2000, que por lo visto implementa una nueva vuelta de tuerca que ya ha sido bautizada como LC4 .

A lo largo del artículo voy a explicaros el método a seguir para desarrollar un crack, desde que cogemos el juego del videoclub hasta que le mandamos el ppf a ElOtroLado para que lo publique X-D. Para ello utilizaremos un "hipotético" ejemplo real ;).


Entrando en faena

El funcionamiento de las rutinas de protección es el que os comenté en el otro artículo. Por lo tanto, nuestro objetivo va a ser modificar la rutina que calcula la Magic Word (MW) para que siempre acabe introduciendo el valor correcto en el BPC.

Para ello necesitaremos abordar el problema en dos fases: en la primera deberemos hacer las modificaciones temporales necesarias para averiguar la MW, utilizando para ello el juego original; y en la segunda, una vez que conozcamos la MW, tendremos que cumplir nuestro objetivo principal, esto es, modificar la rutina de modo que siempre meta el mismo valor en el BPC, el valor correcto :).

Lo primero que haremos es copiar el ejecutable principal del juego a nuestro disco duro. Este fichero lo reconoceremos porque siempre se llama sles_x.y , donde x e y son dos números que representan la antigüedad del juego en cuestión. Por si acaso sabed que el ejecutable siempre es el que se llama en el fichero system.cnf. Una vez lo tenemos copiado hay que desensamblarlo. Para ello, podéis utilizar cualquiera de los programas desensambladores que hay por ahí, pero os aviso que yo no he encontrado todavía ninguno que vaya perfecto. Unos no reconocen las instrucciones del COP0, otros no muestran todas las direcciones de las instrucciones, y otros, como es el caso del Munch (el que utilizo yo normalmente), confunden los registros del COP0 con los registros normales del microprocesador. De todas formas con unas pocas pruebas y un poco de práctica os acabaréis acostumbrando... :)


Fase 1: búsqueda de la MW

Esta es la fase que ocupará el grueso de nuestro trabajo. Como os comenté, en principio no podemos utilizar el Action Replay, ya que el juego lo detecta, por lo que tampoco podemos usar un debugger. Para ello lo primero que debemos hacer es desactivar la rutina que realiza la detección. Una vez la tengamos desactivada, ya podemos hacer uso del debugger para comenzar la caza de la MW.

Sin embargo nos encontramos con otro problema: no podemos realizar una traza de las rutinas de protección. El motivo de esto es que como ya os dije éstas rutinas utilizan los registros del COP0 (BPC, BPCM, BDA, BDAM...), cuya función habitual es hacer Breakpoints, es decir, que los debuggers modifican estos registros para poder hacer trazas y situar puntos de ruptura, distorsionando por tanto todos los datos y haciendo fallar a las rutinas irremediablemente. Por lo tanto, la única solución es estudiar el código desensablado para que, una vez localizada por donde anda la MW calculada, sustituir alguna instrucción por otra que cuelgue la PSX, y así poder leer el ansiado número de 16 bit de algún registro. Por supuesto no es posible leerlo directamente del BPC, por lo que habrá que buscar el registro general adecuado.


Anulando la rutina anti-par

Supongo que casi todos la conoceréis por el artículo de BAD, pero de todas formas vamos a volver a repasarla.

Así es como se presenta en el ejemplo que vamos a seguir, la cual, aunque con ligeras diferencias, siempre aparece igual en todos los juegos con LC2.

[list=1]
[*]80090818 LUI v0, 0x1F00
[*]8009081C MTC0 v0, BPC
[*]80090820 LUI v0, 0x1FFC
[*]80090824 MTC0 v0, BPCM
[*]80090828 MTC0 v0, BDA
[*]8009082C LUI v0, 0x8009
[*]80090830 ADDIU v0, v0, 0x0848
[*]80090834 MTC0 v0, BDAM
[*]80090838 LUI v0, 0xE180
[*]8009083C MTC0 v0, DCIC
[*]80090840 JR ra
[*]80090844 NOP
[/list=1]

Como ya sabéis, básicamente los registros del COP0 son utilizados para indicar puntos de ruptura al acceder a las mascaras de direcciones que indican. El registro DCIC es el encargado del control, y como en este caso el valor que se le carga es 0xE1800000 (1110 0001 1000 0000 0000 0000 0000 0000) el único breakpoint que queda habilitado es el de ejecución. Por lo tanto, los únicos valores que afectan a la detección del AR son los cargados en el BPC y BPCM, siendo los demás una mera inicialización de los registros. El motivo de que se detecte la presencia del AR es que este guarda su ROM en la memoria de la PSX, concretamente en los primeros 256K a partir de la dirección 0x1F000000, es decir, precisamente en las direcciones que causarán un breakpoint al ser ejecutadas.

Para solucionar este problema podemos hacer varias cosas, pero siempre teniendo en cuenta no alterar el valor de los registros del COP0 (a excepción del DCIC), ya que su valor será utilizado a continuación en la rutina de protección. Una solución es deshabilitar todos los breakpoints, para lo cual el valor que tendríamos que cargar en el DCIC sería 0xE0800000 (modificando la instrucción 9), y la otra, más sencilla, sería evitar que se cargue dicho valor en el registro de control, simplemente sustituyendo la instrucción 10 por un NOP (0x00000000).

Con este sencillo parche ya podremos utilizar el debugger en busca de la MW, pero recordad que no es necesario para el crack final, así que mejor no lo incluiremos luego por si las moscas. Sin embargo, si durante el juego queremos utilizar códigos para trucos la PSX nos detectará el AR y se bloqueará. Esto último de todas formas se podrá evitar fácilmente introduciendo siempre los códigos equivalentes al parche.


Magic Word

A continuación de esta rutina, que como hemos visto además de detectar el AR se encarga de inicializar los registros a utilizar, viene todo el grueso del LC, donde se realizan los distintos checkeos (CD, ModChip...) y se calcula la MW. Todo este proceso no lo voy a describir, porque es bastante largo y complejo, así que vamos a irnos a lo que más nos interesa ;).

Localizad un fragmento de código parecido a este:

[list=1]
[*]80090AE0 ADDIU a0, a0, 0x49C4
[*]80090AE4 SW zero, 0x0000(a0)
[*]80090AE8 MFC0 a2, BPC
[*]80090AEC LB a0, 0x0004(a1)
[*]80090AF0 ANDI at, a2, 0xFFFF
[*]80090AF4 BNE at, zero, 0x80090B18
[*]80090AF8 ANDI a3, a3, 0x0002
[*]80090AFC BEQ a3, zero, 0x80090B18
[*]80090B00 ADDI a0, a0, 0xFFAD
[*]80090B04 BNE a0, zero, 0x80090B18
[*]80090B08 NOP
[*]80090B0C LB a0, 0x0007(a1)
[*]80090B10 LUI a2, 0x1F00
[*]80090B14 OR a2, a0, a2
[*]80090B18 MTC0 a2, BPC
[*]80090B1C JR ra
[*]80090B20 NOP
[/LIST=1]

Esta parte es la más interesante, y es donde se va a centrar el resto de nuestro trabajo, tanto para encontrar la MW como para lo que realmente es el crack.

La instrucción clave aquí es la 15. Una vez se llegue a ella, la MW ya habrá sido calculada, y estará contenida en la parte baja del registro a2, por lo que simplemente bastará con leer ese registro en ese instante para averiguarla. Ahora bien, ¿cómo podemos leer el registro si no podemos hacer una traza ni colocar puntos de ruptura? Muy fácil, basta por ejemplo con utilizar la instrucción BREAK (cuya ejecución detiene la PSX), y con el debugger mirar el valor que contiene la parte baja de a2. Para ello, lo que deberemos hacer es sustituir la instrucción 15 por un BREAK (0x0000000D).


Final de la fase 1

Resumiendo. Asumiendo que utilizamos la PCCOMM, el AR con la rom Caetla y el PsDebug, solo tendremos que abrir el ejecutable que tenemos guardado en nuestro disco duro, con las opciones "Execute now", "Enable Caetla hooks"
y "Set HBP on start address" activadas. Una vez cargado, abrimos la pantalla Memory y vamos a las direcciones de las instrucciones que queremos modificar, para así poder sustituir su código.

En nuestro caso las direcciones que nos interesan son en primer lugar la 8009083C, correspondiente a la instrucción 10 de la rutina anti-par, en donde tendremos que poner el código de un NOP (0x00000000); y en segundo lugar la 80090B18, en donde deberemos situar el BREAK (0x0000000D). Tened en cuenta además que la CPU de la PSX utiliza el formato Big Endian para almacenar los datos en memoria, lo que significa que las palabras se escriben situando el byte de mayor peso en la primera posición de memoria. Esto se traduce en que, por ejemplo, el BREAK se debe introducir como 0D 00 00 00.

Pues bien, una vez modificado esto le damos el control a la consola y veremos como enseguida se queda bloqueada. Entonces, solo tendremos que mirar el valor del registro a2, que contendrá la MW como por arte de magia :). En este caso el valor que vemos es 0x1F001A57 y, por consiguiente, la ansiada palabra de 16 bit será 0x1A57.


Fase 2: El Crack

En este punto ya tenemos toda la información necesaria para realizar el crack, esto es, la MW. Si estamos seguros de que no nos hemos equivocado y su valor es correcto podemos pasar directamente a crackear (modificar) la imagen del CD, pero si por el contrario tenemos dudas, o disponemos de una copia del juego sin crackear, es recomendable que hagamos una prueba antes.

Veamos de nuevo el fragmento de código que nos interesa:

[list=1]
[*]80090AE0 ADDIU a0, a0, 0x49C4
[*]80090AE4 SW zero, 0x0000(a0)
[*]80090AE8 MFC0 a2, BPC
[*]80090AEC LB a0, 0x0004(a1)
[*]80090AF0 ANDI at, a2, 0xFFFF
[*]80090AF4 BNE at, zero, 0x80090B18
[*]80090AF8 ANDI a3, a3, 0x0002
[*]80090AFC BEQ a3, zero, 0x80090B18
[*]80090B00 ADDI a0, a0, 0xFFAD
[*]80090B04 BNE a0, zero, 0x80090B18
[*]80090B08 NOP
[*]80090B0C LB a0, 0x0007(a1)
[*]80090B10 LUI a2, 0x1F00
[*]80090B14 OR a2, a0, a2
[*]80090B18 MTC0 a2, BPC
[*]80090B1C JR ra
[*]80090B20 NOP
[/list=1]

Recordad que nuestra intención era que en el BPC siempre se introdujera la MW, independientemente de los calculos y resultados de los checkeos. La solución más evidente es pues meter a mano el valor averiguado de la MW en el registro a2, justo antes de que sea copiado al BPC. Para ello, una opción sencilla puede ser cambiar la instrucción 14 por un ORI a2, a2, MW, donde MW en nuestro caso es 0x1A57. Esta instrucción codificada correspondería entonces a 0x34C61A57.

Con estos 4 bytes simplemente bastaría para romper la protección, y poder disfrutar de nuestra copia crackeado por nosotros mismos :). Sin embargo, hay algo que hasta ahora no os había comentado y que, aunque en un principio parece que no se utiliza realmente en la protección (de hecho creo que SquareX lo ignora en sus cracks), si está ahí es por algo, y ya se sabe que es mejor prevenir que curar. Me estoy refiriendo a las instrucciones 6, 8 y 10, que no son más que la consecución de la protección anti-modchip. Personalmente os aconsejo que sustituyáis estas tres instrucciones por NOP's, ya que aunque probablemente se pueda jugar con la copia sin anularlas, no nos cuesta nada hacerlo :).

Bueno, pues si con estos cambios la copia del juego se sigue bloqueando donde antes es que algo habéis hecho mal. Si, como esperamos, el juego ya no se bloquea, ahora sí solo nos queda modificar la imagen para sacar el ppf.


Sacando el parche

En este punto tenemos dos opciones. No calentarnos la cabeza y seguir el estándar que se utiliza habitualmente, o crear nuestro propio parche ejecutable que modifique la imagen. Si optamos por la segunda opción no debemos olvidarnos de corregir también el ECC/EDC, pues de lo contrario el parche fallaría con muchas grabadoras.

Lo mejor que podemos hacer es no calentarnos mucho el coco y seguir las normas establecidas, es decir, utilizar las utilidades ppf de iCARUS. No debéis olvidar tampoco en este caso el tema del ECC/EDC. Sin embargo, la solución es más simple si disponemos de una grabadora que sea capaz de regenerarlo automáticamente (casi todas menos las Philips 3610, algunas Teacs y sus remarcadas). Se trata de modificar una copia de la imagen original con un editor hexadecimal (recordad lo que os comenté antes del formato Big Endian ;) ), tostarla para que nuestra inteligente grabadora corrija el ECC/EDC y volver a sacar una imagen del CD resultante. Una vez hecho esto ya sí que podremos sacar el ppf entre esta imagen y la original, aunque os aviso que es preferible que la imagen "original" sea también hecha de una copia del CD original, y no de este directamente (ya sabéis para que están los regrabables :P).

Si tenemos la mala suerte de poseer una grabadora de las mencionadas antes, la cosa está más complicada. Algo que podría funcionar, aunque no lo he comprobado, sería grabar la imagen modificada en modo TAO como se comenta en esta misma web, y después repetir el proceso comentado anteriormente.

Algo que no he comentado, pero que siempre queda bien, es firmar nuestra obra, por ejemplo cambiando el texto de licencia o incluso la imagen de inicio con el BootEdit de Loser. También se puede poner una intro, con música y todo eso, pero, además de que el tema se complica bastante, aún no tengo demasiados conocimientos sobre ello...


Consideraciones finales

Bueno, pues hasta aquí llega el artículo. Espero que os haya servido tanto a los que ya teníais algo de idea en el tema pero no sabíais por dónde empezar, como a los que solamente tenías ilusión por aprender :). La verdad es que no he podido evitar dároslo todo mucho más detallado de lo que en un principio tenía pensado, y solo he obviado algunas pequeñas cosas que no creo que presenten demasiada dificultad.

Deciros también que aunque ya seáis capaces de hacer cracks no me gustaría que empezarais a mandarlos a todas partes, pues no está muy bien visto que aparezcan cracks para juegos que ya están perfectamente crackeados. La gracia está en ser el primero :). Sin embargo, si consideráis que vuestro parche tiene algún valor añadido al del resto de grupos, tampoco está demasiado mal que lo hagáis. Como ya digo, esto solo son cuestiones de educación y cortesía con el resto de crackers, pero cada cual es libre de hacer lo que quiera...

Aprovecho finalmente para darle las gracias a las dos personas que, sin saberlo, me han ayudado a iniciarme en estos menesteres: Jin y B.A.D.. También mandar ánimos y un saludo a jiXo, Estrayk, BRT, PeP2K, Coole, CesaRin y Pirate Hawk. A ver si con un poco de paciencia, tiempo, y con la ayuda de ellos y la vuestra puedo aprender algo sobre las nuevas versiones del LibCrypt. Ya sabéis que mis conocimientos son para todos ;).


Nota importante

Todo lo explicado en este artículo es con fines educativos, pero en algunos paises puede ser ilegal ponerlo en práctica... en ese caso no lo hagáis.


by Urotsukidoji
0 respuestas