用户空间

用户空间是用户可以使用的空间,与之对应的是内核空间,这是系统所使用的空间。用户空间的大小有2的48次方,远远超出了内存的大小。

用户空间主要分为四个区域:

  • 栈,栈位于用户空间的最高处,从高处向低处生长。linux系统中栈空间大小是8MB
  • 堆, 用于存放一些动态分配的数据
  • 数据, 用来存放全局变量,静态变量,字符串常量
  • 代码, 存放指令和共享库

在Linux中,对于大小小于某一阈值的数据,在堆中分配时是从低地址向高地址生长。反之,从高地址向低地址生长

缓冲区溢出

常见原因: 申请了一个数组但是访问时越界。

我们可以把数组叫做缓冲区,超出边界就是缓冲区溢出。

常见表现,对于输入的字符串没有进行长度检查直接赋值。如果缓冲区分配在栈中,就有可能造成栈中数据的破坏。如果造成了返回地址的破坏,可能直接导致程序的崩溃。这种错误叫做 segmentation fault

这里便可以被黑客利用,先故意把返回地址破坏了并且让返回地址到他自己写的程序上,这样retq时就可以调用自己写的程序。这种方法叫做注入。一般注入的数据有三部分,第一部分是恶意的指令。第二部分是占位数据,这部分数据没什么含义,只是和指令加起来正好到返回地址处,第三部分就是篡改的地址,篡改后的地址指向缓冲区底部即恶意指令所在的地方。

防御代码注入攻击

  • 程序员:不要使用不安全的函数
  • 系统: 栈基地址随机化分配。设置可执行权限位(就是设置一些地方的bit只能当做数据而不能当做指令)
  • 编译器: 添加栈破坏检测。通过添加金丝雀值(canary value),位于当前栈帧底部。如果金丝雀值被破坏,那么就终止程序。