Buffers

A buffer is defined as a limited, contiguously allocated set of memory. The most common buffer in C is an array . We will focus on arrays in the introductory material in this chapter.

Stack overflows are possible because no inherent bounds-checking exists on buffers in the C or C++ languages. In other words, the C language and its derivatives do not have a built-in function to ensure that data being copied into a buffer will not be larger than the buffer can hold.

Consequently, if the person designing the program has not explicitly coded the program to check for oversized input, it is possible for data to fill a buffer, and if that data is large enough, to continue to write past the end of the buffer. As you will see in this chapter, all sorts of crazy things start happening once you write past the end of a buffer. Take a look at this extremely simple example that illustrates how C has no bounds-checking on buffers. (Remember, you can find this and many other code fragments and programs on the Shellcoder's Handbook Web site, www. wiley .com/compbooks/koziol .)

 int main () {     int array[5] = {1, 2, 3, 4, 5};          printf("%d\n", array[5]; } 

In this example, we have created an array in C. The array, named array , is five elements long. We have made a novice C programmer mistake here, in that we forgot that an array of size five begins with element zero array[0] and ends with element four, array[4] . We tried to read what we thought was the fifth element of the array, but we were really reading beyond the array, into the " sixth " element. The compiler elicits no errors, but when we run this code, we get unexpected results.

 [root@localhost /]# gcc buffer.c [root@localhost /]# ./a.out -1073743044 [root@localhost /]# 

This example shows how easy it is to read past the end of a buffer; C provides no built-in protection. What about writing past the end of a buffer? This must be possible as well. Let's intentionally try to write way past the buffer and see what happens.

 int main () {     int array[5];     int i;          for (i = 0; i <= 255; ++i){             array[i] = 10;     } } 

Again, our compiler gives us no warnings or errors. But, when we execute this program, it crashes.

 [root@localhost /]# gcc buffer2.c [root@localhost /]# ./a.out Segmentation fault (core dumped) [root@localhost /]# 

As you might already know from experience, when a programmer creates a buffer that has the potential to be overflowed and then compiles the code, the program usually crashes or does not function as expected. The programmer then goes back through the code, discovers where he or she made a mistake, and fixes the bug.

But wait ”what if user input is copied into a buffer? Or, what if a program expects input from another program that can be emulated by a person, such as a TCP/IP network-aware client?

If the programmer designs code that copies user input into a buffer, it may be possible for a user to intentionally place more input into a buffer than it can hold. This can have a number of different consequences, everything from crashing the program to forcing the program to execute user-supplied instructions. These are the situations we are chiefly concerned with, but before we get to control of execution, we first need to look at how overflowing a buffer stored on the stack works from a memory management perspective.



The Shellcoder's Handbook. Discovering and Exploiting Security
Hacking Ubuntu: Serious Hacks Mods and Customizations (ExtremeTech)
ISBN: N/A
EAN: 2147483647
Year: 2003
Pages: 198
Authors: Neal Krawetz

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net