seedlab缓冲区溢出实验
一、实验目的
本实验的学习目标是让学生通过将他们从课堂上学到的有关漏洞的知识付诸实践,获得有关缓冲区溢出漏洞的第一手经验。缓冲区溢出定义为程序试图在预分配的固定长度缓冲区的边界之外写入数据的条件。恶意用户可以利用此漏洞来更改程序的流控制,甚至执行任意代码。出现此漏洞的原因是数据存储区(例如缓冲区)和控件存储区(例如返回地址)的混合:数据部分的溢出会影响程序的控制流程,因为溢出会改变返回地址。
二、实验步骤与结果
首先进行初始设置:
1、关闭地址空间随机化,为了防止堆栈地址和动态链接库加载地址随机化从而无法执行目标shellcode。
2、在编译程序时应该设置堆栈不可执行,否则shellcode是无法在栈上执行的。
3、关闭stack guard机制,防止栈溢出被检测出来,但是如果有格式化字符串漏洞的话,可以尝试泄露cancary的值,然后可以在构造的时候在ebp之前加上该值就可以执行shellcode了。
4、将/bin/sh的符号链接指向/bin/zsh,因为在16.04中默认是指向/bin/bash的,而该shell会检测到它在一个Set-UID 进程中被执行,它会立即切换有效的user ID 为进程的真实user ID,放弃特权。
Task1:运行shellcode
加入编译条件后
1 | gcc -z execstack -o call_shellcode call_shellcode.c |
运行结果如下:
的确打开了/bin/sh这个shell,说明shell可以被调用成功。
之后查看漏洞程序,发现存在缓冲区溢出漏洞,向24字节大小的地址中写入517个字节的大小。这517个字节数据来自于badfile文件,所以重点就是如何构造输入数据。
之后对于漏洞程序来说,如果我们想要拿到root权限,那么调用shell的程序也是 应该具有root权限才可以,否则只会像上图一样以普通用户模式打开shell。所以应该对此程序设为set-uid root。指令调用如下:
调用结束之后,
发现修改成功,task1结束。
Task2:利用漏洞
既然要利用程序,那么确定buffer相对于返回地址的偏移量便是很重要的,一旦确定偏移量,那么返回地址上面覆盖为需要执行的代码即可。
首先随机生成100个字节写入badfile中,然后运行stack,在gdb中程序会停住。
停住的原因就是返回地址无法识别为可执行的数据。如果能得到EBP的偏移量,那么返回地址就在后面4个字节处,之后查看偏移量:
发现偏移量为32,也就是我们的shellcode的地址应该放到buffer+36地址处,之后便需要确定shellcode的地址,如果选择把shellcode放到buffer+100处,那么进入程序后,会先放到str变量中,如果能知道str变量的地址,那么便可以知道shellcode的地址。
得到了str的地址,那么此时shellcode的地址就是0xbfff12/26/2020eb77+100,即0xbfffebdb。
运行之后,可得root:
之后可以通过运行setuid程序来得到真正的root:
Task3:ASLR
打开地址空间随机化,
因为32为中,栈的基地址只有pow(2,19)种可能,可以暴力破解。
执行如下脚本:
执行结果如下:
运行70272次,成功打开shell。
Task4:stack guard
执行如下指令:
打开stack guard机制
发现栈溢出被检测到了,原因就是覆盖了EBP附近的cancry标志,由系统检测到,报错。
Task5:不可执行栈
使用如下指令关闭不可执行栈:
程序崩溃,进入gdb发现无法识别指令所代表的一串数据为合法地址。
即栈上不能包含指令,如果想要攻击的话,可以在上面覆盖某些gadget的地址,生成ROP链进行攻击。
- 本文作者: 李小混
- 本文链接: https://lixiaohun.github.io/post/9.html
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!