【问题标题】:How do canary words allow gcc to detect buffer overflows?金丝雀字如何让 gcc 检测缓冲区溢出?
【发布时间】:2017-06-26 08:39:21
【问题描述】:

我可以使用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

有人可以向我解释这是如何工作的吗?为什么hello world! 字符串的\0 也不会覆盖“金丝雀词”?

【问题讨论】:

    标签: security gcc x86-64 buffer-overflow callstack


    【解决方案1】:

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

    Canary 字从fs:40 读取并存储在此处的帧顶部:

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

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

    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 安装)。

    为什么canary这个词也没有被hello world的\0覆盖!?

    您的代码有堆溢出,而不是缓冲区溢出,所以 SSP 无能为力...

    【讨论】:

    • @Bionix1441 如果您有兴趣查找错误,而不是强化您的应用程序,我衷心推荐Asan。它在 GCC 和 Clang 中都可用,并且可以发现更大类的内存错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-07
    • 2015-07-02
    • 1970-01-01
    • 2020-05-14
    相关资源
    最近更新 更多