Bestiario de una memoria mal gestionada (II)

David García    21 abril, 2020
Bestiario de una memoria mal gestionada (II)

Si tuviéramos que elegir una vulnerabilidad especialmente dañina sería, con mucha probabilidad, la ejecución de código arbitrario, y más aún si puede ser explotada en remoto. En la entrada anterior introdujimos los problemas que puede acarrear una memoria mal gestionada. Ahora vemos ejemplos concretos.

Double free, un ejemplo básico

Este fallo ocurre cuando liberamos dos veces un mismo bloque de memoria reservada. Veamos un programa que lo hace “bien”:

Reservamos dos bloques, copiamos sendas cadenas en ellos y son liberados a medida que ya no los necesitamos (observar las llamadas a ‘free’). Veamos la ejecución:

Todo correcto, ahora vamos a cometer a drede el desliz de liberar el bloque que ya habíamos liberado. Esto no demuestra la vulnerabilidad en sí (que es más compleja de explotar), sino comprobar qué ocurre cuando lo hacemos mal en las estructuras de memoria dinámica del montículo.

Ejecutemos y veamos qué ocurre:

Como vemos, no se ha imprimido la segunda cadena en el terminal, como sí ocurrió en el programa anterior. ¿Qué ha pasado?

Al liberar un bloque del heap, se ha quedado libre este hueco. Hemos requerido otro hueco para la variable p2 y nos han asignado otro bloque, pero recordemos que p1 aunque se haya liberado, apunta todavía a su bloque original… que ahora pertenece a p2.

Como volvemos a liberar p por segunda vez, lo que hacemos en realidad es liberar memoria que está utilizando otro puntero que no está relacionado con el objeto p. El uso de p2 se vuelve inestable ya que estamos utilizando una región de memoria que ya está liberada. Veamos cómo estaban formadas las direcciones de memoria:

Como vemos, p2 toma la dirección del bloque que ya tenía p, pero este ha sido liberado. Veamos la misma situación, pero liberando los dos bloques al final de la función:

Bien manejada la situación, ambos punteros apuntan a bloques diferentes, no se liberan los recursos a destiempo y todo transcurre como estaba previsto.

Repetimos. La gestión manual de la memoria es compleja, muy compleja. Se debe prestar atención al orden de operaciones, dónde se obtienen recursos y dónde dejamos de usarlos para poder liberarlos en buenas condiciones.


No te pierdas la serie completa de este artículo:

Deja un comentario

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