Su primer desbordamiento de búfer
Ya sea que sea estudiante, desarrollador o gerente de una empresa, debe probar esto. La clave para escribir código seguro es comprender cómo se rompe el código incorrecto. La única forma de descifrar el código incorrecto es ensuciarse las manos y comenzar a hacer estallar proyectiles en los desafíos de explotación binaria. En este artículo, lo guiaré a través de cómo ejecutar su propio ataque de desbordamiento de búfer usando un ejemplo que hice en YouTube.
En uno de mis videos de YouTube, expliqué cómo las cadenas en el lenguaje de programación C han estado haciendo que la gente sea pirateada. La razón principal de esto es que no hay un atributo de longitud incorporado asociado con el tipo de cadena C. La única forma de saber si una cadena está lista es navegar hasta el final de la cadena.
https://youtu.be/fjMrDDj47E8
Este concepto ha provocado innumerables vulnerabilidades de desbordamiento de búfer en el software y, como resultado, ha provocado miles de ataques cibernéticos y el robo de datos personales.
Nuestro servidor vulnerable
A continuación se muestra un código para un servidor simple en C.
#include <stdio.h>
#include <secrets.h>
void debug()
{
printf("!! ENTERING DEBUG MODE !!\n");
system("/bin/bash");
}
int checkPassword()
{
char password[64];
printf("password: ");
gets(password);
return isValidPassword(password);
}
int main(int argc, char **argv)
{
printf("WELCOME TO THE SECURE SERVER\n");
if (checkPassword())
{
debug();
} else {
printf("Wrong password, sorry;\n");
}
}
Sin embargo, hay una gran vulnerabilidad aquí. La contraseña que finalmente se verifica es leída por la función gets , que es una función extremadamente vulnerable. Si no me cree, consulte la página del manual para obtener.
Never use gets(). Because it is impossible to tell without knowing the data
in advance how many characters gets() will read, and because gets() will
continue to store characters past the end of the buffer, it is extremely
dangerous to use. It has been used to break computer security. Use fgets()
instead.
La pila
La parte más difícil de entender para los programadores y los profesionales de la seguridad cibernética es cómo una saturación de datos fuera de un búfer puede hacer que un pirata informático obtenga el control de su código y, en última instancia, de su computadora. La forma en que esto sucede se debe a cómo las computadoras organizan la memoria cuando se ejecuta un programa.

En el ejemplo de código anterior, el programa se inicia en main. Después de que main comience, en la línea 10, se llama a otra_función . Lo que es extremadamente importante de entender es cómo otra_función sabe que debe ir a la línea 11 después de regresar.
La estructura que contiene esta información se denomina "la pila". La pila es la región de RAM que se usa cuando se ejecuta su programa y se usa para almacenar información de flujo de control (como direcciones de retorno), pero también datos.
Cuando main llama a other_function , la dirección que se ejecutará a continuación en main después de que other_function regrese se coloca en la parte superior de la pila. se ejecuta other_function , y luego el programa vuelve a la dirección almacenada por main .
Aquí es donde los desbordamientos de búfer comienzan a importar. Si hay un desbordamiento de búfer en los datos de su programa, puede cambiar la información del flujo de control y eventualmente cambiar la forma en que se ejecuta el programa.

Inténtalo tú mismo
Lo mismo se aplica a este fragmento de código aquí. La idea detrás de este programa es: si conoce la contraseña, obtiene un caparazón. Desafortunadamente, los piratas informáticos no conocemos la contraseña, por lo que no tenemos un caparazón. Sin embargo, debido a que se usa la función gets , podemos aprovechar la vulnerabilidad de desbordamiento del búfer y desbordar la dirección de retorno. En lugar de volver a main , podemos volver directamente a la función de depuración sin saber la contraseña.
Sigue aquí:
https://github.com/lowlevellearning/secure-server-stuff
Funcionalidad de prueba
Para comenzar, debemos ejecutar el servidor y probar su funcionalidad. Además, intentemos adivinar la contraseña.

Muy bien, no hay dados. Aquí es donde comienza la piratería.
Bloquear el servidor
Podemos aprovechar el desbordamiento del búfer, como su nombre lo indica, desbordando el búfer. Para hacer esto, proporcionamos más datos de los que el servidor puede manejar.

En la parte inferior, vemos que el programa tenía una falla de segmentación. Lo que esto significa es que el programa intentó acceder a la memoria a la que no pudo acceder. Si eres un desarrollador, esto es malo. Pero, si estás tratando de hackear el servidor, esto es bueno :)
Analicemos el accidente un poco más.

Aquí, podemos ver que el programa cometió un error de segmento al intentar ejecutar las instrucciones en la dirección 0x41414141. Esa dirección debería parecer... extraña. Curiosamente, 0x41414141 es la representación hexadecimal de la cadena "AAAA", lo que significa que nuestra cadena de As se desbordó en la dirección de retorno y la CPU intentó ejecutarla. ¡AHORA ESTAMOS HACKEANDO!
Tomando el control
Para obtener un control exacto de la dirección de retorno, debemos determinar específicamente qué parte de nuestra cadena ASCII provocó que el programa fallara. Podemos hacerlo modulando nuestra cadena con diferentes caracteres y usando los caracteres para determinar dónde comienza y termina nuestro control de la dirección de retorno.

En lugar de una larga cadena de As, ponemos 64 As, seguidos de una serie de caracteres ASCII adicionales. 64 es la longitud de nuestro búfer de entrada, por lo que es un buen lugar para comenzar a adivinar la longitud. Después de eso, insertamos caracteres adicionales. Para verificar dónde comienza nuestro control, use el mismo comando que antes.

Ahora puede ver que tenemos una nueva dirección de devolución. ¡0x45454545 es la representación hexadecimal de "EEEE"! Lo que esto significa es que hemos determinado dónde nuestro desbordamiento toma el control del puntero de retorno. A partir de aquí, necesitamos poner una dirección en el búfer que realmente nos interese. Estamos tratando de volver a la función de depuración, por lo que debemos colocar esa dirección en lugar de la cadena EEEE.
Para determinar la dirección de depuración, ejecutamos un comando simple...
objdump -d -Mintel ./hacked | less

Parece que la dirección de depuración es 0x08049296. Si ponemos la dirección de depuración donde estaba nuestra cadena EEEE, tal vez podamos controlar el programa y volver a depurar sin necesidad de la contraseña.
La hazaña final
Podemos hacer eso usando algo de python-fu.
import sys
payload = b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
payload += b"BBBBCCCCDDDD"
payload += b"\x08\x04\x92\x96"[::-1]
sys.stdout.buffer.write(payload)
user@user:~/vuln$ (python3 exploit.py; cat) | ./hacked
WELCOME TO THE SECURE SERVER
password: !! ENTERING DEBUG MODE !!
cat password
too_kool_4_skoo
Sígueme en Medium, ve a Suscríbete en YouTube. ¡Más por venir!