[FADB] 1. La Pila

FUNDAMENTOS DE LOS ATAQUES POR DESBORDAMIENTO DE BUFFER

Un programa se divide generalmente en tres partes: el código, los datos y la pila. La parte de código contiene las instrucciones a ejecutar por parte de la CPU y suele ser de sólo lectura. La sección de datos contiene los datos iniciales del programa, así como el espacio reservado para las variables declaradas globales. La pila se utiliza para guardar valores temporales (como las variables locales).

Las instrucciones PUSH y POP de las CPU Intel x86 permiten hacer uso automático de la pila. PUSH mete un dato en la pila y POP saca un dato de la pila. Un registro llamado ESP (Extended Stack Pointer) contiene la dirección actual de la cima de la pila. La pila funciona creciendo hacia las direcciones bajas de memoria.

Si por ejemplo tenemos el siguiente código:

PUSH EAX
PUSH EBX
POP EBX
POP EAX

con ESP = 0x00000100 (0x significa que el número que sigue está dado en hexadecimal), EAX = 0xAABBAABB y EBX = 0x11AA11AA.


Al ejecutar la primera instrucción (PUSH EAX), la CPU decrementa ESP en 4 (siempre se decrementan 4, que corresponden a 4 posiciones de memoria, es decir, 4 bytes, una palabra de 32 bits), con lo que ESP = 0x000000FC, y copia EAX en la dirección apuntada por ESP, es decir 0x000000FC. A este proceso es lo que llamamos meter en la pila. Por lo tanto la memoria queda tal que así:

0x0000010 -> ??
0x000000FF -> AA
0x000000FE -> BB
0x000000FD -> AA
0x000000FC -> BB
0x000000FB -> ??

Las CPUs Intel x86 funcionan en low-endian, es decir, que el byte menos significativo se almacena en la dirección de memoria más baja. Con la siguiente instrucción, PUSH EBX, ocurre exactamente los mismo. Tenemos que ESP = 0x000000F8 y la pila queda como sigue:

0x00000100 -> ??
0x000000FF -> AA
0x000000FE -> BB
0x000000FD -> AA
0x000000FC -> BB
0x000000FB -> 11
0x000000FA -> AA
0x000000F9 -> 11
0x000000F8 -> AA
0x000000F7 -> ??

Ahora bien, la instrucción siguiente, POP EBX, realiza el proceso contrario: primero extrae (4 bytes) lo apuntado por ESP al registro especificado, en este caso EBX = 11AA11AA, y suma 4 a ESP, que nos deja con ESP = 0x000000FC y el mismo mapa de memoria que arriba. Esto se le denomina sacar de la pila. Los datos que se han sacado de la pila no son borrados, sólo se modifica ESP. POP EAX hace lo mismo: copia los 4 bytes apuntados por ESP (0xAABBAABB) a EAX, y luego suma 4 a ESP, que se queda como ESP = 0x00000100.

A la pila se la denomina una estructura de datos LIFO (Last Input First Output), es decir, el útlimo en meterse es el primero en salir. Efectivamente, el último PUSH fue el de EBX y el primer POP el de éste. En caso de que el código fuera

PUSH EAX
PUSH EBX
POP EAX
POP EBX

acabaríamos con EAX = 11AA11AA y EBX = AABBAABB, es decir, intercambiaríamos los valores de ambos registros. Como su nombre indica (LIFO), el primer dato en sacarse es el último en haberse metido.

Comments

Popular Posts