缓冲区溢出以及缓冲区溢出攻击

缓冲区溢出是指当计算机程序向缓冲区内填充的数据位数超过了缓冲区本身的容量。溢出的数据覆盖在合法数据上。理想情况是,程序检查数据长度并且不允许输入超过缓冲区长度的字符串。但是绝大多数程序都会假设数据长度总是与所分配的存储空间相匹配,这就为缓冲区溢出埋下隐患。

操作系统所使用的缓冲区又被称为堆栈,在各个操作进程之间,指令被临时存储在堆栈当中,堆栈也会出现缓冲区溢出。 当一个超长的数据进入到缓冲区时,超出部分就会被写入其他缓冲区,其他缓冲区存放的可能是数据、下一条指令的指针,或者是其他程序的输出内容,这些内容都被覆盖或者破坏掉。可见一小部分数据或者一套指令的溢出就可能导致一个程序或者操作系统崩溃。

    #include <stdio.h>
    #include <string.h>
    #include <iostream>  

    using namespace std;  

    int main(int argc, char *argv[])
    {
        char buf[10];
        strcpy(buf, argv[1]);
        cout<<buf;
        return 0;
    }  

连续输入20个字符就产生了溢出。

C语言常用的strcpy、sprintf、strcat 等函数都非常容易导致缓冲区溢出问题。

程序运行时,其内存里面一般都包含这些部分:

(1)程序参数和程序环境;

(2)程序堆栈(堆栈则比较特殊,主要是在调用函数时来保存现场,以便函数返回之后能继续运行),它通常在程序执行时增长,一般情况下,它向下朝堆增长

(3)堆,它也在程序执行时增长,相反,它向上朝堆栈增长;

(4)BSS 段,它包含未初始化的全局可用的数据(例如,全局变量);

(5)数据段,它包含初始化的全局可用的数据(通常是全局变量);

(6)文本段,它包含只读程序代码。

BSS、数据和文本段组成静态内存:在程序运行之前这些段的大小已经固定。程序运行时虽然可以更改个别变量,但不能将数据分配到这些段中。

以下面的程序为例:

    #include <stdio.h>  

    char buf[3] = "abc";
    int i;  

    int main()
    {
        i = 1;
        return 0;
    }  

其中,i属于BBS段,而buf属于数据段。两者都属于静态内存,因为他们在程序中虽然可以改变值,但是其分配的内存大小是固定的,如buf的数据大于三个字符,将会覆盖其他数据。

与静态内存形成对比,堆和堆栈是动态的,可以在程序运行的时候改变大小。堆的程序员接口因语言而异。在C语言中,堆是经由malloc()和其它相关函数来访问的,而C++中的new运算符则是堆的程序员接口。堆栈则比较特殊,主要是在调用函数时来保存现场,以便函数返回之后能继续运行。



缓冲区溢出攻击



缓冲区溢出攻击简单介绍:

缓冲区溢出的一个致命的使用就是让程序执行它本来不愿意执行的函数。这是一种常见的通过计算机网络攻击系统安全的方法。通常,输入给程序一个字符串,这个字符串包含一些可执行代码的字节编码,成为攻击代码。另外,还有一些字节会用一个指向攻击代码的指针覆盖返回地址。那么,执行ret指令的效果就是跳转到攻击代码。My god, 黑客顺利侵入。

一种攻击形式,攻击代码会使用系统调用启动一个外壳程序,给攻击者提供一组操作系统函数。

另一种攻击形式,攻击代码会执行一些未授权的任务,修复对栈的破坏,然后第二次执行ret指令,(表面上正常返回给调用者)。


那么如何防护/对抗缓冲区溢出攻击?

(1)栈随机化(主要受linux系统版本限制,老版本不支持栈随机化):使得栈的位置在程序每次运行时都有变化。为了在系统插入攻击代码,攻击者不但要插入代码,还需要插入指向这段代码的指针(指向攻击代码的首地址/栈地址),这个指针也是攻击字符串的一部分。产生这个指针需要知道这个字符串放置的栈地址。老的系统版本,如果在相同的系统运行相同的程序,栈的位置是相当固定的。所以黑客可以在一台机器上研究透系统上的栈是如何分配地址的,就可以入侵其它主机。

实现的方式:程序开始时,在栈上分配一段0~n字节之间随机大小的空间。分配的范围n必须足够大,才能获得足够多样的栈地址变化,但是又要足够小,不至于浪费程序太多的空间。tradeoff

(2)栈破坏检测(主要受GCC版本的限制,老的GCC版本不支持栈破坏检测):检测到何时栈被破坏。从strcpy等函数我们可以看到,破坏通常发生在当超越局部缓冲区的边界时。在C语言中,没有可靠的方法来防止对数组的越界写。但是,我们能够在发生了越界写的时候,并且,在其还没有造成任何有害结果之前,尝试检测到它,并且把程序终止。

实现的方式金丝雀,加入一种栈保护机制。 在栈帧中,紧接着局部缓冲区的位置放置一个哨兵(金丝雀),哨兵值是随机产生的,攻击者没有简单的方法能够知道它是什么。在恢复寄存器状态和函数返回之 前,程序检查这个金丝雀的值是否发生改变,如果发生改变立即终止程序。《深入理解操作系统》P182页,有一个特别好的例子。

(3)限制可执行代码区域(主要受硬件版本的限制,需要硬件支持):消除攻击者向系统插入可执行代码的能力,一种方法是:限制那些能够存放可执行代码的存储器区域。在典型的系统中,只有保存编译器产生的代码的那部分存储器才需要是可执行的,其它部分可以被限制为只允许读和写。

一般的系统允许三种访问的形式:读(从存储器读数据)、写(存储数据到存储器)和执行(将存储器的内容看作是机器级代码)。以前,x86体系结构将读和执行访问控制合并为1位的标志,这样任何被标记为可读的页都是可执行的。栈又要求必须是既可以读又可以写的,所以x86体系结构栈上的字节都是可执行的。也有一些体制,能够限制一些页是可读但是不可执行,但是这些体制一般都会带来严重的性能损失。

实现的方式:AMD为它的64位存储器的内容保护引入了“NX”(No-eXecute,不执行)位,将读和执行访问模式分开,intel也跟进了。从这开始,栈可以被标记为可读、可写,但是不可执行。检查页是否可执行由硬件来完成,效率上没有损失。

时间: 2024-10-13 00:41:30

缓冲区溢出以及缓冲区溢出攻击的相关文章

Linux文件系统(四)---三大缓冲区之inode缓冲区 (内存inode映像 )

在文件系统中,有三大缓冲为了提升效率:inode缓冲区.dentry缓冲区.块缓冲. (内核:2.4.37) 一.inode缓冲区 为了加快对索引节点的索引,引入inode缓冲区,下面我们看Linux/fs/inode.c代码.inode缓冲区代码 1.一些数据结构: 之前已经说过,有多个链表用于管理inode节点: <span style="font-size:14px;">59 static LIST_HEAD(inode_in_use); 60 static LIST

C语言创建循环缓冲区(环形缓冲区)-- Circular Buffer(Ring Buffer)

由于嵌入式系统的资源有限性,循环缓冲区数据结构体(Circular Buffer Data Structures)被大量的使用. 循环缓冲区(也称为环形缓冲区)是固定大小的缓冲区,工作原理就像内存是连续的且可循环的一样.在生成和使用内存时,不需将原来的数据全部重新清理掉,只要调整head/tail 指针即可.当添加数据时,head 指针前进.当使用数据时,tail 指针向前移动.当到达缓冲区的尾部时,指针又回到缓冲区的起始位置. 目录: 为什么使用循环缓冲区 C 实例 使用封装 API设计 确认

C 标准库IO缓冲区和内核缓冲区的区别

1.C标准库的I/O缓冲区 UNIX的传统 是Everything is a file,键盘.显示器.串口.磁盘等设备在/dev 目录下都有一个特殊的设备文件与之对应,这些设备文件也可以像普通文件(保存在磁盘上的文件)一样打开.读.写和关闭,使用的函数接口是相同的.用户程序调用C标准I/O库函数读写普通文件或设备,而这些库函数要通过系统调用把读写请求传给内核 ,最终由内核驱动磁盘或设备完成I/O操作.C标准库为每个打开的文件分配一个I/O缓冲区以加速读写操作,通过文件的FILE 结构体可以找到这

css talbe中td溢出隐藏 div溢出隐藏

td溢出隐藏 1 table{ 2 width:100px; 3 table-layout:fixed;/* 只有定义了表格的布局算法为fixed,下面td的定义才能起作用. */ 4 } 5 td{ 6 width:100%; 7 word-break:keep-all;/* 不换行 */ 8 white-space:nowrap;/* 不换行 */ 9 overflow:hidden;/* 内容超出宽度时隐藏超出部分的内容 */ 10 text-overflow:ellipsis;/* 当对

1065 A+B and C (64bit) (20)(大数相加、正溢出、负溢出)

正溢出:两个正数相加超过了该数据类型能表示的最大范围,结果为负数 负溢出:两个负数相加超过了该数据类型能表示的最小范围,结果为正数包括零 #include <algorithm> #include <iostream> #include <cstdio> #include <queue> #include <cstring> #include <vector> using namespace std; const int maxn =

JavaSE8基础 StringBuffer delete trimToSize 清空字符串缓冲区与整理缓冲区的空间

os :windows7 x64    jdk:jdk-8u131-windows-x64    ide:Eclipse Oxygen Release (4.7.0)        code: package jizuiku1; public class Demo100 { public static void main(String[] args) { StringBuffer sb = new StringBuffer(); sb.append("cnblog"); System.

缓冲区溢出攻击

缓冲区溢出(Buffer Overflow)是计算机安全领域内既经典而又古老的话题.随着计算机系统安全性的加强,传统的缓冲区溢出攻击方式可能变得不再奏效,相应的介绍缓冲区溢出原理的资料也变得“大众化”起来.其中看雪的<0day安全:软件漏洞分析技术>一书将缓冲区溢出攻击的原理阐述得简洁明了.本文参考该书对缓冲区溢出原理的讲解,并结合实际的代码实例进行验证.不过即便如此,完成一个简单的溢出代码也需要解决很多书中无法涉及的问题,尤其是面对较新的具有安全特性的编译器——比如MS的Visual Stu

缓冲区溢出攻击(待看)

缓冲区溢出攻击 本词条缺少信息栏.名片图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧! 缓冲区溢出攻击是利用缓冲区溢出漏洞所进行的攻击行动.缓冲区溢出是一种非常普遍.非常危险的漏洞,在各种操作系统.应用软件中广泛存在.利用缓冲区溢出攻击,可以导致程序运行失败.系统关机.重新启动等后果. 1简介编辑 缓冲区溢出是指当计算机向缓冲区内填充数据位数时超过了缓冲区本身的容量,溢出的数据覆盖在合法数据上.理想的情况是:程序会检查数据长度,而且并不允许输入超过缓冲区长度的字符.但是绝大多数程序都会

黑客中级技术 缓冲区溢出攻击的介绍

大家都知道缓冲区溢出是一种普遍.而且危险性极强的漏洞,在各种操作系统.应用软件中广泛存在.利用缓冲区溢出攻击,可以导致程序运行失败.系统当机.重新启动等后果. 更为严重的是,可以利用它执行非授权指令,甚至可以取得系统特权,进而进行各种非法操作. 缓冲区溢出攻击有多种英文名称:buffer overflow,buffer overrun,smash the stack,trash the stack,scribble the stack, mangle the stack, memory leak