BlogWonderHowTo

Tutorial de C orientado a la seguridad 0x0F – Funciones Parte III: La pila

Bienvenido de nuevo a otro tutorial sobre funciones. La última vez, miramos dentro de la memoria para ver cómo se veían las funciones en la carne y todo ese ensamblaje fue bastante desagradable. Al menos tienes algo de exposición. Esta vez, examinaremos cómo funcionan las funciones con la pila.

Código de ejemplo

Recuperemos el código que usamos en el tutorial anterior.

Imagen vía wonderhowto.com

La ubicación de regreso

Así que les expliqué varias veces sobre el regreso. Sabemos que devuelve el control al llamador de la función y también sabemos que puede devolver un valor, pero aún no estamos seguros de cómo sabe dónde debe regresar. Compilemos y depuremos para ver cómo funciona todo.

Compilación y depuración

En primer lugar, requerimos puntos de interrupción para pausar el programa para que podamos ver lo que está sucediendo en esos momentos. Rompemos en la línea 15 antes de llamar a la función y en la línea 7 dentro de la función. Luego compararemos las diferencias en la pila para ver si algo cambió.

En el tutorial anterior, vimos que dos valores se movieron a la pila durante el análisis de funciones de main y, como podemos ver, ambos están allí. Continuemos en el agregar función e imprima la pila de nuevo.

Al hacer coincidir las direcciones, podemos ver nuestras variables num1 y num2 otra vez. Pero, ¿qué es esto en rojo? Parece extrañamente familiar … ¡Oh, sé de dónde vino eso! Traigamos la imagen de volcado de ensamblador de main del último tutorial.

Tenemos dos direcciones coincidentes, una en la pila y otra dentro de la función principal del segmento de código. De vuelta en la introducción a las funciones, dije Luego procederá a saltar la ejecución a la ubicación guardada de la siguiente instrucción en la función que la llamó. Bueno, ahora conocemos su truco de magia. Durante la llamada de una función, la persona que llama inserta su siguiente ubicación de instrucción en la pila de modo que cuando la persona que llama termine, ESP aparecerá (eliminará de la parte superior de la pila) de todos sus datos y cuando la retirado se llama a la instrucción, el flujo de ejecución utilizará esa dirección para encontrar a dónde debe ir. Pero espera … Vimos otro par de nuestras variables num1 y num2 de nuevo, ¿no? Los dos valores justo antes de la dirección de retorno …

Argumentos de función

De vuelta en el Tutorial 0x0D, había explicado sobre las funciones y sus argumentos. Cuando se llama a una función, la persona que llama pasa sus propias variables y / o valores al destinatario mediante proceso de copiar y colocarlos en la parte superior de la pila para que el destinatario ahora tenga sus propias variables, que se denominan como las nombró en el paréntesis de la definición de la función. En este caso, num1 y num2 se copiaron, presionaron (para colocar en la parte superior de la pila) y se almacenaron como variables a y B en agregar.

Depuración

Veamos esa pila de nuevo …

¡Allí mismo, en el azul! Así que no estábamos alucinando, ¡realmente está ahí! Antes de que se envíe la dirección de retorno, requerimos los parámetros de la función del destinatario (a y B), por lo que, como ya he dicho un par de veces, la persona que llama inserta sus valores en la pila para que tenga un Copiar de su propia. Fíjate cómo he estado poniendo la palabra en negrita Copiar cada vez que escribí en los últimos tutoriales. Es un Copiar, no el valor original real. Si cambia las variables en la función del destinatario, se no cambie los valores en el llamador a menos que devuelva y guarde explícitamente el valor. Lo que también es interesante es en qué orden se introducen los valores. Si echas un vistazo, nuestro primer parámetro es num1 y nuestro segundo es num2 pero en la pila, ¡es al revés! La razón de esto es que las funciones (como printf) con algo llamado argumentos variables puede ser compatible *. Intentemos experimentar.

*Desde Continuación de las subrutinas: Pasar argumentos, devolver valores y asignar variables locales, 2015, Prof. Moshovos, A., Ingeniería informática y eléctrica de la Universidad de Toronto

Código de ejemplo

Esta vez, le hemos dado la intercambio función a vacío valor de retorno, lo que significa que no devuelve nada. Si este es el caso, no regreso se requiere llamada. num1 y num2 se pasan al intercambio funcionar de nuevo, al igual que el agregar función en el código anterior solo ahora, hemos establecido los dos valores en números diferentes. Obviamente, como ya lo he explicado, sabemos que los valores no cambiarán.

Compilación y ejecución

Como se esperaba.

Conclusión

Casi hemos terminado con las funciones, probablemente habrá dos tutoriales más sobre este tema, pero lo dejaré descansar ahora porque hay otras cosas que debemos saber antes de llegar allí. Recuerde revisar el contenido, tratar de comprender completamente lo que está sucediendo y tal vez podamos traer otro método de explotación con la vulnerabilidad de desbordamiento de búfer. ¡Gracias por leer!

dtm.

Publicaciones relacionadas

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Mira también
Cerrar
Botón volver arriba
Cerrar