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

Ubuntu 23.04中scanf触发Segmentation Fault的原因及学习路径

问题原因分析

你的代码存在明确的缓冲区溢出漏洞:char a[2]是仅能容纳2个字符(加上终止符\0的话是3字节)的数组,但scanf("%s", a)未限制输入长度,当输入AAchiching(共10个可见字符,加上自动添加的\0总长度为11字节)时,输入内容会超出a的缓冲区,覆盖栈上的其他数据。

两个Ubuntu版本出现差异的核心原因是系统组件版本及栈布局的变化:

  • Glibc版本差异:Ubuntu 23.04使用的Glibc版本远高于18.04,新版本的scanf实现对内存访问的检查更严格,溢出内容可能直接覆盖了栈帧的返回地址、栈基址等关键区域,导致函数执行时触发非法内存访问;而旧版本Glibc中,溢出内容仅覆盖了b数组,未触及栈帧的敏感部分,因此没有立即触发段错误。
  • 栈布局差异:不同版本的GCC编译生成的栈帧结构、变量排列顺序存在差异。在Ubuntu 23.04的编译结果中,a数组的位置更靠近栈帧的敏感区域,溢出后直接破坏了关键数据;而18.04的栈布局中,a和b的位置关系让溢出内容先覆盖b,未影响函数的正常执行流程。
  • 内存防护默认配置:即使你添加了-fno-stack-protector关闭栈保护,新版本系统在内存页权限、栈随机化等方面的默认配置更严格,溢出后更容易触发段错误。
深入学习渠道
  • 官方文档
    • 研读GCC官方手册,重点理解编译选项(如-fno-pie、-O0、-fno-stack-protector)对程序内存布局的影响,以及栈帧的生成规则。
    • 查阅Glibc的版本变更记录和stdio库文档,了解scanf等函数在不同版本中的实现细节差异。
  • 专业书籍
    • 《深入理解计算机系统》:系统讲解栈帧结构、缓冲区溢出、内存管理等底层原理,是理解这类问题的核心教材。
    • 《漏洞战争:软件漏洞分析精要》:深入剖析缓冲区溢出的利用方式、不同系统的防护机制,适合进阶学习。
  • 实践工具
    • 使用gdb调试,通过info frame、x/20x $rsp等命令对比两个系统中栈内存的布局差异,观察溢出前后的内存变化。
    • 用objdump -d chal查看编译后的汇编代码,分析不同版本中栈变量的排列和函数调用流程。
    • 借助readelf -l chal查看可执行文件的段权限,理解内存区域的访问控制规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 12:17:23