# Stack Overflow {{#include ../../banners/hacktricks-training.md}} ## Czym jest Stack Overflow **Stack overflow** to luka, która występuje, gdy program zapisuje więcej danych na stosie, niż jest w stanie pomieścić. Te nadmiarowe dane **nadpiszą sąsiednią przestrzeń pamięci**, prowadząc do uszkodzenia ważnych danych, zakłócenia przepływu sterowania i potencjalnie do wykonania złośliwego kodu. Problem ten często pojawia się z powodu użycia niebezpiecznych funkcji, które nie wykonują sprawdzania granic na wejściu. Głównym problemem tego nadpisania jest to, że **zapisany wskaźnik instrukcji (EIP/RIP)** oraz **zapisany wskaźnik bazowy (EBP/RBP)** do powrotu do poprzedniej funkcji są **przechowywane na stosie**. Dlatego atakujący będzie w stanie je nadpisać i **kontrolować przepływ wykonania programu**. Luka ta zazwyczaj pojawia się, ponieważ funkcja **kopiuje na stos więcej bajtów niż ilość przydzielona dla niej**, co pozwala na nadpisanie innych części stosu. Niektóre powszechne funkcje podatne na to to: **`strcpy`, `strcat`, `sprintf`, `gets`**... Ponadto funkcje takie jak **`fgets`**, **`read` & `memcpy`**, które przyjmują **argument długości**, mogą być używane w sposób podatny, jeśli określona długość jest większa niż przydzielona. Na przykład, następujące funkcje mogą być podatne: ```c void vulnerable() { char buffer[128]; printf("Enter some text: "); gets(buffer); // This is where the vulnerability lies printf("You entered: %s\n", buffer); } ``` ### Znajdowanie przesunięć Stack Overflow Najczęstszym sposobem na znalezienie przesunięć stack overflow jest podanie bardzo dużego wejścia z `A`s (np. `python3 -c 'print("A"*1000)'`) i oczekiwanie na `Segmentation Fault`, co wskazuje, że **adres `0x41414141` próbował być dostępny**. Ponadto, gdy już znajdziesz, że istnieje luka w Stack Overflow, będziesz musiał znaleźć przesunięcie, aż będzie możliwe **nadpisanie adresu powrotu**, do tego zazwyczaj używa się **sekwencji De Bruijn.** Która dla danego alfabetu o rozmiarze _k_ i podsekwencji o długości _n_ jest **cykliczną sekwencją, w której każda możliwa podsekwencja o długości \_n**\_\*\* występuje dokładnie raz\*\* jako ciągła podsekwencja. W ten sposób, zamiast ręcznie ustalać, które przesunięcie jest potrzebne do kontrolowania EIP, można użyć jako wypełnienia jednej z tych sekwencji, a następnie znaleźć przesunięcie bajtów, które zakończyły nadpisanie. Można użyć **pwntools** do tego: ```python from pwn import * # Generate a De Bruijn sequence of length 1000 with an alphabet size of 256 (byte values) pattern = cyclic(1000) # This is an example value that you'd have found in the EIP/IP register upon crash eip_value = p32(0x6161616c) offset = cyclic_find(eip_value) # Finds the offset of the sequence in the De Bruijn pattern print(f"The offset is: {offset}") ``` lub **GEF**: ```bash #Patterns pattern create 200 #Generate length 200 pattern pattern search "avaaawaa" #Search for the offset of that substring pattern search $rsp #Search the offset given the content of $rsp ``` ## Wykorzystywanie przepełnień stosu Podczas przepełnienia (zakładając, że rozmiar przepełnienia jest wystarczająco duży) będziesz w stanie **nadpisać** wartości lokalnych zmiennych w stosie, aż do osiągnięcia zapisanych **EBP/RBP i EIP/RIP (lub nawet więcej)**.\ Najczęstszym sposobem nadużywania tego typu podatności jest **modyfikacja adresu powrotu**, aby po zakończeniu funkcji **przepływ kontroli został przekierowany tam, gdzie użytkownik wskazał** w tym wskaźniku. Jednak w innych scenariuszach może wystarczyć tylko **nadpisanie niektórych wartości zmiennych w stosie** do wykorzystania podatności (jak w łatwych wyzwaniach CTF). ### Ret2win W tego typu wyzwaniach CTF, istnieje **funkcja** **wewnątrz** binarnego, która **nigdy nie jest wywoływana** i którą **musisz wywołać, aby wygrać**. W tych wyzwaniach musisz tylko znaleźć **offset do nadpisania adresu powrotu** i **znaleźć adres funkcji**, którą chcesz wywołać (zwykle [**ASLR**](../common-binary-protections-and-bypasses/aslr/) będzie wyłączony), aby po powrocie z funkcji podatnej, ukryta funkcja została wywołana: {{#ref}} ret2win/ {{#endref}} ### Shellcode na stosie W tym scenariuszu atakujący mógłby umieścić shellcode w stosie i nadużyć kontrolowanego EIP/RIP, aby skoczyć do shellcode i wykonać dowolny kod: {{#ref}} stack-shellcode/ {{#endref}} ### Techniki ROP i Ret2... Ta technika jest podstawowym frameworkiem do obejścia głównej ochrony poprzedniej techniki: **Brak wykonywalnego stosu (NX)**. Umożliwia to wykonanie kilku innych technik (ret2lib, ret2syscall...), które zakończą się wykonaniem dowolnych poleceń poprzez nadużycie istniejących instrukcji w binarnym: {{#ref}} ../rop-return-oriented-programing/ {{#endref}} ## Przepełnienia sterty Przepełnienie nie zawsze będzie miało miejsce w stosie, może również wystąpić w **stercie**, na przykład: {{#ref}} ../libc-heap/heap-overflow.md {{#endref}} ## Rodzaje ochrony Istnieje kilka ochron próbujących zapobiec wykorzystaniu podatności, sprawdź je w: {{#ref}} ../common-binary-protections-and-bypasses/ {{#endref}} {{#include ../../banners/hacktricks-training.md}}