事实上,这是一种相当新的缓解机制,旨在避免泄漏有关崩溃应用程序堆栈的信息。
您看到的“ <unknown>
”(这是由 加入的静态字符串-fstack-protector
)以前是argv[0]
. 但是,一些攻击者开始利用您可以溢出堆栈的事实,到达argv[0]
并使用您选择的地址覆盖它。实际上,如果您可以控制地址 atargv[0]
并使应用程序崩溃,则可以将整个堆栈泄漏到应用程序之外。
该技术主要用于fork()
用于重新生成实例的服务器。正如fork()
克隆初始进程的内存一样,ASLR 是无用的,因为使用了相同的起始内存映像,然后一次又一次地使用相同的内存映射。
如果堆栈中存储了密钥或某些机密数据,则攻击者可以通过此功能访问它。
这就是为什么在去年的某个时候,一些开发人员决定argv[0]
在显示有关堆栈粉碎的信息时避免使用<unknown>
.
这是Unix/Linux Stack-Exchange 站点上的一个答案,它指出了glibc
对此负责的代码部分。
void
__attribute__ ((noreturn))
__fortify_fail_abort (_Bool need_backtrace, const char *msg)
{
/* The loop is added only to keep gcc happy. Don't pass down
__libc_argv[0] if we aren't doing backtrace since __libc_argv[0]
may point to the corrupted stack. */
while (1)
__libc_message (need_backtrace ? (do_abort | do_backtrace) : do_abort,
"*** %s ***: %s terminated\n",
msg,
(need_backtrace && __libc_argv[0] != NULL
? __libc_argv[0] : "<unknown>"));
}
并且,这是介绍补丁的原始提交的注释:
避免来自__stack_chk_fail
[BZ #12189] 的回溯
__stack_chk_fail
在损坏的堆栈上调用。堆栈回溯对于损坏的堆栈非常不可靠。__libc_message
更改为仅当操作包括 时
接受
enum __libc_message_action
并调用。 添加是为了避免从
.BEFORE_ABORT
do_backtrace
__fortify_fail_abort
__stack_chk_fail
我本来想提供更多关于这个缺陷的英文参考资料和文章,但似乎没有人写过这件事......对不起。
这是一篇解释它的文章(法语):