什么是缓冲区,什么是堆栈,什么是内存地址,以及应用程序的内存结构,什么是缓冲区溢出,以及为什么会发生缓冲区溢出?
- 什么是缓冲区
简单来说,缓冲区就是程序运行时所使用的内存空间或场所。这些内存空间用于存储程序当前使用的临时数据。因此,如果我们有一个简单的程序,它要求用户输入自己的名字,并将其存放到一个名为username的变量中,然后,该程序会输出“Hello username”形式的消息。这样,如果我们运行该程序,并输入用户名“Rick”,那么,“Rick”一词会首先存放到缓冲区中,直到程序执行print命令的时候,该程序才会从缓冲区中取出给定的用户名“Rick”,并输出结果:“Hello Rick”。
#include <stdio.h> int main () { char username[20]; printf("Enter your name: "); scanf("%s", username); printf("Hello %s\n", username); return(0); }
char username [20] 这里是为变量规定名称的地方,但这一行最重要的是char .... [20],其作用是为该变量指定了相应的缓冲区,具体大小为存放20个字符所需内存空间
- 什么是堆栈
堆栈就是一个内存缓冲区,用来存储程序的函数和局部变量。
- 应用程序的内存结构
首先,最下面部分存放的是代码,即程序的源代码编译后的代码,它们是程序的主要指令。
其次,从下往上数第二部分是用于存储全局变量的缓冲区,
局部变量和全局变量之间的区别在于,局部变量被限定在一个特定的函数中:如果在一个函数中定义了一个局部变量,那么,该变量就只能在这个函数中调用。但是,全局变量既可以在主函数中定义,也可以在函数外部定义,并且,这种类型的变量可以在任何地方调用。
然后,再往上就是栈(stack)了,这是内存的重要组成部分,因为缓冲区溢出就是在这里发生的。这是存储局部变量和函数调用的地方。
最后,也是最上面的一部分,即堆(Heap),这是动态内存分配区。
- 什么是内存地址
基本上,当程序被编译和执行时,程序的所有指令位于应用程序对应的内存空间中,并且,并为它们分配一个地址。该地址通常采用十六进制字节的格式。分配到的地址就叫做内存地址
- 什么是缓冲区溢出
简单来说,当输入的数据的长度超过缓冲区的上限时,就会发生缓冲区溢出,这会导致程序在为其分配的缓冲区之外写入数据,这样,就可能会覆盖程序用来保存数据的某些内存空间,从而使数据不可用,并最终导致程序崩溃。
为什么会发生缓冲区溢出?
#include <stdio.h> int main () { char username[20]; printf("Enter your name: "); scanf("%s", username); printf("Hello %s\n", username); printf("Program exited normally"); return(0); }
处于演示的目的,这里又添加了一行代码,用来输出“program exited noramlly”。
现在,程序运行时会询问我们的用户名,接着打印“Hello username”,然后输出“program exited noramlly”并退出。其中,用于保存变量username的值的缓冲区的长度被设置为20个字符,所以,用户名的长度最好小于20个字符。但是,如果输入的数据的长度超过了20个字符,程序将会崩溃,因为缓冲区外面的某些数据将被覆盖,致使程序的某些部分被破坏掉了。在我们的例子中,被破坏的部分将是打印“program exited noramlly”的那一部分。
首先,让我们运行程序,并输入AAAAA。
这时,程序可以正常退出
但是,如果我们输入30个A呢?
这时,我们看到程序会打印“Hello aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa”,但是,之后并没有看到它输出“program exited normally”,相反,我们看到的是一个段错误。这是因为我们额外输入了10个字符,而程序只需要20个字符,或更少。这些额外的字符,即“aaaaaaaaa”超过了20个字符的缓冲区的容量,会写入缓冲区边界之外的内存中,并覆盖其他数据(即打印“Program exit normal”的打印指令),从而引发段错误,因为程序已被破坏。
借助GDB考察缓冲区溢出
这个不会用,以后再更
为什么缓冲区溢出如此危险?
当易受攻击的二进制文件或程序是具有setuid访问权限的二进制文件时,缓冲区溢出问题可能带来巨大的危害。如果您不知道具有setuid权限二进制文件是什么的话,建议阅读提供的链接文章的详细介绍,但简单来说,让执行该程序的用户以该程序拥有者(通常是root)的权限去执行它们,但是当该程序容易受到缓冲区溢出的影响时,这就不太妙了。由于我们可以向缓冲区中传递数据并覆盖程序,因此,我们可以使用执行系统调用的payload覆盖程序,从而得到一个具有root权限的shell。
标签:username,20,程序,溢出,缓冲区,个字符 From: https://www.cnblogs.com/wgd-elwood/p/16720791.html