该机器代码如何防止缓冲区溢出?

时间:2015-11-13 14:17:13

标签: c gcc assembly stack-overflow machine-language

以下是三个不同的.s文件的一部分。 .c文件已编译为三个不同的选项:

  1. -fno-inline -fstack-protector-strong,
  2. -fno-inline -fsanitize = address,
  3. -fno-inline -fno-stack-protector -zexecstack。
  4. 以下是.s文件的内容:

    handle_read:
    .LFB20:
        .cfi_startproc
        pushq   %r12
        .cfi_def_cfa_offset 16
        .cfi_offset 12, -16
        pushq   %rbp
        .cfi_def_cfa_offset 24
        .cfi_offset 6, -24
        movq    %rsi, %r12
        pushq   %rbx
        .cfi_def_cfa_offset 32
        .cfi_offset 3, -32
        movq    8(%rdi), %rbx
        movq    %rdi, %rbp
        movq    160(%rbx), %rsi
        movq    152(%rbx), %rdx
        cmpq    %rdx, %rsi
        jb      .L394
        cmpq    $5000, %rdx
        jbe     .L421
    
    handle_read:
    .LASANPC20:
    .LFB20:
        .cfi_startproc
        pushq   %r15
        .cfi_def_cfa_offset 16
        .cfi_offset 15, -16
        pushq   %r14
        .cfi_def_cfa_offset 24
        .cfi_offset 14, -24
        pushq   %r13
        .cfi_def_cfa_offset 32
        .cfi_offset 13, -32
        pushq   %r12
        .cfi_def_cfa_offset 40
        .cfi_offset 12, -40
        pushq   %rbp
        .cfi_def_cfa_offset 48
        .cfi_offset 6, -48
        movq    %rdi, %rbp
        addq    $8, %rdi
        pushq   %rbx
        .cfi_def_cfa_offset 56
        .cfi_offset 3, -56
        movq    %rdi, %rax
        shrq    $3, %rax
        subq    $24, %rsp
        .cfi_def_cfa_offset 80
        cmpb    $0, 2147450880(%rax)
        jne     .L1170
        movq    8(%rbp), %rbx
        leaq    160(%rbx), %r13
        movq    %r13, %r15
        shrq    $3, %r15
        cmpb    $0, 2147450880(%r15)
        jne     .L1171
        leaq    152(%rbx), %r14
        movq    %rsi, %r12
        movq    160(%rbx), %rsi
        movq    %r14, %rax
        shrq    $3, %rax
        cmpb    $0, 2147450880(%rax)
        jne     .L1172
        movq    152(%rbx), %rdx
        leaq    144(%rbx), %rcx
        cmpq    %rdx, %rsi
        jb      .L1054
        cmpq    $5000, %rdx
        jbe     .L1055
        movl    $httpd_err400form, %eax
        shrq    $3, %rax
        cmpb    $0, 2147450880(%rax)
        jne     .L1173
        movl    $httpd_err400title, %eax
        movq    httpd_err400form(%rip), %r8
        shrq    $3, %rax
        cmpb    $0, 2147450880(%rax)
        jne     .L1174
    
    
    handle_read:
    .LFB20:
        .cfi_startproc
        pushq   %r12
        .cfi_def_cfa_offset 16
        .cfi_offset 12, -16
        pushq   %rbp
        .cfi_def_cfa_offset 24
        .cfi_offset 6, -24
        movq    %rsi, %r12
        pushq   %rbx
        .cfi_def_cfa_offset 32
        .cfi_offset 3, -32
        movq    8(%rdi), %rbx
        movq    %rdi, %rbp
        movq    160(%rbx), %rsi
        movq    152(%rbx), %rdx
        cmpq    %rdx, %rsi
        jb      .L384
        cmpq    $5000, %rdx
        jbe     .L411
    

    有谁能告诉我这些代码如何阻止缓冲区溢出?

1 个答案:

答案 0 :(得分:2)

您的handle_read函数最终不会在堆栈上分配任何内容,因此-fstack-protector-strong没有任何内容可以保护,因此此选项没有任何区别。 -zexecstack选项在生成的可执行文件中设置一个标志,告诉操作系统它应该允许执行存储在堆栈中的代码。它对生成的程序集没有影响。

只有-fsanitize=address选项具有显示在您发布的生成的程序集输出中的效果。它负责出现在第二个生成的程序集块中的shrq $3, rXX; cmp $0, 2147450880(%rXX); jne .LXXXX序列。这些指令查找内存中的每个地址,这些地址在“影子存储器”表中进行访问。该表记录了哪些位置已分配,哪些尚未分配。如果插入的代码检测到程序正在尝试访问尚未分配的内存位置,则会导致程序退出并显示错误消息。

有关影子记忆表如何工作的详细信息,以及AddressSanitizer的工作原理,您可以阅读作者的Usenix论文AddressSanitizer: A Fast Address Sanity Checker