[英]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.