Quick Links

Buffer Overflows

Buffer overflow attacks are caused by a code’s naive mishandling of user input. Just because you have a buffer of a said size, you cannot guarantee that the user will supply at most that size.

The function we’ll look at here is char *gets(char *s).
By the way, if you look at the man 3 gets page, it literally says “Never use gets()

gets reads data from stdin and stores into the address given by its first parameter s. At the end of input it also writes the null terminating byte \00.

Overwriting variables

Here we have a basic program that asks the user for their name, and then greets the user and tells us a num. It stores the user’s name into the character array name (which has a size of 10).

If our name was Samuel, the program would run something like this…

1
2
3
4
5
6
7
$> ./buffer_overflow

Hey there, what's your name?
> Samuel

Hey there, Samuel!
And the secret number is 12!

Cool, all is as expected.

If we take a look at the memory stored in the program

Memory

Offset000102030405060708090A
ValueSamuel\x00···\x12
Variablenamenum

What if we enter a 10 letter name, perhaps Jacqueline.

1
2
3
4
5
6
7
$> ./buffer_overflow

Hey there, what's your name?
> Jacqueline

Hey there, Jacqueline!
And the secret number is 0!

Hmm that’s strange, why did our secret number become 0?

Memory

Offset000102030405060708090A
ValueJacqueline\x00
Variablenamenum

Remember, gets writes a null terminating byte after it finishes reading the user input. That null terminating byte so happens to be written into the memory for num.

Don’t forget! If you want to store a 10 letter word, you need 10 + 1 = 11 bytes to store it!


In that sense, you can “overflow” your data into another variable to overwrite the values of other variables!

1
2
3
4
5
6
7
$> ./buffer_overflow

Hey there, what's your name?
> __________A

Hey there, __________A!
And the secret number is 65!

Memory

Offset000102030405060708090A
Value__________A
Variablenamenum

The character A is equivalent to the ASCII code 65, which is why we see 65.


Also see Example 1

But that was boring!!! Show me something else!!!

No one:
Me: Alright fine you’ve convinced me.

Modifying return addresses

Having access to the memory in the stack means that not only can we change the function variables, we can also modify the return address of a certain stack frame.

In other words, we can make a function run another function (should we know the function address)

In the above program, when we enter the right password (in this case hello), the program will say “You are awesome!”.
If we don’t know the password, but we know the address of the win function, we could exploit the gets function to overwrite the return address in the stack frame.

1
2
3
4
5
6
7
8
$> echo -e "__________............\xc9\x61\x55\x56" | aslr ./buffer_overflow_return

// Pretend you didn't see this but you should try jump to win at 0x565561c9
Enter the password: Sorry, that wasn't right.
Goodbye!

You are awesome :)
Segmentation fault

Note that we couldn’t just type this in directly because our memory address would be split into characters {\,x,c,9,\,x,6,1,\,x,5,5,\,x,5,6}

In this case we were given the value of the return address that we needed to use, although in reality we probably won’t have access to that (see example 3)!

Example 2
Example 3


Buffer overflows provide attackers a way to write arbitrary data. Whether it be a value, or an address to jump to another function, these vulnerabilities can be troubling and are worth fixing.