# Stack Overflow {{#include ../../banners/hacktricks-training.md}} ## Cos'è uno Stack Overflow Un **stack overflow** è una vulnerabilità che si verifica quando un programma scrive più dati nello stack di quanti ne siano allocati per contenerli. Questi dati in eccesso **sovrascriveranno lo spazio di memoria adiacente**, portando alla corruzione di dati validi, alla disruption del flusso di controllo e potenzialmente all'esecuzione di codice malevolo. Questo problema si verifica spesso a causa dell'uso di funzioni non sicure che non eseguono il controllo dei limiti sugli input. Il problema principale di questa sovrascrittura è che il **puntatore di istruzione salvato (EIP/RIP)** e il **puntatore di base salvato (EBP/RBP)** per tornare alla funzione precedente sono **memorizzati nello stack**. Pertanto, un attaccante sarà in grado di sovrascrivere questi e **controllare il flusso di esecuzione del programma**. La vulnerabilità di solito si verifica perché una funzione **copia nello stack più byte della quantità allocata per essa**, riuscendo quindi a sovrascrivere altre parti dello stack. Alcune funzioni comuni vulnerabili a questo sono: **`strcpy`, `strcat`, `sprintf`, `gets`**... Inoltre, funzioni come **`fgets`**, **`read` & `memcpy`** che prendono un **argomento di lunghezza**, potrebbero essere utilizzate in modo vulnerabile se la lunghezza specificata è maggiore di quella allocata. Ad esempio, le seguenti funzioni potrebbero essere vulnerabili: ```c void vulnerable() { char buffer[128]; printf("Enter some text: "); gets(buffer); // This is where the vulnerability lies printf("You entered: %s\n", buffer); } ``` ### Trovare gli offset degli Stack Overflow Il modo più comune per trovare gli stack overflow è fornire un input molto grande di `A`s (ad esempio `python3 -c 'print("A"*1000)'`) e aspettarsi un `Segmentation Fault` che indica che l'**indirizzo `0x41414141` è stato tentato di essere accesso**. Inoltre, una volta trovata la vulnerabilità di Stack Overflow, sarà necessario trovare l'offset fino a quando non sarà possibile **sovrascrivere l'indirizzo di ritorno**, per questo si usa solitamente una **sequenza di De Bruijn.** Che per un dato alfabeto di dimensione _k_ e sottosequenze di lunghezza _n_ è una **sequenza ciclica in cui ogni possibile sottosequenza di lunghezza \_n**\_\*\* appare esattamente una volta\*\* come sottosequenza contigua. In questo modo, invece di dover capire manualmente quale offset è necessario per controllare l'EIP, è possibile utilizzare come padding una di queste sequenze e poi trovare l'offset dei byte che hanno finito per sovrascriverlo. È possibile utilizzare **pwntools** per questo: ```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}") ``` o **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 ``` ## Sfruttamento degli Stack Overflow Durante un overflow (supponendo che la dimensione dell'overflow sia abbastanza grande) sarai in grado di **sovrascrivere** i valori delle variabili locali all'interno dello stack fino a raggiungere il **EBP/RBP e EIP/RIP salvati (o anche di più)**.\ Il modo più comune per abusare di questo tipo di vulnerabilità è **modificare l'indirizzo di ritorno** in modo che, quando la funzione termina, il **flusso di controllo venga reindirizzato ovunque l'utente abbia specificato** in questo puntatore. Tuttavia, in altri scenari, potrebbe essere sufficiente **sovrascrivere alcuni valori delle variabili nello stack** per l'exploitation (come in semplici sfide CTF). ### Ret2win In questo tipo di sfide CTF, c'è una **funzione** **all'interno** del binario che **non viene mai chiamata** e che **devi chiamare per vincere**. Per queste sfide devi solo trovare l'**offset per sovrascrivere l'indirizzo di ritorno** e **trovare l'indirizzo della funzione** da chiamare (di solito [**ASLR**](../common-binary-protections-and-bypasses/aslr/) sarebbe disabilitato) in modo che, quando la funzione vulnerabile restituisce, la funzione nascosta venga chiamata: {{#ref}} ret2win/ {{#endref}} ### Stack Shellcode In questo scenario, l'attaccante potrebbe posizionare uno shellcode nello stack e abusare dell'EIP/RIP controllato per saltare allo shellcode ed eseguire codice arbitrario: {{#ref}} stack-shellcode/ {{#endref}} ### Tecniche ROP & Ret2... Questa tecnica è il framework fondamentale per bypassare la principale protezione della tecnica precedente: **Stack non eseguibile (NX)**. E consente di eseguire diverse altre tecniche (ret2lib, ret2syscall...) che porteranno all'esecuzione di comandi arbitrari abusando delle istruzioni esistenti nel binario: {{#ref}} ../rop-return-oriented-programing/ {{#endref}} ## Heap Overflows Un overflow non sarà sempre nello stack, potrebbe anche essere nell'**heap**, per esempio: {{#ref}} ../libc-heap/heap-overflow.md {{#endref}} ## Tipi di protezioni Ci sono diverse protezioni che cercano di prevenire l'exploitation delle vulnerabilità, controllale in: {{#ref}} ../common-binary-protections-and-bypasses/ {{#endref}} {{#include ../../banners/hacktricks-training.md}}