1. 栈溢出原理剖析
栈溢出(Stack Overflow)是程序运行时最常见的漏洞类型之一,发生在调用栈(call stack)的内存空间被过度使用时。当程序向栈中写入的数据超过了为其分配的内存空间时,就会覆盖相邻内存区域的数据,导致程序行为异常甚至被攻击者利用。
1.1 栈的内存结构
在x86架构中,栈是从高地址向低地址生长的连续内存区域,主要存储以下内容:
- 函数参数(从右向左压栈)
- 返回地址(call指令自动压入)
- 保存的寄存器值(如ebp)
- 局部变量
典型的函数调用栈帧结构如下:
code复制高地址
+----------------+
| 调用者栈帧 |
| 参数n |
| ... |
| 参数1 |
| 返回地址 | <- esp进入函数时
| 保存的ebp | <- ebp被设置为当前esp
| 局部变量1 |
| ... |
| 局部变量n |
+----------------+
低地址
1.2 溢出发生的条件
栈溢出通常发生在以下场景:
- 使用不安全的字符串处理函数(如strcpy、gets)
- 未校验用户输入长度的数组操作
- 递归调用层次过深
- 过大的局部变量申请
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 经典栈溢出示例分析
2.1 脆弱代码示例
c复制#include <string.h>
void vulnerable_function(char* input) {
char buffer[64];
strcpy(buffer, input); // 危险操作!
}
int main(int argc, char** argv) {
vulnerable_function(argv[1]);
return 0;
}
2.2 溢出过程详解
当输入字符串长度超过63字节(64字节缓冲区需要留1字节给结束符'\0')时:
- strcpy会继续向高地址写入数据
- 依次覆盖:
- 保存的ebp值
- 返回地址(关键覆盖目标)
- 调用者的栈帧内容
- 当函数执行ret指令时,会跳转
