Stack Guard and Stack Smashing Protection - canaries, memory
Asked Answered
D

1

8

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, 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 I expect 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.

Drummer answered 18/1, 2015 at 20:47 Comment(3)
Also see Qualys Security Advisory - The Stack Clash on OSS-Security mailing list. Its shows off some neat tricks, and its pretty damning of the guard page. Its amazing how many OS'es they took down with it.Hypnogenesis
You can override the default by compilign with gcc -fno-stack-protector or gcc -fstack-protector=strong. When and how to use GCC's stack protection feature? and gcc.gnu.org/onlinedocs/gcc/…. See also Why does this memory address %fs:0x28 ( fs[0x28] ) have a random value? which points out that normal stack-protector randomizes the stack cookie.Matteo
Correction, the option to enable it is -fstack-protector-strong, not =.Matteo
C
3

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;
}
Chandachandal answered 18/8, 2019 at 19:34 Comment(2)
you can change this code and build you own glibc. Or potentially just write to %%fs:0x28 at the top of main, and restore the original canary value before returning in case main itself or any CRT start functions used stack-protection. Or call exit instead of letting main return so you don't need to restore the old stack canary. IDK if an exception could unwind through main and lead to a stack-protector check fail, but probably not because any top-level exception catching probably aborts instead of returning.Matteo
If you call exit instead of returning from main, you don't need to restore the old stack canary. main's stack-cookie check code won't be reached (and its return address won't be used either). So calling exit simplifies main.Matteo

© 2022 - 2024 — McMap. All rights reserved.