1.缓冲区基础知识相关定义
缓冲区定义:缓冲区一块连续的内存区域,用于存放程序运行时,加载到内存的运行代码和数据。
缓冲区溢出:缓冲区溢出是指程序运行时,向固定大小的缓冲区写入超过其容量的数据。多余的数据会越过缓冲区的边界覆盖相邻内存空间,从而造成溢出。
缓冲区溢出攻击:缓冲区溢出攻击是指发生缓冲区溢出时,溢出的数据会覆盖相邻内存空间的返回地址、函数指针、堆管理结构等合法数据,从而使程序运行失败、或者发生转向去执行其他程序代码,从而使程序运行失败、或者执行预先注入到内存缓冲区中的代码。
补充:缓冲区溢出后执行的代码,会以原有程序的身份权限运行。
2.造成缓冲区溢出的根本原因
原因:因为缺乏类型安全功能的程序设计语言(C/C++等)处于效率的考虑,部分函数不对数组边界条件和函数指针引用进行边界检查。
如c语言中的函数:strcpy()、strcat()等。
建议:所以在日常开发软件过程中,程序员需要对边界检查,防止数据溢出。
3.缓冲区溢出的分类
(1)栈溢出漏洞
被调用的子函数中写入数据的长度,大于栈帧的基址(ebp)到esp之间预留的保存局部变量的空间时,就会发生栈溢出。
补充:写入数据的填充方向是从栈底向栈顶方向输入数据,多余的数据就会越过栈帧的基址,覆盖基址以上的地址空间。
①栈溢出漏洞的利用:
a、修改返回地址
栈的存取数据采用先进后出的策略,程序用它来保护函数调用时的有关信息,如函数参数、返回地址。函数中的非静态局部变量存放在栈中。如果返回地址被覆盖,当覆盖后的地址是一个无效地址,则程序运行失败。如果覆盖返回地址的是恶意程序的入口地址,则源程序将转向去执行恶意程序。
b、修改临街变量
如果返回临近变量的值,可能会更改程序执行流程。
(2)堆溢出漏洞
堆的定义:堆是内存空间中用于存放动态数据的区域。与栈不同的是,程序员自己完成堆中变量的分配与释放。
堆溢出:是指在堆中发生的缓冲区溢出。
解释:由于堆与栈结构的不同,堆溢出不同于栈溢出。相比于栈溢出,堆溢出的实现难度更大,而且往往要求进程在内存中具备特定的组织结构。然后,堆溢出攻击也已经成为缓冲区溢出攻击的主要方式之一,利用堆溢出可以有效绕过基于栈溢出的缓冲区溢出防范措施。
补充: 对于堆内存分配,操作系统有一个堆管理结构,用来管理空闲内存地址的链表。
当使用malloc函数在内存中申请一块空间,在windows环境下,申请过程如下:
buffer1=(char*)malloc(8)
char content []="AAAAAAAABBBBBBBBCCCCDDDD"
memcpy(buffer1,content)
这段代码就会将空闲块双链表指针进行覆盖使得ecx=CCCC,edi=DDDD,当再次使用malloc的时候,就会调用RtlAllocHeap函数找到空闲的堆块。而RtlAIIocHeap这个函数一定会执行:
mov dword ptr [edi] ecx;
所以当就会将覆盖的数据CCCC送到指定的指定地址DDDD中。这就造成了如果攻击者恶意构造覆盖数据,就可以实现修改程序中地址的内容。(如恶意代码执行等)
(3)单字节溢出
单字节溢出是指程序中的缓冲区仅能溢出一个字节。