代码之家  ›  专栏  ›  技术社区  ›  Anon.

用汇编语言解释这一行?

  •  5
  • Anon.  · 技术社区  · 6 年前

    下面是一个被反汇编的C程序的前5行,为了更好地学习汇编语言,我正试图将其反向工程回C代码中。在这段代码的开头,我看到它在堆栈上腾出了空间,并立即调用

    0x000000000040054e <+8>:    mov    %fs:0x28,%rax
    

    我很困惑这行代码的作用,以及从相应的C程序中调用这行代码的原因。到目前为止,我唯一一次看到这行代码是在调用C程序中的另一个方法时,但这次它后面没有任何Callq指令,所以我不太确定。。。你知道这个C程序中还有什么东西可以打这个电话吗?

    0x0000000000400546 <+0>:    push   %rbp
    0x0000000000400547 <+1>:    mov    %rsp,%rbp   
    0x000000000040054a <+4>:    sub    $0x40,%rsp
    0x000000000040054e <+8>:    mov    %fs:0x28,%rax
    0x0000000000400557 <+17>:   mov    %rax,-0x8(%rbp)
    0x000000000040055b <+21>:   xor    %eax,%eax
    0x000000000040055d <+23>:   movl   $0x17,-0x30(%rbp)
    ...
    

    我知道这是为了为缓冲区溢出攻击提供某种形式的堆栈保护,我只需要知道如果没有单独的方法,什么样的C代码会提示这种保护。

    1 回复  |  直到 6 年前
        1
  •  5
  •   zwol    6 年前

    正如您所说,这是用于防止缓冲区溢出的代码。编译器为具有可能是溢出缓冲区的局部变量的函数生成此“堆栈金丝雀检查”。请注意您要询问的行上方和下方的说明:

    sub  $0x40, %rsp
    mov  %fs:0x28, %rax
    mov  %rax, -0x8(%ebp)
    xor  %eax, %eax
    

    这个 sub 在堆栈上分配64字节的空间,这足以容纳至少一个小数组。然后从中复制一个秘密值 %fs:0x28 到该空间的顶部,就在前一帧指针和返回地址的下方,然后从寄存器文件中删除。

    函数体处理数组;如果它写的内容足够远,超过了数组的结尾,它将覆盖机密值。在函数的末尾,将有以下代码

        mov    -0x8(%rbp), %rax
        xor    %fs:28, %rax
        jne    1
        mov    %rbp, %rsp
        pop    %rbp
        ret
    1:
        call    __stack_chk_fail   # does not return
    

    这将验证机密值是否保持不变,如果更改了,则会导致程序崩溃。其想法是,有人试图利用一个简单的缓冲区溢出漏洞进行攻击,就像您使用 gets ,在不修改机密值的情况下,将无法更改返回地址。

    编译器具有 several different heuristics ,可通过命令行选项选择,用于决定何时需要生成堆栈金丝雀保护代码。

    您自己无法编写与此汇编语言对应的C代码,因为它使用了不同寻常的%fs:nnnn寻址模式;堆栈加那利代码有意使用其他代码生成都不依赖的寻址模式,以使对手尽可能难以了解秘密值。