# 内存，第 3 部分：粉碎栈示例

> 原文：<https://github.com/angrave/SystemProgramming/wiki/Memory%2C-Part-3%3A-Smashing-the-Stack-Example>

每个线程使用栈内存。栈“向下增长” - 如果函数调用另一个函数，则栈扩展到较小的内存地址。栈内存包括非静态自动（临时）变量，参数值和返回地址。如果缓冲区太小某些数据（例如来自用户的输入值），那么很可能会覆盖其他栈变量甚至返回地址。栈内容的精确布局和自动变量的顺序取决于体系结构和编译器。然而，通过一些调查工作，我们可以学习如何故意粉碎特定架构的栈。

下面的示例演示了返回地址如何存储在栈中。对于特定的 32 位架构 [Live Linux Machine](http://cs-education.github.io/sys/) ，我们确定返回地址存储在自动变量地址上方两个指针（8 个字节）的地址处。代码故意更改栈值，以便在输入函数返回时，而不是继续在 main 方法内部，它会跳转到 exploit 函数。

```c
// Overwrites the return address on the following machine:
// http://cs-education.github.io/sys/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void breakout() {
    puts("Welcome. Have a shell...");
    system("/bin/sh");
}
void input() {
  void *p;
  printf("Address of stack variable: %p\n", &p);
  printf("Something that looks like a return address on stack: %p\n", *((&p)+2));
  // Let's change it to point to the start of our sneaky function.
  *((&p)+2) = breakout;
}
int main() {
    printf("main() code starts at %p\n",main);

    input();
    while (1) {
        puts("Hello");
        sleep(1);
    }

    return 0;
}
```

[有很多](https://en.wikipedia.org/wiki/Stack_buffer_overflow)计算机倾向于解决这个问题。