简体   繁体   English

为什么粉碎后不会立即出现“堆栈粉碎检测”?

[英]Why does “stack smashing detected” not appear immediately after smashing?

I understand what is meant by "stack smashing detected". 我理解“堆栈粉碎检测”是什么意思。 There are already a lot of questions here regarding this. 关于这一点,这里已经有很多问题了。 But I didn't find an answer to the following question. 但我没有找到以下问题的答案。 Take the C code 拿C代码

int main(int argc, char **args) {
   char puffer[5];
   strcpy(puffer, *++args);
   printf("%s\n",puffer);
   return EXIT_SUCCESS;
}

When I compile with gcc 4.8.1 in Ubuntu 13.10 ./buffer 123456789 raises the expected error stack smashing detected . 当我在Ubuntu 13.10 ./buffer 123456789 gcc 4.8.1编译时./buffer 123456789引发了stack smashing detected的预期错误stack smashing detected But why does ./buffer 12345678 raise no error? 但为什么./buffer 12345678没有引发错误? I would expect that every string with more than 5 chars should raise the error. 我希望每个超过5个字符的字符串都会引发错误。

Theoretically you are right and that is how it should behave. 理论上你是对的,这就是它应该如何表现。 The moment your program uses more than 5 bytes, this could lead to undefined behaviour. 程序使用超过5个字节的那一刻,这可能会导致未定义的行为。 But often the stack pointer is aligned to certain boundaries for various performance reasons. 但是由于各种性能原因,堆栈指针通常与某些边界对齐 Alignment varies from architecture to architecture. 对齐因架构而异。 Hence you do not see this problem for every input which is larger than 5. 因此,对于大于5的每个输入,您都不会看到此问题。

The disassembly of your program is displayed below. 程序的反汇编显示如下。 Check out the sub $0x20,%rsp instruction, which allocates 16 bytes of memory on the stack for this function. 检查sub $0x20,%rsp指令,该指令在堆栈上为此函数分配16个字节的内存。

(gdb) disassemble main
Dump of assembler code for function main(int, char**):
   0x00000000004008b0 <+0>: push   %rbp
   0x00000000004008b1 <+1>: mov    %rsp,%rbp
=> 0x00000000004008b4 <+4>: sub    $0x20,%rsp
   0x00000000004008b8 <+8>: mov    %edi,-0x14(%rbp)
   0x00000000004008bb <+11>:    mov    %rsi,-0x20(%rbp) 
  0x00000000004008bf <+15>: mov    %fs:0x28,%rax
   0x00000000004008c8 <+24>:    mov    %rax,-0x8(%rbp)
   0x00000000004008cc <+28>:    xor    %eax,%eax
   0x00000000004008ce <+30>:    addq   $0x8,-0x20(%rbp)
   0x00000000004008d3 <+35>:    mov    -0x20(%rbp),%rax
   0x00000000004008d7 <+39>:    mov    (%rax),%rdx
   0x00000000004008da <+42>:    lea    -0x10(%rbp),%rax
   0x00000000004008de <+46>:    mov    %rdx,%rsi
   0x00000000004008e1 <+49>:    mov    %rax,%rdi
   0x00000000004008e4 <+52>:    callq  0x400770 <strcpy@plt>
   0x00000000004008e9 <+57>:    lea    -0x10(%rbp),%rax
   0x00000000004008ed <+61>:    mov    %rax,%rdi
   0x00000000004008f0 <+64>:    callq  0x400710 <puts@plt>
   0x00000000004008f5 <+69>:    mov    $0x0,%eax
   0x00000000004008fa <+74>:    mov    -0x8(%rbp),%rcx
   0x00000000004008fe <+78>:    xor    %fs:0x28,%rcx
   0x0000000000400907 <+87>:    je     0x400918 <main(int, char**)+104>
   0x0000000000400909 <+89>:    jmp    0x400913 <main(int, char**)+99>
   0x000000000040090b <+91>:    mov    %rax,%rdi
   0x000000000040090e <+94>:    callq  0x400790 <_Unwind_Resume@plt>
   0x0000000000400913 <+99>:    callq  0x400760 <__stack_chk_fail@plt>
   0x0000000000400918 <+104>:   leaveq 
   0x0000000000400919 <+105>:   retq   

There are different stack smashing protections implemented by compilers but usually to prevent a stack overflow exploitation a canary is put right before the saved frame pointer and the return address. 编译器实现了不同的堆栈粉碎保护,但通常是为了防止堆栈溢出利用,在保存的帧指针和返回地址之前放置金丝雀。 The canary is here to protect the overwriting of the saved frame pointer and the return address. 金丝雀在这里是为了保护覆盖保存的帧指针和返回地址。 Here basically there is some padding inserted by the compiler between the end of the buffer and the frame pointer / return address. 这里基本上在编译器在缓冲区的末尾和帧指针/返回地址之间插入了一些填充。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM