这是一个非常丑陋的C程序:

 #include <stdio.h>
 #include <string.h>
 int main(int argc, char *argv[])
 {
    char buffer[10];
    memcpy(buffer,argv[1],strlen(argv[1]));
    printf("%s\n", buffer);
    return 0;
 }


我正在使用堆栈粉碎保护功能编译该程序:

 $ gcc -fstack-protector smash.c -o smash


这是我在执行过程中得到的内容:

 $ ./smash 01234567890
 01234567890v?\??nr?!??U
 *** stack smashing detected ***: <unknown> terminated


保护工作正常,但我不明白为什么我看到的不是argv[0]

#1 楼

似乎您正在覆盖argv数组本身,因此错误处理程序无法检索argv[0]值。

#2 楼

实际上,这是一种相当新的缓解机制,旨在避免泄漏有关崩溃的应用程序堆栈的信息。

您看到的“ <unknown>”(由-fstack-protector添加的静态字符串)是以前argv[0]。但是,一些攻击者开始利用这一事实,即您可能会使堆栈溢出,到达argv[0]并用您选择的地址覆盖它。实际上,如果可以控制argv[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的回溯。


我希望提供更多关于该缺陷的英文参考文献和文​​章,但似乎没人写过这个东西。不好意思

这是一篇用法语解释的文章:


堆栈粉碎保护器:fuite d'informations


评论


嗯,我真的很不高兴未能找到引用......唯一的好参考,我发现是法语。因此,如果有人可以提供很好的参考或链接(以可理解的语言),请随时在评论中提出建议。我将编辑答案以将其集成。

–恐怖
19/12/6在8:26



#3 楼

strlen返回字符串的长度,不包括结尾的NULL字符,因此,memcpy仅复制提供的字符,但末尾没有0

printf将打印得到的所有内容,直到遇到NULL为止,并因此打印这些“随机”字符。

评论


我了解,但这不是我的问题。我的问题在第二行:应该包含argv [0]

–Bob5421
19年11月3日在8:27

请将此澄清添加到您的问题中,因为“我不明白为什么我看到而不是argv [0]”尚不清楚。

–bart1e
19年11月3日在12:05

抱歉,stackexchange认为是标签!

–Bob5421
19年11月3日,12:26