1. Introducción
Luego de jugar este videojuego en línea, me di cuenta lo entretenido que era hacer retorcidas pistas (y servidores con ellas) para retar a los más ávidos corredores de países tan diferentes como Alemania, China, Francia o Argentina, entre los muchos países disponibles en el juego (lamentablemente exceptuando Chile). Al rato, luego de jugar algunas de las pistas más increíbles (la primera que me impresionó fue una llamada "Sweet Dream") se me presentaron muchas dudas de cual era el secreto dentro de esas excelentes creaciones, consecuentemente descargué cada una de las pistas interesantes mientras las jugaba.
Finalmente decidí revisar aquellas descargas con la finalidad de aprender de aquellos maestros de la creación de pistas, tal fue mi desilusión al descubrir que la mayoría de los circuitos más interesantes estaban protegidos mediante contraseña, que decidí investigar la protección y finalmente crear un pequeño documento con la travesía.
2. Validando una simple pista sin contraseña
La forma más fácil de descubrir la forma en que se almacenaba la contraseña era por supuesto creando una pequeña pista personal y colocarle una contraseña.
Primero desde el editor de pistas del juego, creamos un pequeño circuito sin mayores dificultades (hay que recordar que para que una pista sea válida el juego pide que podamos correrla por lo menos una vez, procedimiento que llama "validar"):

Luego de una simple "validación", guardamos la pista sin utilizar ninguna contraseña esta vez:

3. ¿Qué cambios genera la existencia de una contraseña?
Nuevamente, el paso más simple para responder nuestra interrogante es simplemente asignar una simple contraseña:

Así tenemos una serie de pistas que debemos analizar:

Para ver las diferencias entre los archivos podemos usar métodos que ciertamente comienzan en el masoquismo como lo sería hacer una comparación manual, o por medio de algún comando desde la línea de comandos (me refiero a COMP).
Como el proyecto no pretende ser un análisis de más de un par de horas lo mejor sería usar la utilidad WinDiff o en un mejor caso Hex Workshop que cuenta con una excelente herramienta de comparación de archivos resincronizando la posición de la comparación:

Luego de unos segundos saqué las siguientes conclusiones:
a) Un archivo sin contraseña y otro con contraseña difieren en bastantes bytes más que el largo de la contraseña, esto quiere decir que probablemente será más complejo quitar la contraseña que cambiarla por otra o "adivinarla".
b) Un archivo tiene el nombre otorgado a la pista en el nombre de archivo y adicionalmente dentro del archivo directamente. El juego al iniciar simplemente busca archivos con la extensión correcta, sin importar su nombre externo. Esto tiene una pequeña consecuencia que se debe tener en cuenta la cual es que si queremos comparar dos pistas cambiando sólo la contraseña sin alterar mas bytes debemos mantener el nombre interno de la pista. Esto se logra fácilmente creando un directorio en donde iremos guardando las pistas mientras las guardamos y sobreescribimos el archivo guardado simplemente cambiando la contraseña desde el juego.
c) Dos contraseña de diferente largo generan diversos cambios más en distintas partes del archivo como se aprecia en la siguiente imagen:

4. Why?! Why do you persist, Mr. Anderson?
Generé algunas contraseñas más para analizar, siento que el secreto tras la codificación no es tan oscuro como pensé:

Y ciertamente el cambio que ocurre en dos archivos que se diferencian sólo por un caracter en la contraseña es extremadamente sutil:

(El cambio reflejado en la imagen anterior se repite 2 veces cada vez en el archivo, aunque el cambio es exactamente igual por lo que sólo mostré uno de los cambios)
5. Un pequeño coffee break
Antes de continuar debo resumir los resultados (algunos de ellos sin base empírica aún):
a) Es mucho más simple decodificar la contraseña para descubrir cual es la que se utilizó en la pista
b) Es mucho más complejo remover una contraseña directamente del archivo que lo expuesto en el punto a)
c) Es mucho más complejo cambiar la contraseña por otra de diferente longitud que lo expuesto en el punto a)
d) Sin embargo hay algo mucho más simple que lo expuesto en el punto a) pero menos lógico que es reemplazar la contraseña original del archivo de largo conocido, por otra del mismo largo
e) Finalmente, el juego revisa la integridad de los archivos al iniciar, si hay alguna incongruencia simplemente aborta totalmente el inicio
Dado este pequeño diagnóstico, creo que el punto para seguir el artículo es el a) y esto nos lleva a realizar un análisis de la codificación.
6. Una simple pero astuta forma de encriptar
Al utilizar contraseñas totalmente repetitivas como "aaaaa" en las pistas del juego encontré que extrañamente (o predeciblemente) ninguna de las formas de codificadas de cada letra se repetía en su correspondiente "hermano" codificado (recordemos que la longitud afectaba completamente al archivo, pero misteriosamente cada letra añadía sólo un nuevo caracter codificado en la sección que detecté en donde se almacenaba esta contraseña codificada), gráficamente, la codificación de "aaaaa" da un resultado así:

Ese pequeño diagrama no produce asombro, de hecho se puede pensar que la codificación es "bastante buena". Lo extraño es lo que sucede para una clave algo más larga, digamos "aaaaaaa":

Claramente se nota una codificación cíclica, más específicamente, cada cinco posiciones se repite el patrón.
En este punto tenía dos opciones, analizar miles de posibilidades e intentar revertir la codificación (casi como debería hacerlo un cracker con el fin de generar un keygen) y es más, este modo hubiera sido increíblemente elegante, u otro método menos elegante. Opté por crear una tabla de conversiones (el método menos elegante) pero mucho más mecánica de elaborar.
7. El trabajo mecánico de crear una tabla
La idea es generar una tabla de equivalencias por posición, es decir, si cada cinco caracteres la codificación de un caracter se repite, simplemente debemos confeccionar una tabla con cinco posibilidades por caracter.
El procedimiento puede ser muy trabajoso, de hecho a eso me refiero con "trabajo mecánico". Sin embargo, ¿cómo podría documentar esto sin algo de automatización computina de por medio?
Primero, si colocando "aaaaa" como contraseña a una pista puedo tener las cinco traducciones de la letra "a" en cualquiera de las cinco posiciones posibles (me refiero al módulo de cinco, de la posición que queremos decodificar) entonces ¿cómo podré obtener TODO el abecedario, los números y símbolos?
GroundControl es una excelente herramienta que nos permite automatizar con sencillos comandos el funcionamiento de Windows, entonces:
a) Tomar todo el abecedario en minúsculas, duplicarlo y colocarlo en mayúsculas
b) Adjuntar los dos abecedarios
c) Repetir cinco veces cada caracter, obteniendo finalmente una cadena (que será la contraseña de la pista) de cinco veces el largo de los dos abecedarios juntos
d) Generar la pista con esta contraseña, extraer los caracteres codificados y hacer la tabla de traducción de caracteres de entrada versus caracteres de salida
e) Finalmente repetir el punto c) para los números y luego para los símbolos (o al menos los más comunes)
De hecho todo el procedimiento servirá para analizar la codificación posteriormente. Ahora la titánica tarea de escribir la contraseña de doscientas letras en el juego sin ningún error es un procedimiento totalmente trivial para el siguiente script de GroundControl:
| Código: |
// Variables e inicialización |
Como pueden imaginarse, para los símbolos y números es prácticamente lo mismo. Esto reduce el trabajo a muy pocos minutos y luego con un editor hex hago extracción de nuestra cadena codificada:

Si miran fíjamente, incluso en la columna de "diferencias" (la que corresponde a la diferencia entre el caracter normal ASCII con el codificado, en base 10) se puede apreciar el concepto que dije anteriormente sobre la periodicidad de la codificación.
Para entender mejor todo el proceso, mirar el siguiente video:
8. Entonces, ¿y el programa?
Aquí está:

Trackmania Tracks Password Revealer es el nombre de la aplicación resultante de esta pequeña investigación, su tarea es simplemente recibir una pista de Trackmania (al parecer no importa si es Trackmania Sunrise, Trackmania Nations o Trackmania United, en general cualquiera con extensión ".Challenge.Gbx") y entregar la contraseña de la misma. Esta desarrollada con Visual Studio 2005 (C#) por lo que se necesita el .NET Framework 2.0 o superior para utilizarlo:
Descarga del ejecutable:
files/articles/tm_password_revealer_01/TM_password_revealer_v0.1_bin.rar
Algunas pistas que usé en este artículo:
files/articles/tm_password_revealer_01/Ejemplos_pistas.rar
Descarga del código fuente:
files/articles/tm_password_revealer_01/TM_password_revealer_v0.1_source.rar
9. Un reto para el lector de este artículo
Propongo que si tienes facilidad con estos temas de codificación, descargues la tabla de equivalencias:
files/articles/tm_password_revealer_01/abecedario_tabla_excel_97-2003.rar
files/articles/tm_password_revealer_01/abecedario_tabla_excel_2007.rar
y trates de encontrar una función (o en el peor de los casos, cinco funciones) tales que:
| Código: |
f('letra_codificada',posicion)='letra'; |
Creo que para el abecedarios, mayúsculas y minúsculas es casi evidente, aunque parece que para los símbolos no basta ASCII como representación. Una simple función para el abecedario quitaría varios bytes de la aplicación.
10. Conclusiones
Cuando escribo este último párrafo de conclusiones estoy gratamente complacido con el trabajo, por pequeños que sean los problemas siempre necesitan algo de ingenio y eso es lo entretenido.
Sin embargo, en este caso creo que se pudo haber hecho algo muchas veces más elegante, es por eso que en el punto anterior dejo abierta la invitación y espero recibir alguna sugerencia.
Espero que el documento esté lo suficientemente entendible y bien explicado, generalmente me toma más tiempo documentar una pequeña investigación que hacerla, aunque parezca que no es así.


