views:

65

answers:

5

This an extract from a c program that should demonstrate a bufferoverflow.

void foo()
{
  char arr[8];
  printf(" enter bla bla bla");
  gets(arr);
  printf(" you entered %s\n", arr);
}

The question was "How many input chars can a user maximal enter without a creating a buffer overflow"

My initial answer was 8, because the char-array is 8 bytes long. Although I was pretty certain my answer was correct, I tried a higher amount of chars, and found that the limit of chars that I can enter, before I get a segmentation fault is 11. (Im running this on A VirtualBox Ubuntu)

So my question is: Why is it possible to enter 11 chars into that 8 byte array?

+6  A: 

Your characters are actually exceeding the bounds of the defined array, leading to undefined results. You don't see the effect until you overwrite some memory that is being used for something else.

The language and runtime aren't doing anything to prevent you from overflowing the buffer, which is precisely why these bugs are so bad and sometimes hard to track down.

For these reasons, functions like gets are getting deprecated for safer functions (getline in this case) that ask for the length of the array where they will store data.

See: http://crasseux.com/books/ctutorial/gets.html

Also, you can only reliably store 7 characters because you need the 8th for a null terminator.

FogleBird
+3  A: 

Probably because of alignment and/or padding. There might be some "spare" memory there, that is not actually used so when you overwrite it, nothing breaks. That doesn't mean it's correct or that it works, just that it doesn't fail right now, for you, on that machine using that compiler, chair, hair color and so on.

unwind
+1  A: 

There just happened to be enough free memory for you to store the extra data. You should never rely on that and always keep data within the bounds of the array.

The number of characters actually permitted in your example are 7 "standard" characters plus the NULL character (8 total).

Tim Cooper
+1  A: 

In C there is nothing stopping you from going past the end of an array. When you get the string into memory it will fill up your array, and then keep filling memory until something actually stops it. In larger programs this can mean overwriting other variables in memory, which leads to bugs that are very difficult to track down. On a separate note, you may want to think about how C finds the end of a string when determining how big of a string will fit in a memory location.

tloach
+2  A: 

(Im running this on A VirtualBox Ubuntu) So my question is: Why is it possible to enter 11 chars into that 8 byte array?

11+1 for zero termination = 12 characters. IOW crash occurs when gets() writes 13 characters into the arr[8].

You haven't posted precise stack trace, but from my experience it should have crashed after foo()'s return.

Stack frame (with for void foo() + gets()) would look like (*):

  • <lower memory address>
  • gets() local variables
  • saved stack pointer at the moment of gets() call (so called "prologue")
  • return address, points to foo()
  • foo() local variables (your char arr[8])
  • saved stack pointer at the moment of gets() call
  • return address, points to caller of foo()
  • <higher memory address>

From all the information, the most important bits are the return address and saved stack pointer. And write of 13th byte in your case likely has corrupted the saved stack pointer of foo() function. Highly likely call of the following printf() would succeed, as the stack pointer is still valid (last changed by returning from gets()). But the returning from foo() would cause the foo()'s saved stack pointer (now corrupt) to be restored and then any action accessing stack from inside the calling function would go to a bad address.

From my experience this is the likeliest scenario. When stack is corrupt, it is really hard to tell for sure what would happen.

(*) For precise details how stack frame is constructed look for ABI - Application Binary Interface - for your architecture: for example IA-32 ABI for Intel i386 or AMD64 ABI for AMD64.

Dummy00001