2017-02-08 35 views
0

我可以测试使用strncpy()具有较大源字符串则目标:金丝雀字如何让gcc检测缓冲区溢出?

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 

有人能向我解释这是如何工作的?为什么不是“”字符串的\0也被“金丝雀字”覆盖?

回答

2

有人可以向我解释这是如何工作的?

加那利字从fs:40,并储存在这里架顶部阅读:

movq %fs:40, %rax 
movq %rax, -8(%rbp) 

它的返回地址下方,所以如果你的代码发生缓冲区溢出(这将是下面-8(%rbp))它将首先覆盖-8(%rbp)位置。这将通过GCC这里发出ret之前被检测到:的-8(%rbp)

movq -8(%rbp), %rcx 
xorq %fs:40, %rcx  ; Checks that %fs:40 == -8(%rbp) 
je .L3     ; Ok, return 
call __stack_chk_fail ; Die 

作为覆盖内容将很可能是从适当的值(从fs:40安装)不同。

为什么不是加那利语也被hello世界的\ 0覆盖!?

你的代码有堆溢出,没有缓冲区溢出使SSP不禁...

+0

我明白了。谢谢 – Bionix1441

+1

@ Bionix1441如果您有兴趣发现错误,而不是强化您的应用程序,我衷心推荐[Asan](https://github.com/google/sanitizers/wiki/AddressSanitizer)。它在GCC和Clang中都可用,并且可以发现更大的内存错误类别。 – yugr