canary words 如何允许 gcc 检测缓冲区溢出?
How do canary words allow gcc to detect buffer overflows?
我可以使用 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 , %rsp
movl %edi, -20(%rbp)
movq %rsi, -32(%rbp)
movq %fs:40, %rax
movq %rax, -8(%rbp)
xorl %eax, %eax
movq [=11=], -16(%rbp)
movl , %edi
call malloc
movq %rax, -16(%rbp)
movq -16(%rbp), %rax
movabsq 22916924116329800, %rdx
movq %rdx, (%rax)
movl 0229490, 8(%rax)
movb [=11=], 12(%rax)
movl [=11=], %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
有人可以向我解释一下这是如何工作的吗?为什么 "canary word" 也没有被 hello world!
字符串的 [=15=]
覆盖?
Could someone explain to me how does this work ?
从 fs:40
读取 Canary 词并存储在此处的帧顶部:
movq %fs:40, %rax
movq %rax, -8(%rbp)
它位于 return 地址之下,因此如果您的代码恰好溢出缓冲区(将 低于 -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
安装)不同。
And why is not the canary word also overwritten by the [=19=] of the hello world!?
您的代码存在堆溢出,而不是缓冲区溢出,因此 SSP 无能为力...
我可以使用 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 , %rsp
movl %edi, -20(%rbp)
movq %rsi, -32(%rbp)
movq %fs:40, %rax
movq %rax, -8(%rbp)
xorl %eax, %eax
movq [=11=], -16(%rbp)
movl , %edi
call malloc
movq %rax, -16(%rbp)
movq -16(%rbp), %rax
movabsq 22916924116329800, %rdx
movq %rdx, (%rax)
movl 0229490, 8(%rax)
movb [=11=], 12(%rax)
movl [=11=], %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
有人可以向我解释一下这是如何工作的吗?为什么 "canary word" 也没有被 hello world!
字符串的 [=15=]
覆盖?
Could someone explain to me how does this work ?
从 fs:40
读取 Canary 词并存储在此处的帧顶部:
movq %fs:40, %rax
movq %rax, -8(%rbp)
它位于 return 地址之下,因此如果您的代码恰好溢出缓冲区(将 低于 -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
安装)不同。
And why is not the canary word also overwritten by the [=19=] of the hello world!?
您的代码存在堆溢出,而不是缓冲区溢出,因此 SSP 无能为力...