CUE escribió:Pero es que faltan más datos. No se sabe si todos los ficheros tienen la misma estructura, se desconoce si el primer XOR se hace siempre con el mismo valor, ...
Hay básicamente dos archivos de este tipo. El de las misiones y el que contiene objetos y otros.
El de las misiones son todos iguales. Tienen la misma estructura. El de los objetos tengo que mirarlo más a fondo.
El archivo de misiones siempre es igual, cabecera MXE... Segunda cabecera MXE y a partir del 0x000040 es donde está la parte codificada con los XOR hasta que llega al final que es justo antes del POF. Vamos lo que sería el tamaño marcado en 0x000034.
El algoritmo de decodificación es el siguiente (en ensamblador del MIPS):
beq a0,a1,0x08BA920C
andi a2,a2,0xFF
lbu a3,0x0(a0)
xor a2,a3,a2
sb a2,0x0(a0)
addiu a0,a0,0x1
bne a0,a1,0x08BA91F4
move a2,a3
jr ra
nop
El registro A2 entra con el valor de 0x000041 en el bucle. Se carga con ese valor en una porción de código que está antes de ser invocada esta rutina.
beq compara valores, si son iguales sale del bucle sin ejecutarlo.
andi a2,a2,0xff rellena con ceros el tamaño del registro para ocupar los 32bits.
lbu a3,0xc(a0) carga el registro a3 con el valor que está en la dirección de memoria a la que apunta el registro a0. En el momento de entrar en el bucle estaría en la posición 0x000040 del archivo ejemplo. (La posición de memoria de la consola sería otra, claro).
xor a2,a3,a2 Esto está claro hacer el Xor y guarda el resultado en el registro a2.
sb a2,0x0(a0) guarda el contenido del registro a2 (en este momento guarda el valor del xor) en la posición de memoria a la que apunta a0, sobreescribiendo el valor original.
addiu a0,a0,0x1 incrementa en uno el valor del registro a0, que hace las veces de contador y de apuntador, y apunta a la siguiente posición de memoria.
bne a0,a1,0x08BA91F4 compara el valor de los registros a0 y a1. Si son iguales es que se ha alcanzado el final de la cadena y se sale del bucle (siguiría con jr ra) . Si son distintos se ejecuta un nuevo ciclo del bucle que se inciaría en lbu a3,0x0(a0).
Pero antes del salto a lbu se ejecuta:
move a2,a3 que guarda el valor de a3 (registro que contiene el valor de 0x000040 al inicio) en el registro a2. Y de este modo hace lo que explicaba más arriba:
Cogen el valor 0x000040 y le aplican un Xor con el valor de 0x000041, luego cogen 0x000041 (con su valor original se entiende) y le aplican un Xor con el valor 0x000040 ahora cogen 0x000042 y hace xor con el valor original de 0x000041 y así hasta completar la cadena. Todo esto ya que en la cadena se entra con el valor de 0x000041 en el registro a2.
Y ahora si que se salta al lbu. Iniciando un bucle más.
Para codificar es lo mismo pero al revés. Empezando por el final con el valor e8 para el registro a2. Cuando se llega al final se hace un xor con 0x000041 cogiendo el valor de 0x000040 al que ya ha sido aplicado el xor. Vamos en el caso del ejemplo 0x000041 vale 01 antes de ser aplicado el xor y 0x000040 vale cd pues 01 xor cd = cc que es el valor original de 0x000041 antes de ser descifrado.
Acabo de mirar el resto de archivos de este tipo y son iguales. Todos tienen la misma estructura. En caso de necesitar más tengo muchos...
