缓冲区溢出攻击的分析

时间:2022-09-28 07:45:27

缓冲区溢出攻击的分析

所谓缓冲区溢出攻击,就是一种利用目标和程序的缓冲区溢出漏洞,通过操作目标程序堆栈并暴力改写其返回地,从而获得目标探制权的攻击手段。

(1)缓冲区溢出攻击的内存模型。为了理解缓冲区溢出的本质,需要先对程序运行时计算机中的内存是如何分配的所以认识。一般而言,操作系统会分配给第一个进程独立的虚拟地址空间,它们是实际空间的映射。当编译后的C程序运行时,内存将被划分为代码区、数据区和堆栈区。其中代码区的数据区构成表态内存,在程序运行之前这些部分的大小已经固定,而与之相对的则是动态的堆栈区内容:堆和堆栈。在C程序中,堆栈和堆都可以被利用来进行溢出。在C程序中,每当调用函数时,就会自动处理堆栈分配。堆栈起到了保存有关当前函数调用上下文的容器的作用,许多内容都可能进入堆栈区,通常其内容与计算机体系结构和编译器相关。一般而言,如下内容都将被储存在堆栈中:函数的非静态局部变量值、堆栈基址、当函数返回时程序就该跳转到的地址以及传递到函数中的参数。当发生函数调用时,编译器所执行的步骤如下:

①调用者。首先,调用者将被调用的函数所需的所有参数都压入堆栈,之后堆栈指针自动更改到指向当前栈顶。接着随着系统不同,调用者可能压入一些其他数据来保护现场。完成后,调用都使用调用指令来调用数,调用指令将返回地址(IP)压入堆栈,并相应更新堆栈指针。最后,调用指令将程序计数器设置为正被调用的函数地址,执行权交给被调用函数。进入第二步操作。

②被调用者。首先,被调用者将堆栈基址指针(BP)寄存器内容压入堆栈来保存调用者的堆栈基址,并更新堆栈指针到旧的基址。然后设置BP内容为自己的堆栈基址,亦即当前的真人真事指针。然后,被调用者按照局部变量的声明移动堆栈指针,为所有非静态局部变量分配足够的空间,执行被调用函数的操作。

③调用函数结束。当被调用函数执行完毕后,调用者更新堆栈指针以指向返回地址IP,调用返回指令将程序控制权交给返回地址上的程序,然后恢复被保存的运行环境。

从以上的过程中可以看到,发生函数调用时的堆栈分配过程中,非静态局部变量缓冲区的分配和填充不是同时进行的,并且依据不同的标准。局部变量缓冲区的分配是依据局部变量的声明,而填充则是依据其实际被赋予的值,由此引发了安全漏洞。

(2)缓冲区溢出攻击的工作原理。根据上一节的讨论,当实际输入的局部变量值的长度超出缓冲区长度,而程序中又缺乏边界检查机制时,数据就会继续向栈底写入,导致栈中老的元素被覆盖。而被改写的将是栈基址BP和返回地址IP,这样缓冲区溢出攻击就可以实现了。只要在程序运行时传送给它一个足够大的参数,就可以在返回地址中填入一个希望程序转向的任意内存地址,从而近代制了程序的运行权。而且此时拥有的权限与运行程序所需的权限相同。这就是缓冲区溢出攻击的原理。实际操作中还存在两个问题:

①攻击代码植入目标程序地址空间。这可以通过以下两种方法来解决:利用已经存在的代码。可以利用被攻击的程序中的代码来达到攻击目的。此时,攻击者只需对代码传递指定参数,将代码植入堆栈区或数据区,然后使程序控制权转给目标代码。常见的方法是通过溢出代码传送攻击代码,此时攻击代码将出现在堆栈局部变量缓冲区中;另一种方法是将攻击代码存方在变量值中,此时攻击代码将被存方在数据区中。

②改写返回地址为攻击代码地址以获得程序控制权。由于程序的堆栈区起始地址是固定的,因此很容易获得堆栈起始地址。但对于攻击代码的精确地址则需要仔细分析目标程序的反汇编代码蔌多次试验来得到。对此,可以在攻击代码前插入大量空操作来大大降低其难度。这样,只要得到了攻击代码的近似地址而非准确地址,就可以使攻击代码运行。实践证明,这可以相当有效地减少定位攻击代码所需的时间,然后只要溢出一个没有边界检查的缓冲区,以暴力手段改写返回地址IP就可以了。

实际上,常见的缓冲区溢出攻击都是一次完成攻击代码植入和程序转向攻击代码两种功能。攻击者找到一个溢出漏洞,然后向被攻击程序传送一个很大的字符串(其中包括攻击代码),在引发缓冲溢出的同时植入了攻击代码,这就是缓冲区溢出的Levy攻击模版。当然,也可以通过多次完成代码植入和缓冲区溢出的动用,可以在一个缓冲区内放置代码而不溢出它,之后再通过溢出另一个缓冲区来来将程序指针定位到攻击代码。这种方法一般用来解决可供溢出的缓冲区不足以容纳全部攻击代码的问题。

上一篇:数学课应和信息技术亲密接触 下一篇:浅谈培养学生数学创新思维的途径