使用缓冲区堆栈损坏

时间:2013-04-01 03:13:58

标签: c unix

我正在尝试了解堆栈损坏时会发生什么。这是我试图理解的示例程序。我已将缓冲区的大小定义为1个字节。但是在我输入第13个字节后发生堆栈损坏。为什么在第13个字节后被破坏?

C代码:

#include<stdio.h>
#include<string.h>
int main(int argc,char *argv[]){
 char buffer[1];
 strcpy(buffer,argv[1]);
 printf("\n buffer : %s \n",buffer);
 return 0;
}

汇编代码:

        .file   "buffer_overflow.c"
        .section        .rodata
.LC0:
        .string "\n buffer : %s \n"
        .text
.globl main
        .type   main, @function
main:
        pushl   %ebp
        movl    %esp, %ebp
        andl    $-16, %esp
        subl    $32, %esp
        movl    12(%ebp), %eax
        addl    $4, %eax
        movl    (%eax), %eax
        movl    %eax, 4(%esp)
        leal    31(%esp), %eax
        movl    %eax, (%esp)
        call    strcpy
        movl    $.LC0, %eax
        leal    31(%esp), %edx
        movl    %edx, 4(%esp)
        movl    %eax, (%esp)
        call    printf
        movl    $0, %eax
        leave
        ret
        .size   main, .-main
        .ident  "GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5"
        .section        .note.GNU-stack,"",@progbits

3 个答案:

答案 0 :(得分:1)

堆栈在英特尔处理器上向下增长。变量放在堆栈上。在函数调用之后,ABI(应用程序二进制接口)也可能占用几个字节来存储诸如帧指针,指向变量块的指针以及它所需的任何其他内容。你可以在程序集中看到它在开头推动ebp。

那你为什么只在第13个字节后看到堆栈损坏?好吧,1个字节是可以的,因为你有1个字节的内存。接下来的12个是好的,因为ABI将其他变量推入该房间。由于覆盖它可能会有奇怪的结果,但你不会崩溃。然后你进入下一个变量,即返回地址。覆盖它,你几乎肯定会崩溃(没有非凡的运气)。

答案 1 :(得分:1)

最重要的 - 当你超过第一个字节时,堆栈已损坏。 :)但我离题了。

在主要被调用之前,堆栈可能会被推到它上面。

此函数的返回地址为4个字节。

“argc”的4个字节

“argv”的4个字节。

“缓冲区”的1个字节,但编译器可能在4字节边界上对齐

所以堆栈的前12个字节都是变量。一旦你破坏了返回地址,在偏移12或13附近,你就把程序置于错误的状态,并且在试图从这个调用返回时可能会崩溃。

答案 2 :(得分:1)

当CPU进入一个函数时,需要将一些值推入内存堆栈。根据你的代码,在调用'strcpy'之前,堆栈框架在x86系统上显示如下。

------------  offset 13
char buffer[1]
------------  offset 12
char *argv[]
------------  offset 8
int argc
------------  offset 4
ret
------------  offset 0

因此,在您编写了13bytes之后,strcpy重写了ret区域。当主要完成时,它已被破坏。