3.2.3 缓冲区溢出法
来源:安全中国
3.2.3 缓冲区溢出法
缓冲区溢出是利用系统中的堆栈实现的。下面以32位的CPU的堆栈操作为例来说明缓冲区溢出的攻击原理。
当CPU执行入栈(PUSH)操作时,首先将堆栈寄存器ESP减4,然后将数据存入由ESP指向的存储单元;而执行出栈操作时,则先取出由ESP指向的存储单元中的数据,然后将ESP加4。
在调用函数时,CPU先将下一条指令的地址值(返回地址)EIP入栈保存,然后再依次(从左至右或从右至左)把函数的参数入栈。如果函数内部还有局部变量时,则在堆栈中再开辟空间以保存这些变量。正常情况下,函数调用结束时,由函数参数和局部变量所占用的堆栈空间全部被释放出栈,并恢复EIP寄存器的值开始执行下一条指令。同时,堆栈指针被恢复成函数调用前的状态。图3-2描述了正常调用C函数main(int arg ,char *arv)时,堆栈指针的变化情况(C语言中的函数参数是从右至左依次入栈的)。
假设C函数定义为:
int main(int arg ,char *arv){ char buff[60];strcpy(buff , arv);}
由于字符串处理函数没有对超长字符加以判断和限制,因此,那些超出缓冲区长度的字符内容必将覆盖缓冲区以外的数据。在函数main( )中,如果使用strcpy( )函数把多于60个字符的字符串复制到堆栈内的缓冲区中,则堆栈中的其他数据将会被覆盖。如果精心设计所覆盖的内容,如用特定的地址值覆盖堆栈中的EIP值(图3-2中的斜体字部分就是覆盖后的堆栈内容),那么,当函数调用结束时,就会将这个特定的地址值赋给指令寄存器EIP,进而导致指令执行的顺序发生改变。这就是缓冲区溢出攻击的实现原理。
图3-2 正常调用C函数时堆栈指针的变化情况