四、缓冲区溢出漏洞和攻击
原文:Buffer-Overflow Vulnerabilities and Attacks 译者:飞龙
1 内存
这个讲义的“区域”(Area)和“段”(Segment)与多数教程正好相反,译文中已更正。
在 PC 架构中,程序中有四个基本读写段:栈、数据、BSS 和堆。数据、BSS 以及堆区可统称为“数据区域”。在“内存布局和栈”的教程中,Peter Jay Salzman 详细描述了内存布局。
- 栈:栈通常在内存的高地址。通常“向下增长”:从高地址到低地址。无论何时进行函数调用,栈都会使用。
- 数据区域
- 数据段:包含程序所用的全局变量,它们不被初始化为 0。例如,字符串
hello world
由char s[] = "hello world"
定义,它在 C 中存在于数据段。 - BSS 段:起始于数据段的末尾,并包含所有初始化为 0 的全局变量。例如,变量声明为
static int
,会包含在 BSS 段中。 - 堆段:起始于 BSS 段的末尾,向高地址增长。堆段由
malloc
库管理。堆段由程序中所有共享库以及动态加载模块共享。
- 数据段:包含程序所用的全局变量,它们不被初始化为 0。例如,字符串
2 栈缓冲区溢出
2.1 栈的背景
- 栈布局:下面的图片展示了在执行流进入函数
func
之后,栈的布局。 - 栈方向:栈从高地址向低地址增长(而缓冲区正好相反)。
- 返回地址:函数返回后所执行的地址。
- 在进入函数之前,程序需要记住从函数返回之后,应该返回到哪里。也就是需要记住返回地址。
- 返回地址是函数调用下一条指令的地址。
- 返回地址会储存在栈上。在 x86 中,指令
call func
会将call
语句下一条指令的地址压入栈中(返回地址区域),之后跳到func
的代码处。
- FP来表示FP寄存器的值。 variable_a被引用为FP-16。buffer被引用为FP-12。str被引用为
- 缓冲区溢出问题:上面的程序拥有缓冲区溢出问题。
- 函数
strcpy(buffer, str)
将内存从str
复制到buffer
。 str
指向的字符串多于 12 个字符,但是buffer
的大小只为 12。- 函数
strcpy
不检查buffer
是否到达了边界。它值在看到字符串末尾
- 函数