一、 实验目的
通过实验,使我们对缓冲区溢出攻击的原理更加了解,对此攻击方式更加得心应手。
二、 实验原理
当向缓冲区里写入的数据超过了为其分配的大小时,就会发生缓冲区溢出。攻击者可以利用缓冲区溢出来窜改进程运行时栈,从而改变程序的正常流向。
三、 实验分析
1) main函数在调用f函数前,首先将参入的参数压入栈中;
2) 接着,将当前程序执行的下一个的位置EIP加入栈中,后面f函数返回时用;
3) 进入f函数,f函数首先将当前的EBP压入栈中,接着mov esp, ebp(将EBP指向当前的栈顶),接着以EBP为基础构建自己的函数帧结构。函数帧结构中包含当前函数的局部变量(攻击的示例程序的buffer变量及在这里面)
4) 在f函数执行完成后,会将栈中的EBP值弹出,恢复到EBP寄存器中,还原ESP寄存器,接着弹出EIP变量,程序根据EIP变量指向的位置接着执行main函数后面的程序部分。
图1
main函数调用f函数的栈结构如下图所示:
图2
对buf进行数据拷贝,得到的结果如下图所示:
图3
四、 实验步骤
首先,就像教程上做的,将32位编程的一些库加进去:
图4
图5
图6
接下来进入正题,进入32位linux环境,使用bash:
图7
使用地址空间随机化来随机堆与栈的初始地址使得我们猜测准确的内存地址非常困难,因此我们关闭这一功能:
图8
接下来编写stack相信大家都会了,实验教程中也有,因此这里就不再贴出来,编译程序,设置SET-UID:
图9
接下来是写攻击程序,将stack.c和exploit.c都存放在tmp中,tmp文件夹可以在主文件夹中搜索到,在exploit.c中“\x??\x??\x??\x??”处需要添上shellcode保存在内存中的地址,因为发生溢出后这个位置刚好可以覆盖返回地址。而strcpy(buffer+100,shellcode); 这一句又告诉我们,shellcode保存在 buffer+100 的位置。现在我们要得到shellcode在内存中的地址,输入命令:
图10
结果显示:
图11
接下来按照教程:
图12
根据语句strcpy(buffer+100,shellcode); 我们计算shellcode的地址为 0xffffd010(十六进制)+100(十进制)=0xffffd074(十六进制)
现在修改exploit.c文件!将 \x??\x??\x??\x?? 修改为 \x74\xd0\xff\xff
编译exploit.c并且进行攻击:
图13
产生段错误,这里使我非常苦恼,然后我就进行了测试:
图14
图15
图16
图17
在此终于找到问题,在stack.c中我打错了一个单词:badfile,使得我大动干戈,首先我定位到了fread的问题,那肯定是有什么地址溢出或者是访问出现了越界之类的问题,然后我努力的查看了exploit.c发现一点问题都没有,就再运行了一遍发现warning中问题出现在了stack.c,这告诉我们每一个warning都是致命的。
图18
接下来,重新计算地址:
图19
然后开始缓冲区溢出攻击:
图20
出现的fault不要怕,重新编译一下stack.c就OK了。
第二个实验则重新开始即可,地址需要重新查看与计算:
图21
发现出现段错误(这是本阶段实验出现的正确的实验结果):
图22
第三个实验还是重新开始,但是这次不加以下代码:
图23
进行相同操作发现可以成功显示root:
图24
最后附上改地址的操作图片:
图25
五、 实验总结
1) 通过这次的实验,使得我对缓冲区的溢出攻击的原理更加明白了,本来上课听的有些模糊,经过这次上网上搜索资料和进行实验,让我对这个实验更加了解;
2) 通过这次实验,让我对bug调试更加得心应手,当时我总是产生段错误,然后我就在网上搜索解决的办法和容易出现此类错误的地方,然后通过命令我定位到了错误地点,访问的内存地址不存在,然后我检查了代码编译出现的warning,发现一个单词打错了,最终解决问题。