分类:编程与开发(programming)· 单视频深度解读
大多数程序员一辈子都在“内存安全”的债上过日子,只是自己不知道:你写的每一行越界代码、每一次没配平的 malloc/free,都是埋在程序里的雷。Low Level 频道的「coding in c until my program is unsafe」用 350 多万播放证明了一件事:把一段“看起来完全正常”的 C 代码,一步步推向危险区,比任何安全布道都更有说服力。本文替你把这条视频的知识拆开、溯源、审一遍——看完你不仅知道 C 是怎么“变坏”的,还会带走一套立刻能用的自保手段。
| 项目 | 内容 |
|---|---|
| 标题 | coding in c until my program is unsafe |
| 中文直译 | 用 C 写代码,直到我的程序变得不安全 |
| 频道 | Low Level(@LowLevelLearning) |
| 主理人 | Ed(安全工程师 / 软件安全研究员) |
| 播放量 | 3,513,465 次(据 2026-09-15 UTC 素材快照) |
| 频道体量 | 约 110 万订阅(据本站 2026 年 5 月频道盘点) |
| 发布日期 | 未采集到(据频道页面;素材快照未含此项) |
| 链接 | https://www.youtube.com/watch?v=oTEiQx88B2U |
Low Level 不是那种“动画科普”频道。主理人 Ed 是一名安全工程师,频道常年主打逆向工程、汇编语言与安全研究,镜头里最常见的画面就是一个终端窗口加现场敲代码。本站 2026 年 5 月的编程频道盘点曾把该频道归入“底层深潜”一档,评语是:把安全研究从“黑客的黑暗艺术”转化为每个程序员都该懂的底层知识。这条「coding in c until my program is unsafe」正是这种风格的代表作之一:不喊口号,直接演示。
视频的设定本身就是论点:标题里那个"until"(直到)是整条片子的灵魂——不是讲一个已经写坏的程序,而是直播“变坏的过程”。你亲眼看着一段人畜无害的 C 代码,在作者手下一级一级走上不安全的阶梯。按叙事顺序,这个实验对应五层主张:
主张一:不安全不是“写错了语法”,而是“语言契约里本来就有洞”。 C 给程序员的自由极大:指针可以指向任意地址,数组访问不做边界检查,栈和堆都交给你手工打理。视频的起点正是一个“完全符合直觉”的小程序——语法正确、编译零警告、跑起来结果也对。危险恰恰在于:它对,只是暂时对。C 标准从不承诺“越界访问会报错”,它只说那是“未定义行为”——可能崩溃,也可能什么都不发生。第三种情况才是噩梦的开始。
主张二:栈溢出的第一步,往往只是“踩到隔壁”。
实验最经典的一级台阶,是把超长数据写进一个固定大小的栈缓冲区。教科书式的桥段是:函数里有两个局部变量,一个是字符数组,一个是标志位(比如 admin = 0)。用户输入超长字符串,边界检查函数(gets()、strcpy() 这类“信任调用者”的老 API)原样灌入,数据漫过数组边界,恰好把旁边的 admin 改成了 1——攻击者没碰那行代码,却改掉了它的执行结果。视频用现场演示告诉你:内存里没有“变量边界”这回事,只有字节和地址。
主张三:继续溢出,就能改写“程序接下来去哪”。 栈帧里保存着函数返回地址——函数结束时 CPU 要跳回去的位置。如果溢出的数据足够长,攻击者就能把这个地址整个覆盖成自己想要的值,让程序跳去执行注入的指令。这就是“控制流劫持”,从 1988 年莫里斯蠕虫到今天绝大多数漏洞利用,核心套路三十多年没变过。视频把这层窗户纸捅破的意义在于:你会意识到崩溃是程序在保护你——真正危险的程序不崩溃,它安静地听别人的话。
主张四:堆侧的洞,比栈更隐蔽。
栈溢出好歹还“动静大”,堆上的错误则无声无息:free() 之后继续用(use-after-free,释放后使用)、同一块内存 free() 两次(双重释放)、申请了从不归还(内存泄漏)。这类问题的杀伤力在于“时序”:出错的那行代码和爆雷的那次分配,中间可能隔着几万次请求。现实中著名的“心脏出血”(Heartbleed,2014 年 OpenSSL 漏洞,导致全网私钥裸奔)本质上就是一次内存越读——读了一段本不该读的堆内存,把相邻数据连带泄了出去。
主张五:编译器不是你的敌人,但也不是你的保镖。 视频后半段会触及一个反直觉的事实:你显式越界,编译器给你生成危险代码,不算bug;你没越界,但代码里存在整数溢出、悬空指针、数据竞争,编译器却“合理地”把你没写的逻辑优化掉——这同样是未定义行为的合法后果。未定义行为是 C 的地基性妥协:它换来了编译器优化空间和极限性能,代价是把一整类正确性责任完整地甩给了人类。
1. 溢出攻击的“考古现场”。 缓冲区溢出作为攻击手法可考的起点是 1988 年的莫里斯蠕虫——它利用 fingerd 服务的栈溢出感染了当时互联网上约十分之一的机器,这一事件直接催生了现代计算机应急响应体系(CERT/CC)。1996 年,Aleph One 在传奇黑客刊物 Phrack 第 49 期发表《Smashing the Stack for Fun and Profit》,第一次系统性地向公众讲清栈溢出原理,成为此后二十余年安全课程的默认第一课。视频里的演示,就是这堂老课的现代重播版。
2. 标准层的“亡羊补牢”。 gets() 是最臭名昭著的边界函数——它根本不接收长度参数,想防溢出在物理上不可能。C99 把它标记为弃用,C11 标准(ISO/IEC 9899:2011)正式将其移除——一个存在了二十年的标准库函数被从语言标准里开除,这在 C 历史上极为罕见,相当于标准委员会亲口承认“这个 API 从设计上就不该存在”。
3. 行业数据的“账本”。 内存安全问题的规模有多大?微软 MSRC(安全响应中心)2019 年给出过著名统计:其分析的高危漏洞中约 70% 归因于内存安全问题;Google Chromium 团队也报告过类似比例。更近的账本来自 Android:据谷歌安全博客 2024 年 9 月的数据,随着新代码大规模转向 Rust 等内存安全语言,Android 内存安全漏洞占比已从 2019 年的约 76% 降到 2024 年的约 24%——没有靠“程序员更小心”,而是靠“让新代码天生免疫”。
4. 政策层的转向。 2022 年 11 月,美国国家安全局(NSA)发布指南,建议关键软件优先选用内存安全语言;2024 年 2 月,白宫国家网络总监办公室(ONCD)发报告把内存安全上升为国家级技术政策;CISA 同期推动“Secure by Design”承诺,多家厂商签署。这条视频的走红不是孤立的怀旧——它踩在“内存安全”从工程话题升级为公共政策的时代节点上。
5. 防御工事的演进。 针对“控制流劫持”,业界叠了三层防线:编译期工具(AddressSanitizer、-Wall -Wextra 级别的警告、模糊测试 fuzzing);运行时缓解(ASLR 地址随机化让硬编码地址失效、栈保护 canary 在返回地址前埋哨兵、NX/DEP 让数据页不可执行);以及终极方案——新代码直接用 Rust、Go、Java 这类语言书写,由语言运行时接管内存安全。视频标题里那个"unsafe"的每一层,恰好对应这三层防线要拦的东西。
站得住的部分: - “C 不做边界检查、未定义行为危险”是语言标准的白纸黑字,无争议; - 栈溢出改写返回地址、UAF/双重释放这些机制,是安全社区四十年反复验证的共识,也是全球漏洞分类库(CVE/CWE)里的标准类别(CWE-120、CWE-416 等); - 70% 与 76%→24% 两组数据,分别来自微软与谷歌的官方报告,属于业内引用最广的硬数字。
要打折扣的部分: - "unsafe"不等于“立刻被黑”。 现代操作系统默认开启 ASLR、栈保护和 NX,视频中教科书式的攻击在今天的生产环境里要绕过层层缓解措施才能落地。视频演示的是机制可能性,不是“你写的每个越界都会被打穿”。但注意:缓解措施抬高的是攻击成本,不是免疫——攻击成本对国家级对手而言从来不是问题。 - 内存安全 ≠ 没有漏洞。 Rust 写的代码照样可能有逻辑漏洞、权限混乱、注入问题。行业数据说的是“约七成高危漏洞是内存安全问题”,剩下三成(认证绕过、逻辑缺陷等)一行代码都不会少。 - “全部重写”不现实。 世界上绝大多数关键基础设施仍是 C/C++,重写成本以十年计。现实路线是“新代码用安全语言、旧代码上工具加固”,任何“C 必须立刻死”的推论都超出了证据支持。 - 视频形态的天然限制。 这是演示型内容,不是系统课程:它负责让你“看见”危险,不负责给你完整的内存模型。把它当成课程会漏掉对齐、别名、内存屏障等大量细节——那些该交给《CS:APP》(深入理解计算机系统)和编译器手册。 - 数据时效说明。 本文播放量取自 2026-09-15 素材快照,为采集时点数据;视频发布日期未在快照中,本文不作断言。
1. 今天就给你的 C/C++ 项目上“三件套”。 编译警告开到 -Wall -Wextra -Werror;CI 里挂 AddressSanitizer(-fsanitize=address,undefined)跑一遍测试集——它能当场抓住视频里演示的越界与 UAF,且几乎零成本;有条件再引入模糊测试(libFuzzer/AFL)。这三步不能让代码变安全,但能让“不安全”从潜伏变成立刻暴露。
2. 见到“信任调用者”的老 API 就绕道。 gets() 已被标准除名,strcpy/strcat/sprintf/scanf("%s") 是同一家族的风险亲戚——凡是不接收目标缓冲区大小的接口,默认换成语义等价的边界安全版本(strncpy 家族或平台安全库)。这不是强迫症,是 C11 标准委员会用开除一个函数的方式替你总结过的教训。
3. 把“看视频”变成“做实验”。 这条视频的正确打开方式是暂停跟随:把演示代码抄下来,先预测这次输入会发生什么,再运行验证;然后去 Compiler Explorer(godbolt.org)看同样的代码在不同优化级别下生成了什么汇编。亲手让一个程序从“对”变“坏”一次,胜过读十篇内存安全社论。
flowchart TD
A["一段正常的C程序"] --> B["边界函数灌入超长输入"]
B --> C["栈溢出第一步<br/>踩到相邻变量"]
C --> D["溢出继续加深<br/>覆盖返回地址"]
D --> E["控制流被劫持<br/>程序被人指挥"]
B --> F["堆侧失衡<br/>UAF与双重释放"]
F --> G["未定义行为<br/>被编译器优化放大"]
E --> H["防线一 工具暴露<br/>警告/ASan/模糊测试"]
G --> H
H --> I["防线二 运行时缓解<br/>ASLR/栈保护/NX"]
I --> J["防线三 换语言<br/>新代码交给内存安全语言"]
本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵爱卫生(微信ID: gprshome201101)维护,聚焦5G/6G核心网、3GPP标准解读、通信前沿技术深度分析。 出版作品有《5G核心网原理与实践》《IMS原理与实践》等4本通信专业书籍。知识星球「51学通信」提供深度技术答疑和行业洞察。
[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。
