缓冲区溢出问题的困境

6

我正在尝试一个Stack Overflow的例子。这个例子看起来像这样:

 void return_input (void){ 
    char array[30];    
    gets (array); 
    printf("%s\n", array); 

 }

 main() { 
    return_input();    
    return 0;    
 }

所有的代码都在名为overflow.c的文件中。我们有一个叫做return_input的易受攻击函数,特别是它是30字节的字符数组。我编译了它并在gdb中打开了易受攻击的函数,得到了以下输出:

 (gdb) disas return_input
 0x08048464 <+0>:   push   %ebp
 0x08048465 <+1>:   mov    %esp,%ebp
 0x08048467 <+3>:   sub    $0x48,%esp
 0x0804846a <+6>:   mov    %gs:0x14,%eax
 0x08048470 <+12>:  mov    %eax,-0xc(%ebp)
 0x08048473 <+15>:  xor    %eax,%eax
 0x08048475 <+17>:  lea    -0x2a(%ebp),%eax
 0x08048478 <+20>:  mov    %eax,(%esp)
 0x0804847b <+23>:  call   0x8048360 <gets@plt>
 0x08048480 <+28>:  lea    -0x2a(%ebp),%eax
 0x08048483 <+31>:  mov    %eax,(%esp)
 0x08048486 <+34>:  call   0x8048380 <puts@plt>
 0x0804848b <+39>:  mov    -0xc(%ebp),%eax
 0x0804848e <+42>:  xor    %gs:0x14,%eax
 0x08048495 <+49>:  je     0x804849c <return_input+56>
 0x08048497 <+51>:  call   0x8048370 <__stack_chk_fail@plt>
 0x0804849c <+56>:  leave  
 0x0804849d <+57>:  ret    
 End of assembler dump.

从函数序言中可以看出,我们在栈上为局部变量保留了hex48(十进制72)个字节。我一开始试图找到我们易受攻击的数组在栈上的起始地址。我认为它是-0x2a (%ebp),我是对的吗?Hex2a是42进制。据我理解,这意味着我们可以在开始覆盖存储在栈上的EBP之前安全地写入42个字节。但是当我运行此示例时,只需要正确写入37个字节就会出现分段错误:

rustam@rustam-laptop:~/temp/ELF_reader$ ./overflow
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault (core dumped)

37个字节怎么足以溢出缓冲区?如果我们的本地char数组距离保存的EBP有-42个字节


无关,但是这个问题非常相似。 - huon
在C语言中,向一个30字节的数组写入31个字节就足以导致该数组溢出(并引发未定义行为)。 - pmg
1个回答

6
没有看到整个函数的反汇编,很难说清楚。
然而,我的猜测是存储在-0xc(%ebp)处的%gs:0x14可能是您栈金丝雀,如果检测到堆栈损坏,则会导致干净退出。 因此,此值存储在-0xc(%ebp)处,这意味着您的缓冲区实际上只有30个字节大,其后紧跟着任何内容。

谢谢,兄弟。重新编译时去掉了gcc堆栈保护,汇编代码正确地给出了所有值。 - Rustam Issabekov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接