通常,Linux 上的金丝雀字有多大?

信息安全 缓冲区溢出 堆栈溢出
2021-08-29 19:03:53

金丝雀字是位于缓冲区(例如堆栈)和程序中控制数据之间边界的位序列,作为检测缓冲区溢出并对其作出反应的一种方式。

这些金丝雀在 Linux 上通常有多少位?

3个回答

让我们试试吧!这是一个非常简单的示例程序。

int test(int a)
{
    return a;
}

用GCC编译,在汇编阶段拦截编译。-S标志会这样做。)重命名程序集文件(这样它就不会被覆盖)并再次编译,这次还要添加-fstack-protector-all-mstack-protector-guard=global标志。第一个标志为所有函数启用堆栈金丝雀,第二个标志选择全局金丝雀而不是线程本地的。(线程本地默认值在实践中可能更有用,但全局版本的程序集更容易理解。)

比较两个生成的程序集文件,我们发现了以下添加(评论是我的)。

        movl %edi, -20(%rbp)                 ; save function parameter onto stack (unrelated to canary)
        movq __stack_chk_guard(%rip), %rax   ; load magic value into RAX register
        movq %rax, -8(%rbp)                  ; save RAX register onto stack (place the canary)
        movl -20(%rbp), %eax                 ; load function parameter into EAX register for return (unrelated to canary)
        movq -8(%rbp), %rcx                  ; load canary value into RCX register
        movq __stack_chk_guard(%rip), %rdx   ; load magic value into RDX register
        cmpq %rdx, %rcx                      ; compare canary value to expected value
        je .L3                               ; if they are the same, jump to label .L3 (continue)
        call __stack_chk_fail                ; otherwise (stack corruption detected), call the handler
.L3:
        leave

我们可以看到金丝雀是在 RAX、RCX 和 RDX 寄存器中处理的,它们都是 64 位宽的。(它们的 32 位对应物将被命名为 EAX、EBX 和 EDX。16 位版本被命名为 AX、BX 和 CX。8 位变体 AL、BL 和 CL。)另一个线索是存储、加载和比较canary(MOVQ 和 CMPQ)有一个“Q”后缀,用于标识 64 位指令。(32 位指令具有“L”后缀,16 位指令具有“W”后缀,8 位指令具有“B”后缀。)

因此,我们得出结论,金丝雀是一个 64 位的值,这在 64 位架构(在我的例子中是 x86_64 GNU/Linux)上是有意义的。我希望他们将始终使用本机字号,因为这对我来说最有意义。你可以在你的机器上尝试同样的实验,看看你会得到什么。

正如我在本页中看到的那样:堆栈粉碎保护器

堆栈金丝雀是原生字大小的,如果随机选择,攻击者将不得不在 2^32 或 2^64 组合中猜测正确的值

使用的位数必须等于处理器的字大小。所以如果你有一个 32 位处理器,它的字大小是 32,因此金丝雀字是 32 位长。