金丝雀的话怎么允许gcc检测缓冲区溢出?

时间:2017-02-08 16:06:02

标签: security gcc stack buffer-overflow

我可以使用strncpy()来测试更大的源字符串然后是目标:

int main() {
  char *ptr = malloc(12);
  strcpy(ptr,"hello world!");
  return 0;
}

使用标记-fstack-protector进行编译并使用我获得的-S选项:

.file   "malloc.c"
.text
.globl  main
.type   main, @function
main:
.LFB2:
.cfi_startproc
pushq   %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq    %rsp, %rbp
.cfi_def_cfa_register 6
subq    $32, %rsp
movl    %edi, -20(%rbp)
movq    %rsi, -32(%rbp)
movq    %fs:40, %rax
movq    %rax, -8(%rbp)
xorl    %eax, %eax
movq    $0, -16(%rbp)
movl    $12, %edi
call    malloc
movq    %rax, -16(%rbp)
movq    -16(%rbp), %rax
movabsq $8022916924116329800, %rdx
movq    %rdx, (%rax)
movl    $560229490, 8(%rax)
movb    $0, 12(%rax)
movl    $0, %eax
movq    -8(%rbp), %rcx
xorq    %fs:40, %rcx
je  .L3
call    __stack_chk_fail
.L3:
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE2:
.size   main, .-main

有人可以向我解释这是如何运作的吗?为什么“{1}}字符串的\0也覆盖了”金丝雀词“?

1 个答案:

答案 0 :(得分:2)

  

有人可以向我解释这是如何运作的?

fs:40读取加那利字,并在此处存储在框架顶部:

movq    %fs:40, %rax
movq    %rax, -8(%rbp)

它低于返回地址,因此如果您的代码碰巧溢出缓冲区( -8(%rbp)下方),它将首先覆盖-8(%rbp)位置。在此处发布ret之前,GCC会检测到这一点:

movq    -8(%rbp), %rcx
xorq    %fs:40, %rcx      ; Checks that %fs:40 == -8(%rbp)
je  .L3                   ; Ok, return
call    __stack_chk_fail  ; Die

由于-8(%rbp)的覆盖内容可能与正确值(从fs:40安装)不同。

  

为什么不能用你好世界的\ 0覆盖那个金丝雀的单词!?

你的代码有堆溢出,而不是缓冲区溢出,所以SSP无法帮助......