缓冲区溢出漏洞
A buffer is a temporary storage, usually present in the physical memory used to hold data.
缓冲区是一种临时存储,通常存在于用于保存数据的物理内存中。
Consider the program shown in the left image where a character buffer of length 5 is defined. In a big cluster of memory, a small memory of 5 bytes would be assigned to the buffer which looks like the image on the right.
考虑左图所示的程序,其中定义了长度为5的字符缓冲区。 在大内存集群中,将为缓冲区分配5个字节的小内存,该缓冲区看起来像右边的图像。
A buffer overflow occurs when more data is written to a specific length of memory in such a way that adjacent memory addresses are overwritten.
当更多数据写入特定长度的内存,从而覆盖相邻的内存地址时,就会发生缓冲区溢出。
Let’s take an example of a basic authentication app that asks for a password and returns Authenticated! if the password is correct.
让我们以一个基本的身份验证应用程序为例,该应用程序要求输入密码并返回Authenticated! 如果密码正确。
Without really knowing how the app works, let’s enter a random password.
在不真正知道应用程序如何工作的情况下,让我们输入一个随机密码。
It says Authentication Declined! since the password wasn’t correct. To test, we need to enter large random data.
它说Authentication Declined! 因为密码不正确。 为了进行测试,我们需要输入大量随机数据。
You must be wondering why it got authenticated and why there is a Segmentation fault. Let’s see a more detailed version of the app.
您一定想知道为什么它通过了身份验证以及为什么存在Segmentation fault 。 让我们看看该应用程序的更详细版本。
As you can see, there are three variables: auth, sys_pass, and usr_pass.
如您所见,存在三个变量: auth , sys_pass和usr_pass 。
The auth variable determines if the user is authenticated or not depending on the value (initially, 0). The usr_pass stores the password that the user enters and the sys_pass variable is what the correct password is.
auth变量根据值(最初为0)确定用户是否通过身份验证。 usr_pass存储用户输入的密码,而sys_pass变量是正确的密码。
How the app works is, if the usr_pass variable is equal to sys_pass, then the auth variable becomes 1. If the auth variable is not 0, then the user is authenticated.
应用程序的工作方式是,如果usr_pass变量等于sys_pass ,则auth变量变为1 。 如果auth变量不为0 ,则对用户进行身份验证。
You may also see how the variables are stored in memory. Since the address is in hexadecimal and there is a difference of 1, therefore, usr_pass and sys_pass variables are buffers of length 16.
您可能还会看到变量如何存储在内存中。 由于地址为十六进制且相差1,因此usr_pass和sys_pass变量是长度为16的缓冲区。
To test for buffer overflow, a long password is entered as shown.
要测试缓冲区溢出,请输入一个长密码,如下所示。
As you can see, the password entered in usr_pass variable overflows the sys_pass variable and then the auth variable.
如您所见,在usr_pass变量中输入的密码usr_pass sys_pass变量和auth变量溢出。
Note: C functions like strcpy(), strcmp(), strcat() do not check the length of the variable and can overwrite later memory addresses, which is precisely what buffer overflow is.
注意:诸如strcpy() , strcmp() , strcat()类的C函数不会检查变量的长度,并且会覆盖以后的内存地址,而这正是缓冲区溢出的原因。
Refer to the code below for better understanding.
请参阅下面的代码以更好地理解。
#include <stdio.h>int main(void) { int auth = 0; char sys_pass[16] = "Secret"; char usr_pass[16]; printf("Enter password: "); scanf("%s", usr_pass); if (strcmp(sys_pass, usr_pass) == 0) { authorized = 1; } printf("usr_pass: %s\n", usr_pass); printf("sys_pass: %s\n", sys_pass); printf("auth: %d\n", authorized); printf("sys_pass addr: %p\n", (void *)sys_pass); printf("auth addr: %p\n", (void *)&authorized); if (auth) { printf("Authenticated!\n"); } else{ printf("Authentication declined!\n"); }}Note: This might be an unrealistic example and is only meant for understanding purposes. You may not see such situations in real life.
注意:这可能是不现实的示例,仅用于理解目的。 在现实生活中,您可能看不到这种情况。
Let’s dive a little deeper into the concepts now.
现在让我们更深入地研究这些概念。
Source: Techno Trick.
资料来源: Techno Trick 。
This is what the memory assigned to a process looks like. There are various sections like stack, heap, Uninitialized data, etc. used for different purposes.
这就是分配给进程的内存。 有不同的部分,如stack , heap , Uninitialized data等用于不同目的。
You may read more about the memory layout here: Memory layout of a process.
您可以在此处阅读有关内存布局的更多信息: 进程的内存布局。
This blog focuses on buffer overflow in a stack so let’s look at that.
该博客着重于堆栈中的缓冲区溢出,因此让我们来看一下。
Stack: A LIFO data structure extensively used by computers in memory management, etc. 堆栈:计算机在内存管理等中广泛使用的LIFO数据结构。 There is a bunch of registers present in the memory, but we will only concern ourselves with EIP, EBP, and ESP. 内存中有一堆寄存器,但是我们只关心EIP,EBP和ESP。 EBP: It’s a stack pointer that points to the base of the stack. EBP:这是一个指向堆栈底部的堆栈指针。 ESP: It’s a stack pointer that points to the top of the stack. ESP:这是一个指向堆栈顶部的堆栈指针。5. EIP: It contains the address of the next instruction to be executed.
5. EIP:它包含要执行的下一条指令的地址。
The above image shows what a stack looks like. It might look intimidating, but trust me, it isn’t.
上图显示了stack外观。 它可能看起来令人生畏,但请相信我,事实并非如此。
Let’s see some important points related to the stack:
让我们看一下与堆栈有关的一些要点:
A stack is filled from higher memory to lower memory. 堆栈从较高的内存填充到较低的内存。 In a stack, all the variables are accessed relative to the EBP. 在堆栈中,所有变量都是相对于EBP访问的。 In a program, every function has its own stack. 在程序中,每个函数都有其自己的堆栈。 Everything is referenced from the EBP register. 一切都从EBP寄存器中引用。Source: IT & Security Stuff.
资料来源: IT与安全资料 。
Above the EBP, function parameters are stored.
在EBP上方存储功能参数。
For example:
例如:
void foo(int a, int b, int c){ //Function body }Here, a, b, and c are the function parameters stored above the EBP.
这里, a , b和c是存储在EBP上方的功能参数。
All the local variables of a function are stored below the EBP. 函数的所有局部变量都存储在EBP下方。The Old