Página 1 de 4

Cómo funciona un exploit

Publicado: 03 Feb 2010, 02:00
por gokuhs
Hola a todos,

Ahora leyendo los últimos rumores de PSP, me surgió una duda mas del tipo curiosidad que otra cosa;

¿Como funciona un exploit? Es decir, tenemos un crash que hemos podido capturar la excepción con PSPLink (en el caso de la PSP) y una vez aquí, teóricamente ¿Que es lo que se hace? ¿Que información útil sacamos de ahí y que hacemos con ella?

Un saludo y gracias

Re: Cómo funciona un exploit

Publicado: 03 Feb 2010, 03:00
por darklex150
el crash es el comienzo, es una via por la cual intentamos inyectar codigo para dejar a la psp en estado "tonto" y asi permitir la ejecucion de aplicaciones. Comunmente los crash permiten entrar en modo usuarioy con el exploit entramos a modo kernel, aunque todo depende del exploit, ya que no todos son asi.

Algo asi, ahora mismo no recuerdo como funciona exactamente (que alguien me corrija si estoy mal, por favor :) )

Re: Cómo funciona un exploit

Publicado: 03 Feb 2010, 03:04
por patmi22
darklex150 escribió:el crash es el comienzo, es una via por la cual intentamos inyectar codigo para dejar a la psp en estado "tonto" y asi permitir la ejecucion de aplicaciones. Comunmente los crash permiten entrar en modo usuarioy con el exploit entramos a modo kernel, aunque todo depende del exploit, ya que no todos son asi.

Algo asi, ahora mismo no recuerdo como funciona exactamente (que alguien me corrija si estoy mal, por favor :) )



Imagen

Re: Cómo funciona un exploit

Publicado: 03 Feb 2010, 03:40
por ryder
patmi22 escribió:
darklex150 escribió:el crash es el comienzo, es una via por la cual intentamos inyectar codigo para dejar a la psp en estado "tonto" y asi permitir la ejecucion de aplicaciones. Comunmente los crash permiten entrar en modo usuarioy con el exploit entramos a modo kernel, aunque todo depende del exploit, ya que no todos son asi.

Algo asi, ahora mismo no recuerdo como funciona exactamente (que alguien me corrija si estoy mal, por favor :) )



Imagen

:laughing: :laughing: :laughing: :laughing: :laughing:

XD eso da risa, asi como dijo darklex150, un crash te da acceso a una inestabilidad del sistema, un exploit, te permite manipular ciertas "circunstancias" dentro del sistema, tales como modificarlo o ver sus "entrañas", tecnicamente un exploit es como hacerte pasar Director general de un edificio, cuando solo eres el intendente XD


saludos

Re: Cómo funciona un exploit

Publicado: 03 Feb 2010, 03:59
por m0skit0
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 :mrgreen: :tongue:

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 :adora: 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:

Código: Seleccionar todo

Exception - Address store

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.

Código: Seleccionar todo

Thread ID - 0x05024259
Th Name   - SCE_VSH_GRAPHICS

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.

Código: Seleccionar todo

EPC       - 0x09C9A4FC

Dirección en RAM de la instrucción inválida.

Código: Seleccionar todo

Cause     - 0x10000014

Éste es el código de la causa de la excepción, es decir, Address store como hemos visto más arriba.

Código: Seleccionar todo

BadVAddr  - 0x89FFE5D0

La dirección RAM que se ha intentado usar en la instrucción inválida.

Código: Seleccionar todo

Status    - 0x60088613

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.

Código: Seleccionar todo

0x09C9A4FC: 0xAFB00020 ' ...' - sw         $s0, 32($sp)

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:

    Código: Seleccionar todo

    0x09C9A4FC: 0xAFB00020 ' ...' - sw         $s0, 32($sp)

    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? :lol: ), 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 :lol:

Re: Cómo funciona un exploit

Publicado: 03 Feb 2010, 04:07
por dark_sasuke
Vaya pedazo de hilo profe!!!!

y si quieres seguir explicando con gusto yo leo :mrgreen:

Re: Cómo funciona un exploit

Publicado: 03 Feb 2010, 10:19
por Rasta
Gran tuto.
Pero, podríamos utilizar el avatar de m0skit0 para hacer un crash y posteriormente un xploit, jajajaja...
Seguro que la psp se acojona y deja la puerta abierta...

Re: Cómo funciona un exploit

Publicado: 03 Feb 2010, 12:45
por gokuhs
Gracias m0skit0, la info es muy útil, te lo entendí todo no te preocupes, no soy un máquina pero hombre de esto algo entiendo.

Vale de momento tenemos la excepción no controlada por parte de Sony (estoy pensando en el firmawre de la PSP no de un homebrew). Supongo que los exploit se basan en desviar el hilo de procesamiento de la dirección que está ejecutando ahora a una nueva donde nosotros hemos cargado nuestro código que revienta el sistema ¿Es correcto? Ahora bien, ¿¿Como lo cargas?? y como haces de esa excepción un salto en los registros de memoria?

(Sobre ensamblador por desgracia no tengo mucha idea así que si me pones muchas instrucciones me perderé, pero no te cortes que con un buen manual...) :lol:

Re: Cómo funciona un exploit

Publicado: 03 Feb 2010, 14:03
por m0skit0
gokuhs escribió:Supongo que los exploit se basan en desviar el hilo de procesamiento de la dirección que está ejecutando ahora a una nueva donde nosotros hemos cargado nuestro código que revienta el sistema ¿Es correcto?

Totalmente. NI yo lo habría explicado mejor :D

gokuhs escribió:Ahora bien, ¿¿Como lo cargas??

Bien, la dificultad fundamental de un exploit realmente no es cargar el código, sino hacer que se ejecute. Como vimos anteriormente, las instrucciones no son más que números, al igual que los datos, que no son más que números. Por tanto si camuflamos nuestro código como datos y conseguimos engañar al sistema, aprovechando un fallo en una excepción, para que lo ejecute, entonces

Imagen

Una de las partes más difíciles de un exploit es saber si una excepción es aprovechable o no. Hay casos muy sencillos en que se ve a la legua si es aprovechable, pero en otros casos no es tan sencillo y requiere estudiar el código para ver donde radica realmente el fallo. Hay veces que la instrucción inválida ocurre más adelante en el código que donde realmente está el fallo. A veces demasiado adelante, y volver hacia atrás se convierte en una ardua tarea de ingeniería inversa.

Veamos el ejemplo más sencillo: control directo del registro ra. El registro ra es muy importante en temas de exploits porque es el registro que contiene la dirección de retorno (return address, in inglis pitinglis). ¿Qué demonios es una dirección de retorno? Pues es la dirección de memoria a la que tiene que volver la ejecución del programa una vez finalizada una función. No voy a meterme en qué tecnicismos sobre qué es una función, pero con que sepáis que es una porción de código que realiza una determinada tarea, nos vale. Las funciones generalmente terminan con la instrucción MIPS jr $ra (0x03E00008), es decir "salta a la dirección indicada por el registro ra". Si conseguimos de alguna manera hacer que este registro tenga el valor que queramos, podremos controlar la ejecución a nuestro antojo, haciendo que ejecute código en la dirección que nosotros consideremos. Y como al corromper ra hemos cargado otros datos, por ejemplo el nombre de un jugador en un savegame, podemos hacer que en realidad ese nombre sea código y hacer que el valor que sobreescribe el registro ra apunte en realidad a nuestro código que el juego ha cargado pensando que era un nombre.

¿Cómo se da la corrupción del registro ra? Generalmente se da por el hecho de que el valor de ra se guarda en lo que denominamos la pila, que no es más que una región de memoria en que se guardan valores temporales. ra se guarda en la pila porque es posible que su valor se modifique si la función en ejecución actualmente llama a otra, con lo que ra perdería el valor que tuviera. Pero al cargar datos maliciosos desde un fichero, lo que hacemos en realidad es corromper toda la pila, lo que se denomina técnicamente un desbordamiento de buffer (buffer overflow). Esto es debido a un fallo de los programadores, que por ejemplo preveen que el nombre del jugador va a tener como máximo 20 caracteres, pero al modificar manualmente el savegame le hemos puesto 200. Así que los programadores del juego, necios ellos, no comprueban la longitud del nombre, sino que lo cargan directamente en su pila, con lo que los 200 caracteres se cargan a todo lo que haya en la pila, incluído el valor de ra.

Espero os haya aclarado un poco el asunto. Si quieréis profundizar más sobre el tema, más detalles técnicos (conocimientos de C y ensamblador requeridos), podéis visitar este cursillo, por ahora sin acabar: http://advancedpsp.tk/foro_es/viewtopic.php?f=23&t=52

Re: Cómo funciona un exploit

Publicado: 03 Feb 2010, 14:47
por djoscar007
m0skit0 Muy Buena Leccion.....
Me ah encantado esto de los crash y los exploit....