我写的很详细,希望对你有帮助!
栈溢出攻击实验
-
实验原理
若一个程序存在栈溢出漏洞,则可以通过反汇编的方法,找到程序中漏洞所在函数的返回地址,比如说该漏洞是由strcpy()函数导致的,就可以通过重写要拷贝的数组内容,使其发生栈溢出,导致函数的返回地址被攻击程序的地址覆盖,这样当该函数被调用执行完准备返回时,会调用攻击程序。
-
实验过程
首先是环境准备,在终端中执行下面的指令:
- sudo sysctl -w kernel.randomize_va_space=0
该指令的作用是关闭地址空间随机化,若不关闭,每次运行漏洞程序都会分配新的地址空间,栈寄存器ebp的基地址会发生变化,会导致攻击不成功。
2.
1)sudo su
2)gcc -m32 -g -z execstack -fno-stack-protector -o stack stack.c
3)chmod u+s stack
-fno-stack-protector选项的作用是关闭StackGuard防御机制。
execstack的作用是关闭不可执行栈防御机制。
chmod u+s的作用是赋予该程序root权限。
stack.c是含有漏洞的程序
3.
1)sudo rm /bin/sh
2)sudo ln -s /bin/zsh /bin/sh
改变/bin/sh指向zsh 避免在shell中运行时自动放弃特权
到这里,环境准备完成。
之后要对stack可执行文件进行调试:
首先对main函数进行反汇编:
结果部分如下:
我们要找的是栈寄存器的基地址,即ebp的地址,
设置断点如下:
运行到断点处:
查看ebp的地址:
这样我们就得到了ebp的地址。
漏洞代码部分如下(包含漏洞的部分):
可以看到,漏洞存在于bof函数,注意,buffer数组的大小为24,而str的大小在strcpy前并没有限制,也就是说,str的大小如果大于buffer数组的大小,那么就会发生栈溢出。
传入这个函数的str是哪里来的呢?我们再看主函数:
可以看到,主函数中是把文件badfile的内容读到了str中然后把str传给了bof函数,我们假设badfile的内容大于buffer的大小,那么就会导致bof中发生栈溢出。这时,如果栈中溢出buffer数组空间的数据正好覆盖了返回地址的内容,而新的数据又正好是恶意程序的地址,那么本来要执行的返回功能就会变成恶意程序的功能。
到这里,我们就明确了接下来要干什么
- 找到返回地址
- 用恶意代码的地址覆盖返回地址
其实返回地址我们已经得到了,返回地址一般都位于ebp+4的位置,ebp的位置我们已经有了。
尽管如此,不妨先反汇编bof函数看看有什么,
可以看到,在<+12>有ebp-0x20,函数中声明的buffer大小为24,换成16进制为0x18,与0x20很接近,所以可以认为ebp-0x20就是buffer的首地址,多分配的空间可能用于存储数组的其他信息。
所以,ebp的基地址就是(ebp-0x20)+0x20,即buffer[32];返回地址就是ebp+4,即buffer[36]。
返回地址确定了,接下来就是要确定恶意代码的地址,其实恶意代码的地址有很多选择,我们可以先看exploit.c程序的代码,这个程序是用来生成badfile文件的:
这个程序是要把buffer写进badfile,buffer的大小为517,而漏洞程序stack.c是把badfile的内容读进str,之后把str传给bof函数,在bof函数中,buffer的大小被定义为24,实际内存中分配的大小为32,所以是否会发生栈溢出,取决于badfile中的内容,即exploit.c程序中要给badfile写进什么内容,我们可以看到,exploit.c程序是把buffer写进badfile,而buffer的大小超过24,就会导致stack.c程序中发生栈溢出。
经前面的分析我们可以知道,在漏洞程序的bof函数中,buffer[36]就是返回地址,所以我们覆盖返回地址为
,这是我们打算放恶意程序的位置,这个位置是ebp+100,即
+ 0x64,又因为ebp的地址是buffer[32],所以恶意程序应放在buffer[132],这才有了上面图片中的两行代码:
之后编译exploit.c并运行,即可生成badfile文件。
一切准备就绪,我们先在seed用户下查询id:
发现没有root权限,
运行stack漏洞程序后在查询:
发现出现euid=0,获得root权限,攻击成功。