
1) 【一句话结论】在Linux环境下,栈溢出漏洞通过覆盖函数调用后的返回地址,使程序跳转到我们构造的恶意代码(如shellcode),从而执行任意指令,获取系统权限。
2) 【原理/概念讲解】老师解释栈帧结构。函数调用时,栈会向下增长,保存返回地址(函数返回后跳转的地址)、局部变量、函数参数等。缓冲区溢出是指向缓冲区写入超过其容量的数据,这些多余的数据会覆盖栈上的返回地址,导致函数返回时跳转到错误的地址。比如,函数vuln中有一个缓冲区buf,当输入字符串长度超过buf大小时,strcpy会将输入全部复制到buf,并覆盖栈上的返回地址。此时,程序执行完vuln后,会从错误的地址跳转,执行我们构造的代码。类比:就像给一个杯子倒水,杯子满了还倒,水就会溢出,覆盖旁边的地址标签(返回地址),导致程序“走错路”,跳转到我们指定的位置。
3) 【对比与适用场景】
| 漏洞类型 | 定义 | 核心原理 | 利用方式 | 注意点 |
|---|---|---|---|---|
| 栈溢出 | 函数调用时,缓冲区溢出覆盖返回地址 | 覆盖栈上的返回地址 | 控制返回地址跳转 | 需计算偏移量,处理栈保护 |
| 堆溢出 | 操作堆内存时,溢出覆盖堆结构 | 覆盖堆控制块 | 控制堆地址跳转 | 需计算堆偏移量,处理内存保护 |
| 格式化字符串 | 使用未初始化的格式化字符串函数 | 读取栈/堆内存 | 控制输出位置 | 需分析格式化字符串格式 |
栈溢出是经典的代码执行漏洞,适用于存在缓冲区未检查边界的函数(如strcpy、gets、sprintf等),通过修改返回地址实现代码执行。
4) 【示例】
以一个简单的C程序为例,展示栈溢出漏洞及利用:
#include <stdio.h>
#include <string.h>
void vulnerable_function(char *input) {
char buffer[64];
strcpy(buffer, input); // 缺少边界检查,导致缓冲区溢出
printf("Input processed: %s\n", buffer);
}
int main(int argc, char *argv[]) {
if (argc < 2) {
printf("Usage: %s <payload>\n", argv[0]);
return 1;
}
vulnerable_function(argv[1]);
return 0;
}
漏洞利用步骤:
-0x18,即16字节)。A*偏移量(填充至返回地址位置)+ shellcode(如系统调用execve的shellcode)+ 返回地址(跳转到shellcode的地址)。例如,若返回地址为0xdeadbeef,shellcode地址为0x12345678,则payload为:A*16 + shellcode + 0xdeadbeef(小端系统下为0xef be ad de 12 34 56 78)。/bin/sh),获取shell权限。5) 【面试口播版答案】
“缓冲区溢出漏洞利用的核心是通过覆盖函数返回地址,使程序跳转到我们控制的恶意代码执行。在Linux环境下,函数调用时栈帧会保存返回地址,当缓冲区写入超过容量时,会覆盖返回地址。比如,假设一个函数中有一个64字节的缓冲区,输入超过64字节后,会覆盖返回地址,导致程序返回时跳转到我们构造的shellcode。具体步骤是:计算返回地址在栈上的偏移量,构造包含shellcode和跳转地址的payload,覆盖返回地址后,程序执行shellcode,获取shell权限。以360安全卫士的某个本地模块为例,假设模块中有类似函数,通过分析其栈布局,计算偏移量,构造payload,最终执行shellcode,获得系统权限。”
6) 【追问清单】
7) 【常见坑/雷区】