完成端口 堆栈溢出_函数调用之堆栈原理(终章)--缓冲区溢出

860563f37a69bb221c9ecd82b6787f2a.png

现在你已经很好地掌握了堆栈的操作方式,所以让我们来看看有史以来最臭名昭著的一个BUG:堆栈缓冲区溢出。示例程序如下:

Vulnerable Program - buffer.c

void doRead()
{
        char buffer[28];
        gets(buffer);
}

int main(int argc)
{
        doRead();
}

上面示例程序是从标准输入读取的。gets函数一直读取,直到遇到换行符或文件结束。下面是读取字符串后堆栈的样子:

d58a532ec3cf2fa366256a3b1c8f491c.png

这里的问题是gets不知道缓冲区的大小:它将愉快地继续读取输入并将数据填充到缓冲区之外的堆栈中,删除保存的ebp值、返回地址和下面的任何内容。为了利用这种漏洞,攻击者制造一个精确的“输入内容”并将其输入程序。下图是堆栈在攻击后的样子:

c3a441dbb502984ac79cdf8444120837.png

其基本思想是提供要执行的恶意程序代码,并覆盖堆栈上的返回地址以指向该代码。这有点像病毒入侵细胞,破坏它,并引入一些RNA来实现它的目标。

和病毒一样,这个漏洞的有效“负载”也有许多显著的特征。它从几个nop指令开始,以增加恶意代码被成功执行的几率。这是因为返回地址是绝对的,必须猜测,因为攻击者不知道他们的代码将存储在堆栈的哪个位置。但是,只要它们停留在一个nop上,这个漏洞就会起作用:处理器将执行nop,直到它遇到可以工作的指令为止。

exec /bin/sh表示执行shell的原始汇编指令(例如,假设该漏洞位于一个联网程序中,因此该漏洞可能提供对系统的shell访问)。将汇编指令嵌入到一个程序中,使程序产生一个命令窗口或者用户输入,这种想法是很可怕的,但是,那只是让安全研究如此有趣且“脑洞大开”的一部分而已。有时脆弱的程序会对其输入调用tolower或toupper,迫使攻击者编写不属于大写或小写ascii字母范围的汇编指令。因为改变大小写的话,栈上的值就会改变,跟攻击者的预期不一致。

最后,攻击者将猜测的返回地址重复几次,以获得对他们有利的机会。通过从一个4字节的边界开始并提供多次重复,它们更有可能覆盖堆栈上的原始返回地址

值得庆幸的是,现代操作系统有许多针对缓冲区溢出的保护措施,包括非可执行堆栈和堆栈金丝雀。“金丝雀”这个名字来自煤矿用语中的金丝雀,是计算机科学丰富词汇中的一个补充。用史蒂夫·麦康奈尔的话来说:

计算机科学拥有任何领域中最丰富多彩的语言。在其他的领域,你能走进一个无菌室,小心翼翼地控制在68°F,并找到病毒、特洛伊木马、蠕虫、昆虫、炸弹、崩溃以及致命错误吗?-- Steve McConnell 《代码大全2》( 就是说在其他领域,你遇不到这么包罗万象的术语

无论如何,堆栈金丝雀是这样的:

d47151c02ecac99c4c0bf738b026abf8.png

金丝雀是由编译器实现的。例如,GCC的堆栈保护选项会导致在任何可能易受攻击的函数中使用金丝雀。函数序言将一个幻数加载到canary位置,而在函数调用后该值应该还是完整的。如果不是,则可能发生缓冲区溢出(或错误),并通过__stack_chk_fail中止程序。由于它们在堆栈上的战略位置,金丝雀使得利用堆栈缓冲区溢出变得更加困难。

这就完成了我们在堆栈深处的旅程。我们不想贪得无厌地深挖。下周,我们将在抽象上更进一步,深入研究递归等。在结束这段开场白和结束语之前,我想引用一句铭刻在美国国家档案馆纪念碑上的名言:

fc1b81f90fb950cb1237344fb624a1f3.png
过去只是未来的序曲
译者注:
金丝雀的典故:早期地下采煤的时候,矿井中都有金丝雀,因为它对于甲烷和一氧化碳等致命毒气非常敏感,如果有毒气,金丝雀就会死去,从栖木上掉下来。矿工就知道是时候离开了。过一段时间之后,如果新换上的金丝雀安然无恙,矿工们又可以安全地重返矿井。

7e35b75df564cc76227363e5275da27c.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值