canary的前世今生

1.gs:14

这个地址是在tls存储的,据说不会映射到虚拟内存中。

然而发现0xb7e20914的值始终和canary相同。

回溯发现0xb7e20914是由

0xb7ffef0c<_dl_random>:0xbffff53b

地址的值赋予的。

2.程序初始过程

用户态下面:

动态链接库ld-linux.so.2

_start->_ld_start->_ld_start_finish->_ld_sysdep_start->dl_main->security_init(而在security_init中实现了对0xb7e20914的赋值)

而在_start前面,内核已经初始化用户栈,并且0xbffff53b已经完成赋值。

完整过程:

user:bash通过fork()生成一个新的进程,继而调用excve()执行ELF文件

kernel:sys_execve()->do_execve()->search_binary_handle()

  boot_init_stack_canary()->get_random_bytes()->extract_entropy()

user:_start->_ld_start->_ld_start_finish->_ld_sysdep_start->dl_main->security_init(ld-linux-so.2)

_start->_libc_start_main->exit

3.操作系统版本

/* Support for the AT_RANDOM auxiliary vector entry was added in 2.6.29. */
#if __LINUX_KERNEL_VERSION >= 0x02061d
# define __ASSUME_AT_RANDOM    1
#endif

 

static inline uintptr_t __attribute__ ((always_inline))
_dl_setup_stack_chk_guard (void *dl_random)
{
  union
  {
    uintptr_t num;
    unsigned char bytes[sizeof (uintptr_t)];
  } ret;

#ifndef __ASSUME_AT_RANDOM
  if (__builtin_expect (dl_random == NULL, 0))
    {
      const size_t filllen = sizeof (ret.bytes) - 1;
      ret.num = 0;
# ifdef ENABLE_STACKGUARD_RANDOMIZE
      int fd = open_not_cancel_2 ("/dev/urandom", O_RDONLY);
      if (fd >= 0)
    {
      ssize_t reslen = read_not_cancel (fd, ret.bytes + 1, filllen);
      close_not_cancel_no_status (fd);
      if (reslen == (ssize_t) filllen)
        return ret.num;
    }
# endif
      ret.bytes[filllen - 2] = 255;
      ret.bytes[filllen - 3] = '\n';
    }
  else
#endif
    {
      /* We need in the moment only 8 bytes on 32-bit platforms and 16
     bytes on 64-bit platforms.  Therefore we can use the data
     directly and not use the kernel-provided data to seed a PRNG.  */
      memcpy (ret.bytes, dl_random, sizeof (ret));
#if BYTE_ORDER == LITTLE_ENDIAN
      ret.num &= ~0xff;
#elif BYTE_ORDER == BIG_ENDIAN
      ret.num &= ~(0xff << (8 * (sizeof (ret) - 1)));
#else
# error "BYTE_ORDER unknown"
#endif
    }
  return ret.num;
}

这表明当Linux kernel>2.6.29时,canary是由Linux内核生成的(_dl_random)保存的值;否则canary由"/dev/urandom"生成或直接赋值为0xff0a0000。最后将canary的最后一个字节改为00字节。

 4.源码

canary可能在binfmt_elf.c的create_elf_tables中实现,而ASLR可能在load_elf_binary->arch_randomize_brk中实现

posted @ 2016-04-27 15:11  大魔王Faker  阅读(1466)  评论(0编辑  收藏  举报