Es muy díficil explicar un exploit sin tener conocimientos previos de cómo funciona realmente un sistema informático, y mucho más sobre un sistema específico (es este caso PSP). Pero bueno, voy a intentarlo, a ver qué os parece
Antes de cualquier cosa, hay que entender qué es un crash o cuelgue. Un cuelgue ocurre cuando el software que corre en la PSP intenta ejecutar una instrucción no válida. No se puede saber qué es una "instrucción no válida" si no se sabe lo que es una instrucción. Aquí es donde entramos en el tema de saber cómo funciona un sistema informático, pero para simplificar, voy a decir que un ejemplo de instrucción no válida es intentar guardar un dato en un lugar (técnicamente lo llamamos
dirección) que no existe en la RAM. Es como mandar una carta a una dirección que no existe.
Al intentar ejecutar una instrucción no válida, el procesador de la PSP (un MIPS R4000 modificado) detecta lo que técnicamente se denomina una excepción. Existe un programa que se ejecuta cada vez que ocurre una excepción, lo que se llama el manejador de excepciones (
exception handler). En el caso del FW de la PSP, el manejador de excepciones es un bucle infinito. Al detectar esta condición de bucle infinito, el Syscon (el chip encargado de monitorizar el sistema a nivel de hardware) apaga el procesador. Lo que hace PSPLINK
es instalar su propio manejador de excepciones, que simplemente vuelca el estado del procesador en el momento de la excepción, algo así:
Código: Seleccionar todo
host0:/> Exception - Address store
Thread ID - 0x05024259
Th Name - SCE_VSH_GRAPHICS
Module ID - 0x050BE409
Mod Name - sceFileParserBase_Module
EPC - 0x09C9A4FC
Cause - 0x10000014
BadVAddr - 0x89FFE5D0
Status - 0x60088613
zr:0x00000000 at:0xDEADBEEF v0:0x09C9A4F8 v1:0x80000020
a0:0x08B46EA0 a1:0x00000015 a2:0x80000013 a3:0x00000000
t0:0x09FFE608 t1:0x00000000 t2:0xDEADBEEF t3:0xDEADBEEF
t4:0xDEADBEEF t5:0xDEADBEEF t6:0xDEADBEEF t7:0xDEADBEEF
s0:0x80000013 s1:0x09FFE748 s2:0x09FFEA24 s3:0x09FFE800
s4:0x09FFE600 s5:0x00000001 s6:0x00000015 s7:0x00000000
t8:0xDEADBEEF t9:0xDEADBEEF k0:0x09FFEE00 k1:0x00000000
gp:0x09C61790 sp:0x89FFE5B0 fp:0x09FFE600 ra:0x09D0486C
0x09C9A4FC: 0xAFB00020 ' ...' - sw $s0, 32($sp)
Voy a intentar explicar la descripción que da PSPLINK sobre el estado del sistema en el momento de la excepción:
Aquí nos indica que ha habido una excepción debida a que se ha intentado guardar un dato en una dirección RAM inválida.
El ID y el nombre del hilo que ha ejecutado la instrucción inválida.
Código: Seleccionar todo
Module ID - 0x050BE409
Mod Name - sceFileParserBase_Module
El ID y el nombre del módulo (un PRX para entendernos) que contiene la instrucción inválida.
Dirección en RAM de la instrucción inválida.
Éste es el código de la causa de la excepción, es decir,
Address store como hemos visto más arriba.
La dirección RAM que se ha intentado usar en la instrucción inválida.
Código del estado del sistema al producirse la excepción.
Código: Seleccionar todo
zr:0x00000000 at:0xDEADBEEF v0:0x09C9A4F8 v1:0x80000020
a0:0x08B46EA0 a1:0x00000015 a2:0x80000013 a3:0x00000000
t0:0x09FFE608 t1:0x00000000 t2:0xDEADBEEF t3:0xDEADBEEF
t4:0xDEADBEEF t5:0xDEADBEEF t6:0xDEADBEEF t7:0xDEADBEEF
s0:0x80000013 s1:0x09FFE748 s2:0x09FFEA24 s3:0x09FFE800
s4:0x09FFE600 s5:0x00000001 s6:0x00000015 s7:0x00000000
t8:0xDEADBEEF t9:0xDEADBEEF k0:0x09FFEE00 k1:0x00000000
gp:0x09C61790 sp:0x89FFE5B0 fp:0x09FFE600 ra:0x09D0486C
Contenido de los registros del procesador en el momento de la excepción.
Desensamblado de la dirección RAM en que se ha producido la excepción.
Como puedes ver, para entender el asunto bien, habría que saber qué es un hilo, qué es un módulo, qué es una dirección de memoria, qué es un registro y qué es un desensamblado. A ver si puedo aclarar estos conceptos sin liarme mucho:
- Hilo de ejecución: un hilo es cada una de las entidades que ejecuta código. Por ejemplo, en un juego de carreras de coches, tienes un hilo que ejecuta el dibujado del mapa, otro que dibuja los coches, otro que calcula los movimientos del coche en función de las pulsaciones de botones, otro que maneja los coches de la máquina (la IA), etc... En realidad, estas cosas no ocurren todas a la vez, sino de una en una, pero pasan de una a la siguiente tan rápido que para nosotros lentos humanos parece que todo ocurre a la vez.
- Módulo: simplificando, un módulo es un fichero PRX. Estos ficheros son como los EXE de Windows, pero para PSP. Se cargan en memoria y tienen instrucciones para ejecutar.
- Dirección de memoria: como ya comentamos, es algo muy similar a una dirección de correo, sólo que en realidad es una dirección de un byte en la memoria principal (RAM). En el caso de la PSP, una dirección es un número de 32 bits, representados generalmente como un número hexadecimal de 8 cifras del tipo de 0xFEAFEA00 (el 0x al principio sólo indica que el número que sigue es hexadecimal).
- Registro: es una memoria muy muy pequeña y muy muy rápida que se encuentra dentro del procesador, y que los programadores usan para realizar cálculos. Algunos de ellos tienen una función específica dictada por la arquietectura, otros son de uso genérico. En el caso de PSP, el procesador MIPS tiene 32 registros de 32 bits cada uno, siendo sus nombres zr, at, v0, v1, a0, a1, a2, a3, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s0, s1, s2, s3, s4, s5, s6, s7, k0, k1, gp, sp, fp y ra.
- Desensamblado: consiste en convertir el lenguaje máquina en ensamblador. Por ejemplo, antes hemos visto un desensamblado:
0x09C9A4FC es la dirección de memoria en la que se encuentra la instrucción 0xAFB00020. Como véis, las instrucciones son números (representadas generalmente en hexadecimal). Pero esta instrucción traducida a ensamblador es sw $s0, 32($sp), o en cristiano, "guarda el valor del registro s0 en la dirección de memoria que indique sp + 32".
Bueno, aclarado esto (¿o no?
), podemos intentar entender por qué ocurre esta excepción en concreto. Sabemos que es porque el programa en cuestión (
SCE_VSH_GRAPHICS en este caso) ha intentado guardar un dato en una dirección de memoria inválida mediante la instrucción
sw $s0, 32($sp). Como vemos en la información que nos brinda PSPLINK,
sp tiene un valor de
0x89FFE5B0. Si le sumamos 32, es decir, 0x20 en hexadecimal, obtenemos 0x89FFE5D0. Ésta es la dirección que SCE_VSH_GRAPHICS está intentando usar para guardar el dato que se encuentra en
s0. Si os fijáis, BadVAddr es efectivamente
0x89FFE5D0, la dirección inválida.
¿Pero cómo se sabe si una dirección es válida o inválida? Aquí es donde volvemos otra vez a la importancia de saber la arquitectura de la máquina cuando se habla de crashes y exploits. Las direcciones de memoria válidas en una PSP son (recordad, máximo 32 bits, 8 dígitos hexdecimales):
- 0x00010000 - 0x00013FFF -> Scratchpad (16 KB)
- 0x04000000 - 0x041FFFFF -> RAM vídeo (2 MB)
- 0x08800000 - 0x09FFFFFF -> Memoria de usuario (24 MB)
- 0x0A000000 - 0x0BFFFFFF -> Memoria de usuario extendida (32 MB - sólo modelos 2000 y superiores debido a los 64 MB de RAM)
- 0x88000000 - 0x887FFFFF -> Memoria kernel (8 MB)
- 0xBFC00000 - 0xBFCFFFFF -> Memoria interna procesador (1 MB) (puertos hardware, IPL, Pre-IPL, etc...)
Así que como podéis comprobar, la dirección
0x89FFE5D0 está fuera de todos los rangos, por tanto es inválida. También hay que tener en cuenta que los hilos que sean modo usuario (como los juegos por ejemplo) no pueden acceder a la memoria kernel (de
0x80000000 en adelante) y si lo intentan obtendrán igualmente la misma excepción sobre dirección inválida.
Bueno, habiendo introducido esto, que
es la parte más sencilla de explicar, quien quiera hacerse el valiente para entrar en lo que es un exploit, que ya es bastante más complicado, yo sigo adelante