栈溢出:
栈溢出是缓冲区溢出的一种,分配的内存空间是有限的,如果输入超长的字符串必然会导致溢出。缓冲区溢出中最危险的是堆栈溢出,因为入侵者可以利用堆栈溢出,在函数返回时改变返回程序的地址,让其跳转到任意地址,带来的危害一种是程序崩溃导致拒绝服务,另外一种就是跳转并且执行一段恶意代码比如得到系统权限。
原理:
先看一段代码:
char dest[10];
scanf("%s",dest);
这两行代码声明了一个局部变量,然后用scanf函数读入字符串,但是这个程序没有限制字符串长度的地方。如果用户输入的字符串长度大于十个字符,那么就会产生栈溢出。
而函数的局部变量是存储在栈中的,这种错误就是栈溢出。
利用:
还是刚才的那一段代码:
char dest[10];
scanf("%s",dest);
编译之后用ida打开,应该是一个普通栈应该有的结构:
-0000000C dest db ? ;
-0000000b db ? ;
-0000000a db ? ;
-00000009 db ? ;
-00000008 db ? ;
-00000007 db ? ;
-00000006 db ? ;
-00000005 db ? ;
-00000004 db ? ;
-00000003 db ? ;
-00000002 db ? ;
-00000001 db ? ;
+00000000 s db 4 dup(?)
+00000004 r db 4 dup(?)
+00000008
+00000008 ; end of stack variables
dest就是刚才scanf读入字符串的存放位置。下面的“s”代表ebp寄存器(扩展基址指针寄存器,其内存放一个指针,该指针指向系统栈最上面一个栈帧的底部。)的位置,“r”代表的就是函数的返回位置。
如果我输入的字符串过长,比如“aaaaaaaaaaaa”+“bbbb”+“cccc”,那么现在栈中的数据会是这样:
-0000000C dest db 'a' ;
-0000000b db 'a' ;
-0000000a db 'a' ;
-00000009 db 'a' ;
-00000008 db 'a' ;
-00000007 db 'a' ;
-00000006 db 'a' ;
-00000005 db 'a' ;
-00000004 db 'a' ;
-00000003 db 'a' ;
-00000002 db 'a' ;
-00000001 db 'a' ;
+00000000 s db 4 dup("bbbb")
+00000004 r db 4 dup("cccc")
+00000008
+00000008 ; end of stack variables
可以看到原来应该是函数返回地址的地方被覆盖了,现在函数返回的时候eip指针值变成了“cccc”如果这里不是“cccc”而是精心计算好的地址,那么就会控制eip(执行接口程序)然后系统就会被黑客任意跳转,并以此为跳板进而控制电脑。