cannary

canary是Linux为防止栈溢出的一种保护机制,接着我们分析glibc对canary的实现过程,首先给出跟canary相关的调用栈:

  • security_init()  //在elf/rtld.c中
  • dl_main() 在elf/rtld.c中
  • _dl_sysdep_start() 在elf/dl-sysdep.c中
  • _dl_start_final() 在rtld.c中
  • _dl_start() 在rtld.c中
  • _start() /lib/ld-linux.so.2
static void security_init (void)
{
  /* Set up the stack checker's canary.  */
     //一般情况下此时_dl_random的值是由kernel写入的,glibc直接使用了里面的值, uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random); //把canary的最后一位设为'x00' #ifdef THREAD_SET_STACK_GUARD
     //TLS会进入这里.macro的定义及其详细展开见下面 THREAD_SET_STACK_GUARD (stack_chk_guard); #else __stack_chk_guard = stack_chk_guard; #endif /* Set up the pointer guard as well, if necessary. */ uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random, stack_chk_guard); #ifdef THREAD_SET_POINTER_GUARD THREAD_SET_POINTER_GUARD (pointer_chk_guard); //有TLS结构就会进入这里 #endif __pointer_chk_guard_local = pointer_chk_guard; /* We do not need the _dl_random value anymore. The less information we leave behind, the better, so clear the variable. */ _dl_random = NULL; }

 THREAD_SET_STACK_GUARD()宏的定义

#define THREAD_SET_STACK_GUARD(VALUE) THREAD_SETMEM(THREAD_SELF, header.stack_guard, value)

 header的定义,TLS相关的数据结构,注意元素stack_guard的偏移是20也就是0x14

typedef struct
{
  void *tcb;		/* Pointer to the TCB.  Not necessarily the
			   thread descriptor used by libpthread.  */
  dtv_t *dtv;
  void *self;		/* Pointer to the thread descriptor.  */
  int multiple_threads;
  uintptr_t sysinfo;
  uintptr_t stack_guard;
  uintptr_t pointer_guard;
  int gscope_flag;
#ifndef __ASSUME_PRIVATE_FUTEX
  int private_futex;
#else
  int __unused1;
#endif
  /* Reservation of some values for the TM ABI.  */
  void *__private_tm[4];
  /* GCC split stack support.  */
  void *__private_ss;
} tcbhead_t;

 将cananry的值写入gs:0x14,此处gs寄存器指向TLS结构体,gs:0x14就是将canary写入结构体中偏移为0x14处,也就是写入stack_guard中

/* Same as THREAD_SETMEM, but the member offset can be non-constant.  */
# define THREAD_SETMEM(descr, member, value)   ({if (sizeof (descr->member) == 4)				                     asm volatile ("movl %0,%%gs:%P1" :				      		     : "ir" (value),	
"i" (offsetof (struct pthread, member))); })

 生成TLS结构体的函数位于glibc-2.23/elf/dl-tls.c,可以看到,程序事实上是调用了__libc_memalign函数来分配内存,而__libc_memalign函数最终调用的是mmap函数。如果程序定义了THREAD_SET_STACK_GUARD则canary会被放在TLS,否则canary会被放在.bss中。

原文地址:https://www.cnblogs.com/countfatcode/p/11796476.html