缓冲区溢出案例生成与分析
缓冲区溢出案例生成与分析
1.环境准备
- 操作系统:Ubuntu-linux 这里我使用的是wsl虚拟机
- 编译器:gcc
- 调试工具:gdb
2.缓冲区漏洞案例生成
漏洞程序:
1 | |
存在的漏洞的原因在于它使用了不安全的函数 strcpy,并且没有对输入进行边界检查,导致有缓冲区溢出的可能性。
为什么会是危险的:如果 input 的长度超过64字节,strcpy 会继续将多余的数据写入 buffer 之外的内存区域。这会覆盖栈上的其他重要数据。
编译程序:
1 | |
-fno-stack-protector: 禁用栈保护。-z execstack: 允许栈执行。
(不这样做无法利用漏洞)
触发缓冲区溢出:
1 | |

这样这个缓冲区溢出的漏洞就生成了
3.缓冲区溢出案例分析
使用GDB调试程序,查看崩溃时的寄存器状态。
1 | |
在GDB中运行程序:
1 | |

崩溃后,查看寄存器和栈:
1 | |

寄存器状态分析:
rbp寄存器:1
rbp 0x4141414141414141 0x4141414141414141rbp是栈帧指针(Base Pointer),通常用于指向当前函数的栈帧。- 这里
rbp的值被覆盖为0x4141414141414141,其中0x41是字符A的 ASCII 码。这表明输入数据中的A覆盖了栈帧指针。
rip寄存器:1
rip 0x55555555518e 0x55555555518e <vulnerable_function+37>rip是指令指针(Instruction Pointer),指向当前执行的指令。- 当前
rip的值是0x55555555518e,位于vulnerable_function函数中。这表明程序尚未返回,但栈帧已经被破坏。
其他寄存器:
rcx和r9等寄存器也被覆盖为0x4141414141414141,进一步证明了输入数据溢出到了栈上的其他区域。
栈内存分析:
1 | |
- 这是因为
$esp(栈指针)指向的地址0xffffffffffffdac8是一个无效地址(可能是由于栈被破坏导致的)。 - 在 64 位系统中,地址空间非常大,而
0xffffffffffffdac8是一个接近上限的地址,通常不会被映射到有效的内存区域。
4.如何修复这个漏洞
要修复这个漏洞,就要使用更安全的函数来替代 strcpy,并对输入进行边界检查。
使用
strncpy替代strcpy,并指定最大复制长度:1
2strncpy(buffer, input, sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0'; // 确保字符串以 \0 结尾使用更安全的库函数,如
snprintf:1
snprintf(buffer, sizeof(buffer), "%s", input);对输入长度进行显式检查:
1
2
3
4if (strlen(input) >= sizeof(buffer)) {
printf("Input too long!\n");
return;
}
在这里感谢deepseek对我的大力支持,寄存器分析和栈内存分析由他帮忙完成。
此为计算机思维导论作业
缓冲区溢出案例生成与分析
http://example.com/2025/03/05/缓冲区溢出案例生成与分析/