Linux上最新GCC版本提供了三种对抗缓冲区溢出攻击的机制
--1. 栈随机化
攻击者对系统攻击时不但需要插入代码,还需要插入指向这段代码的指针,这个指针也是攻击字符串的一部分,而产生指针需要知道这个字符串的栈地址,在过去,不同的机器上栈的位置是相当固定的,栈随机化可以解决这种问题,它使得栈的位置在程序每次运行时都发生变化。
实现方式:在程序开始执行时,在栈上分配一段0-n字节的随机大小的空间,比如:用alloca函数在栈上分配指定字节数量的空间。程序不使用这段空间,但它会导致程序每次执行时后续的栈位置发生变化,分配的范围n必须足够大,才能得到足够多得栈地址变化,但也不能太大,否则会浪费程序太多空间。
--2. 栈破坏检测
栈的破坏一般发生在局部缓冲区越界的时候,最新的GCC版本在产生的代码虫加入了一种栈保护者(stack protector)机制,用来检测缓冲区是否越界。
实现方式:在栈帧中任何局部缓冲区与栈状态之间存储一个特殊的金丝雀(canary)值,也称为哨兵值(guard value),随机产生于程序每次运行时。因此,在恢复寄存器状态和从函数返回之前,程序检查这个值是否被函数的某个操作篡改了,如果是,那么程序会异常终止。
--3. 限制可执行代码区域
用来消除攻击者向系统宏插入可执行代码的能力,基本思想是限制那些能够存放可执行代码的存储器区域。
实现方式:令只有保存编译器产生的代码的那部分存储器才能够执行,其他部分只允许读和写。
参考资料:CSAPP