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

修改RSP栈指针:格式化字符串漏洞利用返回地址覆盖问题咨询

解决格式化字符串漏洞中返回地址错误覆盖的问题

看起来你混淆了格式化字符串漏洞和缓冲区溢出的payload构造逻辑,这正是导致返回地址被错误覆盖成0x909090909040089a的原因。我来帮你理清思路,一步步解决这个问题:

为什么你的当前payload会出错?

你现在写的'%24d' + '\x9a\x08\x40\x00\x90\x90\x90\x90\x90\x90ABCDEFGHIJJKLMNOPQRST'是缓冲区溢出的思路:试图填充固定字节数到返回地址位置,再覆盖地址。但格式化字符串漏洞的处理逻辑完全不同:%24d会被printf解析为格式化指令,输出一个宽度为24的十进制数(比如对应参数为0时,会输出23个空格+1个0,共24字节),而不是直接填充24字节的垃圾数据。后面的\x90和字符也会被直接输出,最终这些内容混杂在一起写入栈,导致返回地址被\x90字节污染。

正确的格式化字符串漏洞利用步骤(覆盖返回地址为0x40089a)

格式化字符串漏洞的核心是通过格式化指令(如%n)直接修改栈上的指定位置,而不是靠填充字节覆盖。下面是具体步骤:

1. 定位返回地址在参数列表中的偏移

首先要找到main函数返回地址在格式化参数中的位置。在GDB中输入以下payload来探测栈上的各个参数:

python -c "print '%p.'*20"

执行后,查看输出的一串指针,找到那个对应main返回地址的条目(通常是类似0x40xxxx或0x7ffffxxx的地址)。假设这个地址是第6个参数,那我们就用%6$p来引用它。

2. 构造写入payload

要把返回地址的值改成0x40089a,你需要:

  • 先把返回地址所在的栈内存地址(比如假设是0x7fffffffe018,64位程序下小端序为\x18\xe0\xff\xff\xff\x7f\x00\x00)放在payload开头,让它成为格式化字符串的一个参数。
  • 计算需要输出的字节数:因为%n会将当前已输出的字节数写入指定位置,所以我们需要让总输出字节数等于目标值0x40089a。假设开头的栈地址占了8字节,那么还需要输出0x40089a - 8 = 4196594字节。
  • 用格式化指令快速填充并写入:用%4196594c来填充所需字节,再用%1$lln(1$表示第一个参数,也就是我们放在开头的栈地址;lln表示写入8字节,适配64位程序)完成写入。

最终的payload命令类似:

python -c "print '\x18\xe0\xff\xff\xff\x7f\x00\x00' + '%4196594c%1$lln'"

注意事项

  • 如果是32位程序,目标地址0x40089a是32位,栈地址只需4字节,用%1$n即可(n写入4字节)。
  • 直接输出几十万字节可能效率很低,实际利用中通常会分阶段写入低4字节和高4字节,减少payload长度。

如果你其实是想做缓冲区溢出?

如果你的目标程序实际存在缓冲区溢出漏洞(比如用gets读取输入),那应该回到缓冲区溢出的payload逻辑:用纯垃圾数据填充到返回地址位置,再覆盖目标地址。正确的命令应该是:

# 64位程序:24字节垃圾 + 小端序的0x40089a + NOP sled + shellcode
python -c "print 'A'*24 + '\x9a\x08\x40\x00\x00\x00\x00\x00' + '\x90'*20 + '你的shellcode内容'"

这样就能精准覆盖返回地址为0x40089a,不会混入\x90字节。

内容的提问来源于stack exchange,提问作者re3el

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:12:59