miércoles, 18 de junio de 2014

Programación dirigida por retorno. (I) - La teoría

Antes de entrar en lo que es la Programación dirigida por retorno (en adelante la nombraré por sus siglas en inglés: Return Oriented Programming) vamos a refrescar un poco lo que es el el desbordamiento de buffer y su posible utilización para ejecutar código arbitrario.

En anteriores post hemos entrado en este tema a fondo  pero vamos a recordar un poco para quienes no sigan este blog en que consiste.


Buffer Overflow y sus contramedidas.


Consiste alterar mediante un bloque datos la información de la pila, introduciendo código y modificando una dirección de retorno para redirigirla a ese código introducido.

Los compiladores, desde hace tiempo, usan diversas técnicas para  luchar contra estos ataques. Sin entrar en detalles estas técnicas se suele basar en cargar en la pila encima de la dirección de retorno un valor aleatorio y también colocarlo en el heap de memoria. Antes de hacer el return se comprueba que ambos valores coinciden. Para más información aconsejo esta lectura.

El popular compilador gcc tiene también su opción para proteger el stack con la opción -fstack-protector.

Otra solución  ha sido la implantanción en los procesadores de un mecanismo que impidiera la ejecución de código ubicado en la pila. Esta solucion tiene varios nombres XD, NX según el fabricante de ordenadores y a veces se habla indistintamente de esta capacidad hardware con que el sistema operativo la use y hablamos de Data Execution Prevention que es una capacidad software del sistemo operativo que incluso puede simularse en procesadores sin NX.

El conocer un poco más estos mecanismos da para mucho y en este artículo, en lo que nos sirve nos hemos de quedar con la idea de que existe una proteccion que impide la ejecución de código desde la pila

Bien DEP, impide que se pueda ejecutar un código que previamente he metido de forma aviesa en la pila. Pero DEP no impide que coloque lo que quiera en la pila y por lo tanto no va a impedir que sobreescriba la dirección de retorno correcta por una de mi interés.
Lo único que tengo que hacer es que ese código que quiero de que ejecute no esté en la pila. Podemos hacer entonces dos cosas: llamar a un función que nos interese del sistema, por ejemplo construir una llamada al sistema  o bien podemos hacer que el retorno fuera a otro punto del programa comprometido con lo que estamos alterando su comportamiento.

Hasta aquí la teoría, en el siguiente post veremos mediante un sencillo ejemplo como simplemente alterando al dirección de retorno de una función podríamos comprometer sofisticados sistemas de verificación.





No hay comentarios:

Publicar un comentario