我对Stack Guard和SSP保护有一些疑问。如果我正确的话,第一个问题是关于Stack Guard及其三种类型的Canary-终止符,随机和随机XOR。

  • 我想知道,如何在x86 Linux系统上禁用Stack Guard?在我读过的某个地方,可以使用此命令,而在使用gcc' -disable-stackguard-randomization '进行编译时,就像使用此命令来启用' -enable-stackguard-randomization '一样,两者均无效。如果需要,我的gcc版本是4.8.2。
  • 关于堆栈保护的下一个问题,何时可以启用/禁用它,如何设置,要使用哪种类型的金丝雀?我读到的内容是,默认情况下使用终结者金丝雀,对于随机性,我必须使用 -enable-stackguard-randomization 进行编译,但是随机XOR怎么样? (或为空0x00000000)
  • 现在,关于SSP(ProPolice),我知道,对于随机的金丝雀,我必须使用' fstack-protector-all '进行编译,但是终止符又如何,默认情况下与Stack Guard中的相同?
  • ,如果有人,可以告诉我,我在哪里可以找到内存中的随机金丝雀。例如,我有这种情况-编译的C程序,例如' gcc -g example.c -o example -fstack-protector-all ',因此使用随机金丝雀。假设,每次执行后,我都能获得金丝雀的地址。因此,我的期望是: Canary = 0x1ae3f900 。从不同的论文中,我得到了一些信息,即金丝雀位于.bss段中。因此,我使用readelf获取.bss段的地址:' readelf -a ./example | grep bss '。是080456c9。在gdb中,我设置了一些断点,以获取金丝雀的地址,但是当我检查.bss地址x/20x 0x080456c9时,我看到的只是0x00000000地址,但是
    金丝雀不在。另外,我检查了 __stack_chk_fail 是否不存在,但是结果相同,我在那里看不到它。我从PLT/GOT获取stack_chk_fail的地址。

  • 预先感谢您的答复和时间。

    最佳答案

    堆栈防砸保护(SSP)是对StackGuard的改进。 SSP最初是在gcc 4.1中实现的。



    使用-fno-stack-protector禁用用户态SSP。
    --disable-stackguard-randomization--enable-stackguard-randomization是glibc源代码的构建选项。



    据我所知,这在gcc中是不可配置的。从glibc 2.10开始,堆栈canary是通过称为_dl_setup_stack_chk_guard的函数生成的。这是its code的一部分:

      if (dl_random == NULL)
        {
          ret.bytes[sizeof (ret) - 1] = 255;
          ret.bytes[sizeof (ret) - 2] = '\n';
        }
      else
        {
          memcpy (ret.bytes, dl_random, sizeof (ret));
          ret.num &= ~(uintptr_t) 0xff;
        }
    
    dl_random保留AT_RANDOM的辅助向量条目的地址,它是内核在创建进程时初始化的16字节随机值。如果您在未初始化AT_RANDOM的内核或仿真器上运行,则check dl_random == NULL将为true,并且使用的canary是终止符值,其第一个和第二个最高有效字节分别被初始化为255和\n。所有其他字节均为零。通常,AT_RANDOM由内核初始化,因此AT_RANDOM的至少7个有效字节被复制。金丝雀的最后一个字节设置为零。

    因此,如果要使用特定的方法生成金丝雀,则可以更改此代码并构建自己的glibc。

    作为一种替代方法,@ PeterCordes在注释中建议将金丝雀值写入%%fs:0x28函数顶部的内存位置main(请参见下面的代码),并在从main返回之前恢复运行时生成的金丝雀。


    -fstack-protector选项的所有变体都使用SSP。这些不会影响金丝雀的生成方式。



    金丝雀是在流程启动的早期动态生成的;您不能使用readelf来获取金丝雀。根据this的文章,在为i386进行编译时,可以使用以下代码来获取canary:
    int read_canary()
    {
      int val = 0;
      __asm__("movl %%gs:0x14, %0;"
              : "=r"(val)
              :
              :);
      return val;
    }
    

    对于x86_64:
    long read_canary()
    {
      long val = 0;
      __asm__("movq %%fs:0x28, %0;"
              : "=r"(val)
              :
              :);
      return val;
    }
    

    关于gcc - Stack Guard和Stack Smashing Protection-金丝雀,内存,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28020213/

    10-11 18:22