我可以使用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
有人可以向我解释这是如何运作的吗?为什么“{1}}字符串的\0
也覆盖了”金丝雀词“?
答案 0 :(得分:2)
有人可以向我解释这是如何运作的?
从fs:40
读取加那利字,并在此处存储在框架顶部:
movq %fs:40, %rax
movq %rax, -8(%rbp)
它低于返回地址,因此如果您的代码碰巧溢出缓冲区( -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
安装)不同。
为什么不能用你好世界的\ 0覆盖那个金丝雀的单词!?
你的代码有堆溢出,而不是缓冲区溢出,所以SSP无法帮助......