
什么是内存损坏?
内存损坏是指攻击者以一种程序不希望发生的方式,根据攻击者自己的意愿修改了程序的内存。通过破坏程序内存,攻击者可以使程序行为异常:他可能使程序泄漏敏感信息,执行自己的代码或使程序崩溃。大多数系统级漏洞利用都涉及某种内存损坏。
在本文中,我们将深入探讨内存损坏技术的基本原理:缓冲区溢出。


什么是缓冲区溢出?
缓冲区是用于保存数据的内存区域。例如,当程序接受用户输入以稍后进行操作时,必须将一大块内存留出以存储该用户输入。
而缓冲区溢出是指程序将数据写入缓冲区时,该数据占用的空间大于为该缓冲区分配的内存,从而导致数据覆盖相邻的内存位置。


在缓冲区溢出发生之前,内存分配如下所示:


如果输入大小不超过缓冲区,则一切正常:


但是,当用户输入的大小超过缓冲区的大小时,用户输入可能会覆盖其他可能重要的程序数据:



具体来分析下栈缓冲区溢出与堆缓冲区溢出:
缓冲区溢出主要有两种类型:栈(stack)溢出和堆(heap)溢出。
栈溢出会损坏在栈上的内存。这意味着局部变量,函数参数和返回地址的值会受到影响。
而堆溢出是破坏位于堆上的内存的溢出。它的影响更大,全局变量和其他程序数据都会受到影响。

而这些攻击导致的潜在后果是什么呢?
攻击者对缓冲区溢出的处理方式取决于缓冲区所在的位置以及采用的保护措施。
1.重定向程序流
在栈溢出和堆溢出中,攻击者都可以覆盖程序中的重要控制变量来重定向程序流。例如,攻击者可以覆盖用于身份验证的key值,从而到达应用程序中的限制区域。
不仅如此,攻击者也有可能通过覆盖某些函数指针和异常处理程序来重定向程序流。
2.代码执行
在堆栈溢出攻击中,如果攻击者能够讲自己设计的代码植入内存中,则他可以覆盖堆栈上的返回地址,从而使其指向恶意代码的位置。这样,攻击者可以在当前函数返回后将程序执行重定向到他的代码片段,实现攻击。
3.拒绝服务
即使攻击者无法用特定的方法重定向程序流或无法实现执行代码,溢出也会导致程序数据损坏,从而导致该程序崩溃。
4.防止缓冲区溢出
目前很多公司企业已经开发出多种技术来减少缓冲区溢出的风险。这里我们不做讨论。

我们主要再聊一聊操作系统级别的防御:
先来普及下栈的警惕标志:
栈的警惕标志(stack canary),得名于煤矿里的金丝雀,用于探测该灾难的发生。具体办法是在栈的返回地址的存储位置之前放置一个整形值,该值在装入程序时随机确定。栈缓冲区攻击时从低地址向高地址覆盖栈空间,因此会在覆盖返回地址之前就覆盖了警惕标志。栈返回前会检查该警惕标志是否被篡改。
今天只是了解简单的概念即可,之后笔者在后续的文章中再深入它们。目前我们只需要知道栈的警惕标志是在返回地址之前放置在内存中的随机值。
为了覆盖返回地址并重定向程序流,攻击者还必须覆盖栈的警惕标志。因此,该程序能够通过检查canary值是否正确来检测栈溢出。

在缓冲区溢出发生之前,金丝雀的值为随机值:


缓冲区溢出后,Canary值会更改:


此时,系统会检测到攻击,并且不会重定向到攻击者控制的地址。
但是这样的弊端也很明显,这会加大开发难度,但是如果栈的警惕标志可能提前被泄漏或被强行使用,则可以绕过栈的警惕标志保护。
此时,攻击者还可以通过其他方式更改程序流(而不是覆盖返回地址)来绕过栈的警惕标志,例如,通过覆盖函数的重要控制变量。

地址空间布局随机化
地址空间布局随机化即ASLR,随机化内存布局并使栈,堆和库的地址不可预测。这样可以防止攻击者预测要跳转到的内存地址,并使代码执行攻击变得更加困难。

可执行的空间保护
这是防止基于溢出的代码执行的另一种方法,将内存区域标记为不可执行。这意味着,即使攻击者设法植入了恶意代码,也会将其视为数据而非代码,因此程序不会执行它。
但是,这种方法也不能使程序完全不受代码执行的影响:攻击者可能仍会使用诸如面向返回的编程之类的技术来实现相同的目标。
所以还是从根源上的做法,尽可能安全的编码以防止缓冲区溢出

1.输入大小边界检查:
代码执行输入进行大小边界检查,以确保用户输入可以包含在分配的缓冲区空间内。特别注意,要谨慎处理写入数组和格式字符串的用户输入。

2.使用安全函数
开发人员应将未经过边界检查的函数替换掉。例如,在C语言中,printf(), sprintf(), strcat(), strcpy(), 和 gets() 都是不安全的函数,而 sprintf(), strncpy(), strncat(), fgets() 这些则是安全函数。

参考文献:
图源来自网络,仅作补充
https://zh.wikipedia.org/zh-hans/%E6%A0%88%E7%BC%93%E5%86%B2%E5%8C%BA%E6%BA%A2%E5%87%BA#:~:text=%E6%A0%88%E7%9A%84%E8%AD%A6%E6%83%95%E6%A0%87%E5%BF%97%EF%BC%88stack,%E8%AD%A6%E6%83%95%E6%A0%87%E5%BF%97%E6%98%AF%E5%90%A6%E8%A2%AB%E7%AF%A1%E6%94%B9%E3%80%82
https://www.cnblogs.com/fanzhidongyzby/p/3250405.html
https://blog.csdn.net/FrankieWang008/article/details/6924499
https://www.slideserve.com/yetta-owen/6606550
https://blog.usejournal.com/binary-exploitation-buffer-overflows-a9dc63e8b546