amj*_*jad 2 c stack callstack x86-64 buffer-overflow
我正在阅读一本教科书,它描述了能够检测堆栈何时损坏的防御。书中说:
最新版本的 gcc 在生成的代码中加入了一种称为堆栈保护器的机制,以检测缓冲区溢出。这个想法是在任何本地缓冲区和堆栈状态的其余部分之间的堆栈帧中存储一个特殊的金丝雀值,如下图所示:

这个 canary 值,也称为 aguard 值,在程序每次运行时随机生成,因此攻击者没有简单的方法来确定它是什么。在恢复寄存器状态并从函数返回之前,程序检查金丝雀是否已被此函数的某些操作或它调用的某个操作更改。如果是这样,程序会因错误而中止。
我明白了,但我仍然认为这个设计存在缺陷。是的,攻击者可能无法确定 canary 的值是多少,但攻击者知道 canary 的大小(8 字节),因此攻击者可以操纵指针绕过 canary 所在的堆栈中的这 8 字节区域,然后覆盖返回地址,所以金丝雀实际上什么都不保护,我的理解是否正确?
如果攻击者具有任意写入,那么是的,金丝雀是无用的。事实上,任意写入可以通过多种方式使金丝雀失效,包括覆盖__stack_chk_fail(金丝雀被覆盖时调用的函数)的 GOT 条目,或者只是不覆盖金丝雀开始。但是,并不总是可以获得任意写入。它通常仅在存在格式字符串漏洞时发生。当只有缓冲区溢出时,要写入金丝雀之后的地址,您必须写入该地址之前的地址,其中包括金丝雀。这意味着用缓冲区溢出覆盖返回地址的唯一合理方法是猜测金丝雀或通过另一个漏洞泄漏它。