Stack Guard and Stack Smashing Protection - canaries, memory

7

I have a few questions about Stack Guard and SSP protections. First question is about Stack Guard and its three types of canaries, if I am correctly - terminator, random and random XOR.

  1. I'd like to know, how to disabled Stack Guard on x86 Linux system? Somewhere I read, it's possible with this command, while compiling with gcc '-disable-stackguard-randomization', it's same like with this command for enable '-enable-stackguard-randomization', both doesn't work. If needed, my gcc version is 4.8.2.

  2. Next question about Stack guard, when I will able to enable/disable it, how can I set, which type of canaries I want to use? What I read, terminator canaries are used by default, for random I have to compiled with '-enable-stackguard-randomization', but how about random XOR? (Or with null 0x00000000)

  3. Now about SSP(ProPolice), I know, for random canary I have to compiled with 'fstack-protector-all', but how about terminator, is it same as in Stack Guard, by default?

  4. Last one, if anyone of you, can tell me, where I can find random canary in memory. For example, I have this scenario - compiled C program, like 'gcc -g example.c -o example -fstack-protector-all', so with random canaries. Let's say, I'm able to get address of canary, after every execution. So expect, I have: Canary = 0x1ae3f900. From a different papers, I get some info, that canary is located in .bss segment. So I get address of .bss segment using readelf: 'readelf -a ./example | grep bss'. It's 080456c9. In gdb I set some breakpoints, to get address of canary, but when I check .bss address x/20x 0x080456c9, all I see are only 0x00000000 addresses, but canary is nowhere. Plus, I checked __stack_chk_fail's if it isn't there, but with same result, I can't see it there. I get address of stack_chk_fail from PLT/GOT.

Thank in advance for your answer and time.

gcc
random
linux-kernel
x86
protection
asked on Stack Overflow Jan 18, 2015 by Yeez • edited Aug 18, 2019 by Siong Thye Goh

1 Answer

2

Stack Smashing Protection (SSP) is an improvement over StackGuard. SSP was first implemented in gcc 4.1.

I'd like to know, how to disabled Stack Guard on x86 Linux system?

Use -fno-stack-protector to disable the userland SSP.

The --disable-stackguard-randomization and --enable-stackguard-randomization are build options for glibc source code.

when I will able to enable/disable it, how can I set, which type of canaries I want to use?

This is not configurable in gcc as far as I know. Since glibc 2.10, the stack canary is generated in a function called _dl_setup_stack_chk_guard. Here is some part of 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 holds the address of the auxiliary vector entry for AT_RANDOM, which is a 16-byte random value initialized by the kernel while creating the process. If you are running on a kernel or an emulator that doesn't initialize AT_RANDOM, the check dl_random == NULL would be true and the canary used is the terminator value with the first and second most significant bytes initialized to 255 and \n, respectively. All other bytes are zero. Usually AT_RANDOM is initialized by the kernel and so the least 7 significant bytes of AT_RANDOM are copied. The last byte of canary is set to zero.

So if you want to use a particular method to generate the canary, you can change this code and build you own glibc.

As an alternative method, @PeterCordes have suggested in the comments to write your canary value to memory location %%fs:0x28 (see the code below) at the top of the main function and restore the runtime-generated canary just before returning from main.

Now about SSP(ProPolice), I know, for random canary I have to compiled with 'fstack-protector-all', but how about terminator, is it same as in Stack Guard, by default?

All variants of the -fstack-protector option use SSP. These don't affect how the canary is generated.

Last one, if anyone of you, can tell me, where I can find random canary in memory.

The canary is generated dynamically early at process startup; you can't use readelf to get the canary. According to this article, you can use the following code to get the canary when compiling for i386:

int read_canary()
{
  int val = 0;
  __asm__("movl %%gs:0x14, %0;"
          : "=r"(val)
          :
          :);
  return val;
}

and for x86_64:

long read_canary()
{
  long val = 0;
  __asm__("movq %%fs:0x28, %0;"
          : "=r"(val)
          :
          :);
  return val;
}
answered on Stack Overflow Aug 18, 2019 by Hadi Brais • edited Aug 18, 2019 by Hadi Brais

User contributions licensed under CC BY-SA 3.0