参考教程与材料:http://www.cis.syr.edu/~wedu/seed/Labs_12.04/Software/Buffer_Overflow/
(本文记录了做SEED缓冲区溢出实验的体会与问题,侧重实践,而不是讲解缓冲区溢出原理的详细教程)
1. 准备工作
使用SEED ubuntu虚拟机进行缓冲区溢出实验,首先要关闭一些针对此攻击的防御机制来简化实验。
(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参数来允许栈执行。
2. ShellCode
教程提供了shellcode,是如下代码反汇编得到的机器码,功能就是打开一个shell,通过编译执行call_shellcode.c可以验证shellcode的正确性。使用gdb调试call_shellcode会发现buf的起始地址没有进行字节对其,但是并不影响shellcode的执行,该验证程序是将buf强制转换成了函数指针来执行,用法巧妙。其中shellcode还有一些需要解释的地方,如“//sh”是为了凑足4字节,并且“/”与“//”是一样的;为了给execve传递参数,需要字符串的地址,这里采用了push并传递esp的方法;cdq是一个简短的指令来使edx置零。注意在编译时加入令栈可执行的参数,指令如下所示:gcc -z execstack -o call_shellcode call_shellcode.c
#include <stdio.h> int main( ) { char* name[2]; name[0] = ‘‘/bin/sh’’; name[1] = NULL; execve(name[0], name, NULL); }