Files
examination/topics/cybersecurity/buffer-overflow/code_reading.json
T
wonder 70e368e235
Deploy Examination / deploy (push) Successful in 7s
feat: add cybersecurity topic with 6 subtopics (204 questions)
New topic group: 网络安全专题 (cybersecurity)
Subtopics:
- web-security: Web 安全基础 (34 questions)
- crypto-basics: 密码学基础 (34 questions)
- buffer-overflow: 缓冲区溢出与漏洞利用 (34 questions)
- os-security: 操作系统安全 (34 questions)
- network-attack: 网络攻防 (34 questions)
- secure-coding: 安全编程实践 (34 questions)

Question types per subtopic:
- single_choice × 20
- true_false × 10
- short_answer × 3
- code_reading × 1

Difficulty range: 1-3 (基础)
2026-09-17 13:33:04 +08:00

71 lines
4.5 KiB
JSON

{
"topic": "buffer-overflow",
"type": "code_reading",
"schema_version": "1.0.0",
"generated": "2026-09-17T00:00:00+08:00",
"questions": [
{
"id": "cr-001",
"type": "code_reading",
"difficulty": 2,
"tags": [
"缓冲区溢出",
"栈溢出"
],
"code": "#include <stdio.h>\n#include <string.h>\n\nvoid vulnerable_function(char *input) {\n char buffer[64];\n strcpy(buffer, input);\n printf(\"Input received: %s\\n\", buffer);\n}\n\nint main(int argc, char *argv[]) {\n if (argc != 2) {\n printf(\"Usage: %s <string>\\n\", argv[0]);\n return 1;\n }\n vulnerable_function(argv[1]);\n return 0;\n}",
"language": "c",
"sub_questions": [
{
"index": 1,
"type": "single_choice",
"question": "这段代码存在什么安全漏洞?",
"options": {
"A": "SQL 注入漏洞",
"B": "缓冲区溢出漏洞",
"C": "跨站脚本(XSS)漏洞",
"D": "整数溢出漏洞"
},
"answer": "B",
"explanation": "vulnerable_function 中使用 strcpy() 将用户输入复制到大小为 64 字节的 buffer 中。由于 strcpy() 不检查输入长度,当 argv[1] 的长度超过 63 字节(含 '\\0' 终止符)时,会发生缓冲区溢出,覆盖栈上 buffer 之后的数据。这是典型的栈缓冲区溢出漏洞。"
},
{
"index": 2,
"type": "single_choice",
"question": "如果 argv[1] 的长度为 200 字节,在 32 位 x86 系统上,溢出数据可能覆盖以下哪些内容?(不考虑编译器保护)",
"options": {
"A": "仅 buffer 数组的相邻变量",
"B": "buffer 数组、保存的 EBP 和函数返回地址",
"C": "仅函数返回地址",
"D": "全局变量区的数据"
},
"answer": "B",
"explanation": "buffer[64] 位于栈上,溢出 200 字节的数据会依次覆盖:buffer 之后的栈空间、保存的 EBP(帧指针,通常 4 字节)、函数返回地址(4 字节),以及 main 函数的栈帧内容。200 字节远超 buffer 大小,足以覆盖返回地址及更多栈内容。注意这里假设没有 Stack Canary 等保护。"
},
{
"index": 3,
"type": "single_choice",
"question": "如何修复这段代码中的安全漏洞?",
"options": {
"A": "将 buffer 大小改为 256",
"B": "使用 strncpy(buffer, input, sizeof(buffer)) 并确保字符串以 '\\0' 结尾",
"C": "在 strcpy 之前检查 strlen(input) < 64 即可,无需更换函数",
"D": "将 buffer 声明为 static 变量"
},
"answer": "B",
"explanation": "最正确的修复是使用有长度限制的安全函数。strncpy(buffer, input, sizeof(buffer)) 限制复制的字节数不超过 buffer 大小,并且需要确保 buffer[sizeof(buffer)-1] = '\\0' 以保证字符串终止。选项 A 只是增大了缓冲区但未消除漏洞。选项 C 的检查存在 TOCTOU(检查与使用之间的时间窗口)问题,且仍有竞态风险。选项 D 改变存储位置但不解决溢出问题。"
},
{
"index": 4,
"type": "short_answer",
"question": "假设该程序使用 gcc -fstack-protector-strong 编译,当发生栈溢出时程序的行为会有什么变化?请简要解释。",
"answer": "使用 -fstack-protector-strong 编译后,编译器会在 buffer 和保存的 EBP 之间插入一个 Stack Canary 随机值。当 buffer 发生溢出时,溢出数据会先覆盖 canary 值。在函数返回之前,程序会检查 canary 是否被修改。如果 canary 被篡改,程序会调用 __stack_chk_fail() 函数,输出错误信息(如 '*** stack smashing detected ***')并终止程序(abort),从而阻止攻击者利用溢出劫持执行流。",
"explanation": "Stack Canary 是一种编译器级别的栈溢出检测机制。编译器在函数的局部变量和保存的寄存器/返回地址之间插入一个随机的 canary 值。函数返回前检查该值的完整性,若被修改则立即终止程序。这能有效检测并阻止栈溢出攻击,但攻击者仍可能通过信息泄露获取 canary 值来绕过此保护。"
}
],
"explanation": "",
"source": null,
"related": [],
"question": "请阅读以下代码,分析其中的安全问题并回答相关问题。"
}
]
}