实验报告
课程名称: 计算机与网络安全
任课教师: 常晓林
学生姓名: 郭鑫玥
学生学号: 16281284
学院名称: 计算机与信息技术学院
2019 年 3 月 30 日
Lab 2:Buffer Overflow Vulnerability
目录
1 实验描述 .................................................................................... 3
2 实验内容 .................................................................................... 3
2.1 task 1 :Exploiting the Vulnerability ................................... 4
2.2 task 2 :Protection in /bin/bash ........................................ 8
2.3 task 3 :Address Randomization ........................................ 9
2.4 task 4 :Stack Guard .......................................................... 9
3 实验总结 .................................................................................. 10
1 实验描述
缓冲区溢出定义为程序尝试将数据写入超出预分配的固定长度缓冲区边
界的条件。恶意用户可以利用此漏洞来改变程序的流控制,甚至可以执行任意代
码。此漏洞由于数据存储(例如缓冲区)和控制存储(例如返回地址)的混合而
产生:数据部分中的溢出会影响程序的控制流,因为溢出可能会更改返回地址。
在本实验中,我们将获得一个缓冲区溢出漏洞的程序,开发一个利用漏洞的方案,
最终获得 root 权限。
2 实验内容
首先需要进行一些相关准备工作:
1. 本次实验需要实现 32 位编译,但由于系统为 64 位 Ubuntu Linux。
2. 输入命令安装一些用于编译 32 位 C 程序的相关操作:
完成后可进入 linux32
3. 为了防止缓冲区溢出漏洞,利用保护机制: Address Randomization 地址
空间随机化、Non-executable Stack 不可执行栈、“Stack Guard”三种。在利用缓
冲区溢出漏洞实现攻击或者单独考量某种保护机制的有效性的过程中,我们需要
禁用某些机制。
(1)内存地址随机化(Address Space Randomization)
基于 Linux 的操作系统一般使堆和栈的开始地址随机化,使得攻击者猜测确
切的地址变得困难。使用如下指令关闭该功能。
$ su root
Password: (enter root password)
#sysctl -w kernel.randomize_va_space=0
(2)The StackGuard Protection Scheme
GCC 编译器实现了一个被称为“Stack Guard”的安全机制来防御缓冲区溢
出攻击。所以在编译漏洞程序时加上-fno-stack-protector 参数来关闭该机制。
(3)Non-Executable Stack
Ubuntu 曾经允许栈执行,但是现在程序必须声明栈是否允许执行。内核和
链接器检查程序头的标志来判断是否允许栈被执行。GCC 在模式情况下设置栈
不可执行,所以需要在编译时加入-z execstack 参数来允许栈执行。
4. gdb 调试指令准备
(1)b main ——> 在 main 函数执行出设置断点
(2)p /x &str ——> 以十六进制打印 str(字符串名)的存储地址
(3)disass main ——> 输出 main(函数名)的反汇编代码
2.1 task 1 :Exploiting the Vulnerability
实验任务:要求在关闭所有保护机制的情况下,完成漏洞程序的设计,并实
现攻击。设计思路:合理的填充 badfile 文件的内容,实现在用户程序 stack.c 读
取该文件并拷贝到自己的缓冲区(即 bof(char *str)函数栈帧存储空间)后,由
于缓冲区溢出,执行 bof 函数的返回地址内存单元被覆盖且对应换成了 shellcode
的首地址,接下来用户程序执行 shellcode 并启动了带有用户程序权限的 shell。
实验流程:
1. Ubuntu 和其他一些 Linux 系统中,使用地址空间随机化来随机堆(heap)
和栈(stack)的初始地址,这使得猜测准确的内存地址变得十分困难,而猜测内
存地址是缓冲区溢出攻击的关键。因此本次实验中,我们使用以下命令关闭这一
功能:
2. linux 系统中,/bin/sh 实际是指向/bin/bash 或/bin/dash 的一个符号链接。我
们使用另一个 shell 程序(zsh)代替/bin/bash
3. 创建并保存“stack.c”文件,编译该程序,编译时确保加入-z execstack 参
数来允许栈执行,加上-fno-stack-protector 参数来关闭“Stack Guard”的安全机
制,并设置 SET-UID。
4. 创建保存“exploit.c”文件,测算 shellcode 的地址
通过 gdb stack 获取 shellcode 在内存中的地址:
其中 esp 中就是 str 起始地址:$0x214,%esp,所以我们在 0x080484ee <+20>:
处设置断点。
从上图可以看到,漏洞程序读取 badfile 文件到缓冲区 str,且 str 的地址为
0xffffce50,计算上 shellcode 偏移量 100(0x64),则 shellcode 地址为 0xffffceb4。
函数调用过程中的堆栈帧结构:
5. 修改 exploit.c 文件
strcpy(buffer+100,shellcode); 表示:shellcode 保存在 buffer+100 的位置。
6. 编译运行 exploit.c 程序,后先运行攻击程序 exploit,再运行漏洞程序 stack。
可见攻击成功。成功获得 root 权限。
2.2 task 2 :Protection in /bin/bash
实验任务:现在,我们让/ bin / sh 指向/ bin / bash,并运行前面开发的相同攻
击
实验流程:
1. 将软连接改回 bash
2. 再回到/tmp 下重复攻击操作
可见无法实现攻击。攻击失败是由于没有获得 root 权限。因为使用的 bash 程
序,当 shell 运行时,没有 root 权限。此时,即便攻击程序攻击了漏洞程序,也
无法获得 root 权限。