Despues de ver el paper de mi amigo seba, que esta excelente!, estuvimos hablando y se me ocurrio redondear un poco este tema tan interesante, y tratar de explicar que es cada concepto para ir entendiendo las diferentes terminologias usadas hoy en dia y comprender de que hablan al momento de cuando la escuchamos o leemos. Intentare ser lo mas light posible para newbies, pero bueno, cualquier cosa me putean... mas adelante pienso expandirlo, pero mas adelante, relax!.
# Que es un Buffer Overflow?
Vamos a empezar por esta terminologia que 'creo' es la mas conocida en el ambiente, y por los newbies. Aunque creo que tambien algunas personas intentan exponer el tema como un concepto complejo y realmente es todo lo inverso, ya veran..
Un buffer overflow, significa tener un vaso lleno de agua, a tope y luego agarrar la jarra de agua, y volver a vertir agua en ese vaso a tope.. lo que haria este pobre vaso de agua, es Desbordar debido a que tiene un limite de capacidad para contener dicha agua.
Esto mismo sucede en la memoria.. consiste en escribir en un buffer datos por encima de lo que puede contener este como limite. Veamos un ejemplo en c con un "mal uso de strcpy", creemos nuestro mini soft vulnerable:
Compilamos con GCC.
confused@opk:~/Desktop$ gcc buff.c -o buff
Y ejecutamos ./buff `perl -e "print 'O'x100"`
(la invocacion del perl que imprime 100 veces la letra O, es para no escribir mas de 40 veces un caracter manualmente, aunque pueden hacerlo tranquilamente, ./buff 00000000000....y asi hasta una considerable carga de caracteres arriba de 40 bytes) pero piensen que en una aplicacion de verdad tendran que ingresar mas de 1.000 bytes generalmente y es un dolor hacerlo manualmente.
Bueno al ejecutar nos devolvio "Violacion de Segmento" y eso es lo que nos interesa!.
Esto se debe a que el buffer fue definido por el programador con un total maximo de 40 y si logicamente le metemos 100 al invocar perl, desbordaria por mas del doble de caracteres ingresados.
Como esto simplemente es para comprender los conceptos, la accion la haremos mas adelante..
# Que es Heap Overflow?
Bueno una vez que tenemos conocimientos sobre el BOF (Buffer Overflow) o comprendemos de que trata realmente.. podemos decir que el HEAP OVERFLOW es una derivacion del BOF, pero este tiene la caracteristica de producirse en una zona determinada de la memoria llamada HEAP.
Este termino significa un 'monton'/'porcion' de memoria o tambien conocida como 'memoria dinamica' o 'monticulo'.
Cuando se ejecuta un programa el SO lo primero que hace es copiar y pegar todo el codigo del programa en una zona de memoria que este vacia/libre ademas de reservar espacio extra para la ejecucion de dicho programa:
*Entre ese espacio extra, se encuentra una zona de datos donde se guardaran las variables globales y las constantes.
*Una zona para las call stack o llamadas de pila donde almacena los parametros de las funciones, variables locales, y valores de Retorno...
*Y una zona para la memoria dinamica [HEAP] que es la memoria solicitada para la ejecucion del programa.
Veamos un ejemplo de un sencillo Heap Overflow:
Compilamos:
gcc heap.c -o heap
Y ejecutamos de la siguiente manera ./heap [algunValor]
Como respuesta obtenemos "No paso nada"..
Como vemos el programa pide un dato que sera ingresado por el usuario el cual cuya memoria fue reservada con malloc().
Pero logicamente vemos que pide 40 bytes de memoria reservada y si invocamos a perl nuevamente e ingresamos varios caracteres que sobrepasen la memoria reservada veamos le resultado.
./heap `perl -e "print 'O' x100"`
Y vemos que nos responde lo que queriamos ver
Para ir finalizando explicare la tercer terminologia conocida como Stack Overflow, espero no aburrirlos.
# Que es el Stack Overflow?
Lo primero con lo que debemos manejarnos es con el termino "stack", este termino viene de "PILA". Claramente como la Pila de libros, donde todos los libros estan montados unos arriba del otro y forma una pila... bueno eso es.. tambien podemos pensarlo como un MAZO DE CARTAS, el cual todas las cartas son apiladas.. y el modo de acceso a esas cartas es lo que se conoce en ingles como LIFO -Last in first out- / Ultimo entrado, primero salido. Bien... imaginense que es un mazo de cartas, donde el ancho de espada lo ponemos arriba de la pila, y luego para acceder a una carta debajo de esta, primero tenemos que sacar el ancho de espada y luego sacar si la segunda carta de la pila....
Esto seguramente sera visto mas a futuro con un curso de assembler que tenemos pensado con snf, pero bueno de momento, me conformo con que sepan que una pila, stack no es mas que una estructura de datos, apilado uno arriba del otro y que para usar la 2da posicion debemos primero quitar la primera siempre...
Bueno a continuacion explicare en que consta el stack overflow con un ejemplo similar al anterior supongo que ya se lo imaginaran conociendo el concepto de overflow.
Al mismo vaso de agua de capacidad limitada y a tope, le cargamos mas agua? resultado? Desbordamiento...
Veamos este code:
Bien, como siempre, compilamos con nuestro querido GCC
$ gcc a.c -o a
luego ejecutamos:
$ ./a
El tan preciado 'Violacion de Segmento' ha aparecido.
Claramente aparecio porque cuando copiamos el contenido de buffer2 a buffer1 este desborda de informacion, ya que tan solo tiene un limite de 16 lugares... y buffer2 un container de Zetas :p.
Bien, la pregunta ahora es una ves que desborda termina ahi?... la respuesta es claramente que depende nuestros objetivos NO!.
Veamos habiamos hablado un poco de la STACK/PILA del sistema y habiamos dicho que esta podiamos imaginarla como un mazo de cartas! o una pila de libros. Bien.. supongamos que tenemos algo asi relacionando con el code desbordado.
STACK............................buffer2 [contiene las ZZZZZZZ....]
STACK............................buffer1 [por el momento esta vacio, todavia no copiamos]
Y debajo estan los registros EBP & EIP con ciertos valores...
Ahora una vez que el strcpy es ejecutado, tendriamos un panorama asi en la stack.
STACK............................buffer2 [(45z)zzzzzzzzzzzzzzzzzzzz...]
STACK............................buffer1 [zzzzzzzz zzzzzzzz zzzzzzzz] y las que sobran caen en ebp & eip
STACK............................ahora valen EBP=0x5A5A5A5A EIP=0x5A5A5A5A
Valen 0x5A5A5A5A porque cada direccion es de 4bytes y 5A en hexadecimal es Z.
Esto pasa porque como el buffer1 no tenia capacidad a tantas lluvias de Zetas, se paso del limite y sobreescribio estos dos registros que nombre.
EIP es un registro que contiene la direccion de la instruccion que el programa va a devolver al finalizar este...entonces el programa desborda y al caer las Z en el registro EIP, este al finalizar intenta ejecutar lo que se encuentra en 0x52525252
pero como no hay nada, nos arroja el famoso Violacion de Segmento.
Comprobemos con un ejemplo con my friend Ollydbg aver que sucede y que movimiento hace:
Al correrlo, y parar en la funcion strcpy vemos que sucede en el registro:
Vemos como ahora EBP y EIP pasan a valer Z es decir 0x5A5A5A5A
Ahi tenemos una clara imagen de lo que es la PILA. Y tambien vemos como esta sobreescrita por las Z insertadas.
Y si vemos las direcciones del dump, ahi nos muestra las zetas en sus respectivas posiciones en memoria.
Espero que haya ayudado a iniciarse mejor con los conceptos de overflow.
Saludos, cualquier consulta, son libres de hacerla!
# Que es un Buffer Overflow?
Vamos a empezar por esta terminologia que 'creo' es la mas conocida en el ambiente, y por los newbies. Aunque creo que tambien algunas personas intentan exponer el tema como un concepto complejo y realmente es todo lo inverso, ya veran..
Un buffer overflow, significa tener un vaso lleno de agua, a tope y luego agarrar la jarra de agua, y volver a vertir agua en ese vaso a tope.. lo que haria este pobre vaso de agua, es Desbordar debido a que tiene un limite de capacidad para contener dicha agua.
Esto mismo sucede en la memoria.. consiste en escribir en un buffer datos por encima de lo que puede contener este como limite. Veamos un ejemplo en c con un "mal uso de strcpy", creemos nuestro mini soft vulnerable:
Código
Code (c):// Testing Buffer Overflow in HDL
#include
#include
void BufferVulnerable(char *value) { // creamos nuestro buffer
char buffer[40]; // como es una prueba simplemente limitamos a 40
strcpy (buffer, value); // copiamos lo que se ingrese al buffer
}
int main (int argc, char *argv[]) {
if (argc !=2) {
printf ("Para usar: ./buff [caracteres] \n", argv[0]);
return 0;
}
BufferVulnerable(argv[1]);
return 0;
}
Compilamos con GCC.
confused@opk:~/Desktop$ gcc buff.c -o buff
Y ejecutamos ./buff `perl -e "print 'O'x100"`
(la invocacion del perl que imprime 100 veces la letra O, es para no escribir mas de 40 veces un caracter manualmente, aunque pueden hacerlo tranquilamente, ./buff 00000000000....y asi hasta una considerable carga de caracteres arriba de 40 bytes) pero piensen que en una aplicacion de verdad tendran que ingresar mas de 1.000 bytes generalmente y es un dolor hacerlo manualmente.
Bueno al ejecutar nos devolvio "Violacion de Segmento" y eso es lo que nos interesa!.
Esto se debe a que el buffer fue definido por el programador con un total maximo de 40 y si logicamente le metemos 100 al invocar perl, desbordaria por mas del doble de caracteres ingresados.
Como esto simplemente es para comprender los conceptos, la accion la haremos mas adelante..
# Que es Heap Overflow?
Bueno una vez que tenemos conocimientos sobre el BOF (Buffer Overflow) o comprendemos de que trata realmente.. podemos decir que el HEAP OVERFLOW es una derivacion del BOF, pero este tiene la caracteristica de producirse en una zona determinada de la memoria llamada HEAP.
Este termino significa un 'monton'/'porcion' de memoria o tambien conocida como 'memoria dinamica' o 'monticulo'.
Cuando se ejecuta un programa el SO lo primero que hace es copiar y pegar todo el codigo del programa en una zona de memoria que este vacia/libre ademas de reservar espacio extra para la ejecucion de dicho programa:
*Entre ese espacio extra, se encuentra una zona de datos donde se guardaran las variables globales y las constantes.
*Una zona para las call stack o llamadas de pila donde almacena los parametros de las funciones, variables locales, y valores de Retorno...
*Y una zona para la memoria dinamica [HEAP] que es la memoria solicitada para la ejecucion del programa.
Veamos un ejemplo de un sencillo Heap Overflow:
Código
Code (c):#include
#include
#include
int main(int argc, char *argv[]) {
char *bufferA = malloc (40);
int *acceso = malloc(sizeof(int));
*acceso = 0;
strncpy(bufferA, argv[1], strlen(argv[1]));
if (*acceso!=0) {
printf ("Overflow!\n");
} else {
printf ("No paso nada\n");
}
return (0);
}
Compilamos:
gcc heap.c -o heap
Y ejecutamos de la siguiente manera ./heap [algunValor]
Como respuesta obtenemos "No paso nada"..
Como vemos el programa pide un dato que sera ingresado por el usuario el cual cuya memoria fue reservada con malloc().
Pero logicamente vemos que pide 40 bytes de memoria reservada y si invocamos a perl nuevamente e ingresamos varios caracteres que sobrepasen la memoria reservada veamos le resultado.
./heap `perl -e "print 'O' x100"`
Y vemos que nos responde lo que queriamos ver
Para ir finalizando explicare la tercer terminologia conocida como Stack Overflow, espero no aburrirlos.
# Que es el Stack Overflow?
Lo primero con lo que debemos manejarnos es con el termino "stack", este termino viene de "PILA". Claramente como la Pila de libros, donde todos los libros estan montados unos arriba del otro y forma una pila... bueno eso es.. tambien podemos pensarlo como un MAZO DE CARTAS, el cual todas las cartas son apiladas.. y el modo de acceso a esas cartas es lo que se conoce en ingles como LIFO -Last in first out- / Ultimo entrado, primero salido. Bien... imaginense que es un mazo de cartas, donde el ancho de espada lo ponemos arriba de la pila, y luego para acceder a una carta debajo de esta, primero tenemos que sacar el ancho de espada y luego sacar si la segunda carta de la pila....
Esto seguramente sera visto mas a futuro con un curso de assembler que tenemos pensado con snf, pero bueno de momento, me conformo con que sepan que una pila, stack no es mas que una estructura de datos, apilado uno arriba del otro y que para usar la 2da posicion debemos primero quitar la primera siempre...
Bueno a continuacion explicare en que consta el stack overflow con un ejemplo similar al anterior supongo que ya se lo imaginaran conociendo el concepto de overflow.
Al mismo vaso de agua de capacidad limitada y a tope, le cargamos mas agua? resultado? Desbordamiento...
Veamos este code:
Código
Code (c):#include
#include
int main(void) {
char buffer1[16], buffer2[46]; // declaramos 2 buffers el 2do claramente mas grande.
memset(buffer2, 'Z', sizeof(buffer2)-1); // rellenamos con 45 veces con Z
strcpy(buffer1, buffer2); // copiamos el buffer2 con las Zetas, a el buffer1
return 0; // retornamos 0
}
Bien, como siempre, compilamos con nuestro querido GCC
$ gcc a.c -o a
luego ejecutamos:
$ ./a
El tan preciado 'Violacion de Segmento' ha aparecido.
Claramente aparecio porque cuando copiamos el contenido de buffer2 a buffer1 este desborda de informacion, ya que tan solo tiene un limite de 16 lugares... y buffer2 un container de Zetas :p.
Bien, la pregunta ahora es una ves que desborda termina ahi?... la respuesta es claramente que depende nuestros objetivos NO!.
Veamos habiamos hablado un poco de la STACK/PILA del sistema y habiamos dicho que esta podiamos imaginarla como un mazo de cartas! o una pila de libros. Bien.. supongamos que tenemos algo asi relacionando con el code desbordado.
STACK............................buffer2 [contiene las ZZZZZZZ....]
STACK............................buffer1 [por el momento esta vacio, todavia no copiamos]
Y debajo estan los registros EBP & EIP con ciertos valores...
Ahora una vez que el strcpy es ejecutado, tendriamos un panorama asi en la stack.
STACK............................buffer2 [(45z)zzzzzzzzzzzzzzzzzzzz...]
STACK............................buffer1 [zzzzzzzz zzzzzzzz zzzzzzzz] y las que sobran caen en ebp & eip
STACK............................ahora valen EBP=0x5A5A5A5A EIP=0x5A5A5A5A
Valen 0x5A5A5A5A porque cada direccion es de 4bytes y 5A en hexadecimal es Z.
Esto pasa porque como el buffer1 no tenia capacidad a tantas lluvias de Zetas, se paso del limite y sobreescribio estos dos registros que nombre.
EIP es un registro que contiene la direccion de la instruccion que el programa va a devolver al finalizar este...entonces el programa desborda y al caer las Z en el registro EIP, este al finalizar intenta ejecutar lo que se encuentra en 0x52525252
pero como no hay nada, nos arroja el famoso Violacion de Segmento.
Comprobemos con un ejemplo con my friend Ollydbg aver que sucede y que movimiento hace:
Al correrlo, y parar en la funcion strcpy vemos que sucede en el registro:
Vemos como ahora EBP y EIP pasan a valer Z es decir 0x5A5A5A5A
Ahi tenemos una clara imagen de lo que es la PILA. Y tambien vemos como esta sobreescrita por las Z insertadas.
Y si vemos las direcciones del dump, ahi nos muestra las zetas en sus respectivas posiciones en memoria.
Espero que haya ayudado a iniciarse mejor con los conceptos de overflow.
Saludos, cualquier consulta, son libres de hacerla!
0 comentarios:
Publicar un comentario