实验三+缓冲区溢出
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
服务器安全攻防技术实验报告
实验名称:缓冲区溢出
班级:姓名:学号:
实验地点:日期:2020/3/11
一、实验目的:
1.通过实践掌握缓冲区溢出的原理;掌握常用的缓冲区溢出方法;理解缓冲区溢出的危害性;掌握防范和避免缓冲区溢出攻击的方法。
二、基本技能实验内容、要求和环境:
实验环境:
1.PC机一台,安装有Windows 2003 server;
2.Vmware软件一套;
3.Codeblockse软件。
实验内容:
1、简单陈述缓冲区溢出的原理。
2、(1)陈述程序如何溢出?(2)为什么执行why_here方法?(3)画出栈结构
#include
#include
void why_here(void) //这个函数没有任何地方调用过
{
printf("why u here !n\n");
printf("you are trapped here\n");
system("pause");
_exit(0);
}
int main(int argc,char * argv[])
{
int buffer[1];
buffer[4] = why_here;
system("pause");
return 0;
}
三、基本技能实验结果与分析:
1、简单陈述缓冲区溢出的原理。
答案:缓冲区溢出是指当前计算机向缓冲区内填充数据位数超过了缓冲区本身的容量,溢出的数据覆盖在合法数据上,破坏程序的堆栈,使程序转而执行其他指令,以达到攻击的目的。
2、(1)陈述程序如何溢出?
运行程序,返回结果如下:
分析:由代码我们可以看出,在我们的main()函数中并没有调用过why_here()函数,只是定义了一个buffer[1]的数组,但是在我们定义了数组之后,我们同时为buffer[4]赋值为why_here()函数的返回值。我们知道buffer数组并没有buffer[4]这个位置,此时我们为它赋值就会造成该buffer[4]中原来返回地址被覆盖,转去执行why_here(),就会输出以上的语句了。
进入debug模式,查看Selected frame,从中我们可以获取的信息有:EIP为0x401384,在执行main函数之后被保存为0x4010fd,,编码为C语言,涉及到的实参有argc=1, argv=0x1e2e28,局部变量存放在栈的0x60ff08的位置;而目前的frame指针所指示的位置为0x60ff10;
保存的寄存器为EBP存放在0x60ff08,EIP保存在0x60ff0c。
debugging windows的watchs窗口中函数中涉及的参数和变量所对应的值。
(2)为什么执行why_here 方法?
答案:我们的EBP 所处的位置为0x60ff08,EIP 所处的位置为0x60ff0c,而我们当前的指针(SP )指向了0x60ff10,刚好是buffer[4]所处的地址,那么它就会转去执行why_here()函数,从而就会输出当前的语句。
(3)画出栈结构 答案:栈空间由操作系统自动分配释放,存放函数的参数值,局部变量,EBP,EIP 的值,栈使用的是一级缓存,只是在被调用的时候处于存储空间中,调用完成立即释放。
注意,全局变量和局部静态变量的存储并不会放到内存中的栈区,而是放到静态区,程序执行结束由系统释放。
在Windows 中,栈是线低地址扩展的数据结构,是一块连续的内存区域。 在大多数的C 编译器中,参数是由右向左入栈,然后就是函数中的局部变量。 当本次函数调用结束后,局部变量先出栈,然后是参数,最后是栈顶指针指向函数的返回地址,就是主函数中下一条指令的地址。程序就会从该点继续执行。
了解栈的相关知识之后,就可以画出以以下栈的结构:
局部变量存放在低地址端(0x60ff04)
EBP 存放位置(0x60ff08)
函数返回的地址,下一条指令地址(0x60ff10)
EIP 存放位置(0x60ff0c)
四、进阶技能的任务与要求:
1、(1)陈述程序如何溢出?
(2)画出栈结构
(3)补充auth方法,如果输入字符超出正常范围下,提示“输入字符超出范围”;否则,无提示。
#include
#include
int auth(const char* password){
int flag = 0;
char pwd[16];
strcpy(pwd, password);
pwd[0] = 't';
if(!strcmp(pwd, "test")){
flag = 1;
}
return flag;
}
int main(){
int flag = 0;
char password[128];
scanf("%s", password);
if(auth(password)){
printf("right password\n");
}else{
printf("wrong password\n");
}
return 0;
}
2、设计具有溢出的程序,并解释说明
五、进阶技能实验结果与分析:
1.首先分析代码块,strcpy()函数用于对字符串进行复制,strcpy(char* strDestination, const char* strSource)。其中,strDestination代表的是目的字符串,strSource,代表的是源字符串,strcpy()函数会把strSource指向字符串复制到strDestination。
必须要保证strDestination足够大,能够容纳下strSource,否者的话,就会造成溢出错误。
返回值为目的字符串,即strDestination。
而我们的程序中的main()函数中的password定义为128位的字符数组,而main()函数中if语句调用的auth()函数中定义的pwd为16位的字符数组,并且在auth()函数中strcpy()函数将password的值赋值给了pwd。如果我们输入的password大于16位,这就造成了溢出错误。
1)在我们输入和需要比对的字符串test相同时,就会返回正确的密码;