wp 主题引入js函数:Buffer Overflow Attacks and Their Countermeas (1)

来源:百度文库 编辑:中财网 时间:2024/04/28 05:17:29
What is buffer overflow, why is it dangerous and how is it preventable?

Buffer overflow problems always have been associated with security vulnerabilities. In the past, lots of security breaches have occurred due to buffer overflow. This article attempts to explain what buffer overflow is, how it can be exploited and what countermeasures can be taken to avoid it.

Knowledge of C or any other high level language is essential to this discussion. Basic knowledge of process memory layout is useful, but not necessary. Also, all the discussions are based on Linux running on x86 platform. The basic concepts of buffer overflow, however, are the same no matter what platform and operating system is used.

Buffer Overflow: the Basics

A buffer is a contiguous allocated chunk of memory, such as an array or a pointer in C. In C and C++, there are no automatic bounds checking on the buffer, which means a user can write past a buffer. For example:

int main () {int buffer[10];buffer[20] = 10;}

The above C program is a valid program, and every compiler can compile it without any errors. However, the program attempts to write beyond the allocated memory for the buffer, which might result in unexpected behavior. Over the years, some bright people have used only this concept to create havoc in the computer industry. Before we understand how they did it, let's first see what a process looks like in memory.

A process is a program in execution. An executable program on a disk contains a set of binary instructions to be executed by the processor; some read-only data, such as printf format strings; global and static data that lasts throughout the program execution; and a brk pointer that keeps track of the malloced memory. Function local variables are automatic variables created on the stack whenever functions execute, and they are cleaned up as the function terminates.

The figure above shows the memory layout of a Linux process. A process image starts with the program's code and data. Code and data consists of the program's instructions and the initialized and uninitialized static and global data, respectively. After that is the run-time heap (created using malloc/calloc), and then at the top is the users stack. This stack is used whenever a function call is made.

The Stack Region

A stack is a contiguous block of memory containing data. A stack pointer (SP) points to the top of the stack. Whenever a function call is made, the function parameters are pushed onto the stack from right to left. Then the return address (address to be executed after the function returns), followed by a frame pointer (FP), is pushed on the stack. A frame pointer is used to reference the local variables and the function parameters, because they are at a constant distance from the FP. Local automatic variables are pushed after the FP. In most implementations, stacks grow from higher memory addresses to the lower ones.

This figure depicts a typical stack region as it looks when a function call is being executed. Notice the FP between the local and the return addresses. For this C example,

void function (int a, int b, int c) {char buffer1[5];char buffer2[10];}int main() {function(1,2,3);}

the function stack looks like:

As you can see, buffer1 takes eight bytes and buffer2 takes 12 bytes, as memory can be addressed only in multiples of word size (four bytes). In addition, an FP is needed to access a, b, c, buffer1 and buffer2 variables. All these variables are cleaned up from the stack as the function terminates. These variables take no space in the executable disk copy.

Buffer Overflow: the Details

Consider another C example:

void function (char *str) {char buffer[16];strcpy (buffer, str);}int main () {char *str = "I am greater than 16 bytes"; // length of str = 27 bytesfunction (str);}

This program is guaranteed to cause unexpected behavior, because a string (str) of 27 bytes has been copied to a location (buffer) that has been allocated for only 16 bytes. The extra bytes run past the buffer and overwrites the space allocated for the FP, return address and so on. This, in turn, corrupts the process stack. The function used to copy the string is strcpy, which completes no checking of bounds. Using strncpy would have prevented this corruption of the stack. However, this classic example shows that a buffer overflow can overwrite a function's return address, which in turn can alter the program's execution path. Recall that a function's return address is the address of the next instruction in memory, which is executed immediately after the function returns.