news 2026/10/8 19:03:06

如何防范缓冲区溢出?Coursebook编译器保护与编码规范

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
如何防范缓冲区溢出?Coursebook编译器保护与编码规范

如何防范缓冲区溢出?Coursebook编译器保护与编码规范

【免费下载链接】coursebookOpen Source Introductory Systems Programming Textbook for the University of Illinois项目地址: https://gitcode.com/GitHub_Trending/co/coursebook

缓冲区溢出(Buffer Overflow)是系统编程中最危险的漏洞之一——攻击者只需让一段超长字符串写越界,就可能劫持程序的控制流。开源教材Coursebook(伊利诺伊大学 CS 341 系统编程课程的官方教科书)用大量真实案例,讲透了缓冲区溢出的成因、编译器内置的 4 层保护机制,以及 C 语言编码规范中必须遵守的 5 条防溢出守则。无论你是 C 语言新手还是想补上系统安全一课的开发者,这篇指南都能帮你快速建立防线。

为什么缓冲区溢出如此危险?

C 语言在数组和字符串操作上不做任何边界检查。当你用strcpy把一段过长的字符串复制进固定大小的缓冲区时,多出的字节会直接覆盖相邻的内存——通常是函数的返回地址。

教材在安全章节给出的经典场景:一个greeting函数把命令行参数strcpy进 32 字节的缓冲区,传入超长字符串后程序段错误;而若攻击者精心构造字节,甚至可能让程序跳转到恶意代码,直接拿到 shell。更著名的现实案例是Heartbleed——一次向不足大小缓冲区执行memcpy就造成了影响全球的灾难。

缓冲区溢出的细节在教材中有多处剖析:

  • 安全章节(栈破坏与缓冲区溢出):security/security.tex
  • 常见 Bug 章节(溢出/下溢、字符串少加 1 字节):introc/common_bugs.tex
  • 常见 C 函数章节(gets为何被废弃):introc/common_c_functions.tex

编译器与操作系统的 4 道自动防线 🛡️

好消息是:只要你用现代编译器正常构建,多数基础溢出攻击会默认被拦截。教材在"操作系统安全"一节中系统梳理了 4 道防线,全部默认开启:

1️⃣ 栈保护(Stack Canaries / 金丝雀)

编译器默认会在每个函数栈帧中埋入一个秘密值——"金丝雀"。只要缓冲区溢出破坏了这个值,运行时就会中止程序并报告"stack smashing detected"。这正是教材示例中必须加-fno-stack-protector才能演示溢出的原因。

2️⃣ 地址空间布局随机化(ASLR)

ASLR 让可执行文件基址、栈、堆和共享库的位置在每次运行时都随机变化。没有它,攻击者可以稳定地定位 libc 函数地址做 return-to-libc 攻击;有了它,敏感数据的位置必须靠猜。

3️⃣ 数据执行保护(DEP / NX)

内存页只能"可写"或"可执行",不能两者兼得。攻击者把恶意代码写进栈或堆后无法执行,直接掐断了最常见的溢出利用路径。

4️⃣ 最小权限与沙箱

POSIX 权限、进程能力(capabilities)、AppArmor 等机制限制了被攻破程序的破坏范围,是最后一道兜底。

过程与内存空间的划分原理可参考教材 IPC 章节的地址空间图示:ipc/ipc.tex

缓冲区溢出防护:5 条 C 编码规范 ✅

自动防线挡不住一切,编码习惯才是真正的根除手段。教材的"常见 Bug"与"常见 C 函数"章节总结了 5 条守则:

#规范要点
1永不用gets无法控制读取长度,C11 已将其彻底移除;改用fgets(buffer, sizeof(buffer), stdin)或getline
2用有界拷贝函数优先strncpy/strlcpy(OpenBSD),复制前确认目标缓冲区容量
3字符串预留strlen(s) + 1字节别忘了结尾的\0空字符,少 1 字节就是溢出
4警惕循环边界下溢for (i = N; i >= 0; i--)会写出array[N]越界,且int i永不为负
5按类型完整大小分配malloc(sizeof(struct User))而不是sizeof(指针),分配不足会悄悄腐蚀相邻内存

一个新手最容易踩的坑:fscanf/gets把输入读入char in[10],而它旁边的char out[10]立刻被污染——输入hellloooooooo后输出竟然变成aoo。记住:凡是从外部来源读数据,先问"它会不会比缓冲区大"。

延伸阅读:教材中的缓冲区溢出相关资料 📚

  • 完整安全章节(栈破坏、缓冲区溢出、Spectre、ASLR/DEP):security/security.tex
  • 常见 C 语言 Bug 清单(含 Heartbleed 案例):introc/common_bugs.tex
  • 标准输入函数与fgets安全用法:introc/common_c_functions.tex
  • C 内存模型(理解溢出为何能破坏相邻变量):introc/c_memory_model.tex

小结

防范缓冲区溢出的正确姿势是"双保险":

  1. 信任但不依赖自动防线——栈金丝雀、ASLR、DEP 会拦下多数攻击,但不要为了"方便演示"关闭它们;
  2. 把边界检查写进每一行代码——用fgets替代gets、用有界字符串函数、永远为字符串多留 1 字节。

按照 Coursebook 的这 5 条规范写 C 代码,你就已经挡住了绝大多数缓冲区溢出漏洞。💪

【免费下载链接】coursebookOpen Source Introductory Systems Programming Textbook for the University of Illinois项目地址: https://gitcode.com/GitHub_Trending/co/coursebook

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/8 18:59:56

你是否听说过C10K 问题?

1. 来源:这个名词是怎么来的 C10K Concurrent 10,000,意思是"单台服务器同时支撑一万个连接"。 这个说法来自 Dan Kegel 在 1999 年整理的一份文档,标题就叫《The C10K problem》。它把当时各种操作系统和编程模型的做法汇总在一起…

作者头像 李华
网站建设 2026/10/8 18:57:15

Context Is All You Need:读千问办公CEO陈宇森2026云栖演讲

基于 2026 云栖大会技术主论坛MaaS & Agent 演讲《千问办公:Context Is All You Need》 演讲人:阿里巴巴集团副总裁、千问办公 CEO 陈宇森 视频源:Bilibili BV1K1hE6VEhq 核心论断:大模型参数狂飙的阶段过去后,企…

作者头像 李华
网站建设 2026/10/8 18:55:17

每天十分钟跟上 AI 进展:InBrief 的三块信息与用法

先说清楚这篇是写给谁的。如果你在做 AI 相关的研发、产品或投资,想用很少的时间知道"从昨天到今天发生了什么",这篇会有用;如果你要找的是其他行业的新闻,InBrief 不覆盖,这一点我放在最前面讲。 我为什么…

作者头像 李华
网站建设 2026/10/8 18:55:15

「AI 说」单机版三体人:孤独的终极形态

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/8 18:55:14

CS-144 checkpoint 0: networking warmup

Writing a network program using an OS stream socket 2026-10-07 完成 checkpoint 0 的第一部分:用 OS 提供的 stream socket 写一个最小化的 HTTP 客户端 webget。 实验目标 Checkpoint 0 是整个 CS144 的热身关,目标有两个层次: 表层&…

作者头像 李华
网站建设 2026/10/8 18:54:35

py -m venv .venv py : 无法将“py”项识别为 cmdlet、

py -m venv .venv py : 无法将“py”项识别为 cmdlet、PS C:\Users\Administrator> py -m venv .venv py : 无法将“py”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然 后再试一次…

作者头像 李华