图文并茂版本,虽然技术老了点,但是很适合对Stack Overflow感兴趣的朋友,
嗯。。。适合初学者,对于正在成为牛和已经成为牛的家伙们,请当没有该文档,
谢谢牛们不看这篇文档,谢谢-_-~
PDF Version Download:
http://www.cisrg.cn/forum/viewtopic.php?id=2397
可爱的栈溢出
现今的概念开始明确起来,以前的堆栈溢出先被明确为缓冲区溢出,又再次的被明确为栈溢出,其实这种漏洞类型也很明显的体现了堆和栈的区别。
记得在刚开始学C的时候,也总是堆栈不分,也喜欢很酷的把基于栈的缓冲区溢出漏洞,呼喊成堆栈溢出。单实际上,堆和栈是完全不同的东西。好了,废话少说了,我们来看下栈溢出。
缓冲区溢出漏洞,是由于大的缓冲区数据覆盖了小的缓冲区数据所致;从Intel架构来考虑,由于前期给变量分配的内存空间比较小,而把一个大于该变量内存空间的数据复制到了该变量的内存中,从而导致覆盖掉了前面保存的栈数据,触发缓冲区溢出漏洞;使程序可以被攻击者控制。缓冲区溢出多发生在strcpy、strcat、sprintf、fgets、strncpy、strncat、snprintf、sscanf、fscanf、vscanf这些函数上,实际情况下,我们不要错误的认为strncpy这样的函数是安全函数,因为程序员的编码不谨慎则会触发安全漏洞。
敏感函数导致栈溢出的例子:
还有很多存在栈溢出的原因是程序员自己的编码错误,针对敏感函数的例子已经给出了,现在我们来看个实际的程序员编码错误导致栈溢出的例子。
观察下图的函数,看是否存在栈溢出呢?
(自定义函数)
通过观察这个测试函数,我们可以得到下面的结论:
A、 该函数如果正常调用的话,不会出发缓冲区溢出。
B、 该函数被错误调用,则被触发栈溢出。
C、 如果上述函数的参数被黑客所控制,那么就可在某种程度上构造长字符串,实现栈溢出。
下面是我们错误传值的情况,很多情况下,程序员都无法100%的保证自己书写代码的安全性。
经过上面的错误传值过程,我们看到程序执行出错了:)
开启默认的调试器进行调试。
由于大数据覆盖掉小数据,使原先的栈空间保存的ESP寄存器数值被覆盖,导致EIP执行出错,0x61616161很明显是aaaa的16进制,
下面我们来分析下导致栈溢出的原因。
函数入栈前的情况:
Eax=src
Ecx=dst
刚进入函数内部的汇编代码,该处的汇编代码主要为创建栈框架,遵循Intel创建栈的规则。
下面来看下ESP的数据情况:
0040108A 这个地址是否熟悉?看上图请。
0012FF70是否熟悉?参数1的地址。
0012FB70是否熟悉?参数2的地址。
看该处,在ret返回前ESP的值已经被N多的61覆盖,那么此时如果ret指令往下执行,则EIP为可控制。