Tutorial – Buffer Overflows Part 2

Buffer Overflows Part 2!

This is a continuation from my first Buffer Overflow Tutorial; I would highly recommend that you read that tut, before you read this one! (Even if you’ve read it before re-read it to refresh your memory!)

Ok, so in part one we looked at

How a Buffer Overflow happens and the security implications of this.
Ways to find what programs have SUID privileges using the

find / -type f –perm -04000 –ls command .

We also looked at how to change a program to give it #root privileges.

I will start this tutorial off at the point where, you have compiled a piece of code that is vulnerable to an overflow (see part 1), you have changed the ownership of the program to root and you have made it a SUID root program. We will call this program “pool” Smile

So, we know pool can be exploited with a buffer overflow (as we programmed it) and we know it has root privileges (as we gave them to it)

Now what we need to do is generate a program with a buffer (remember a buffer is a portion of memory assigned to a program) that contains the shellcode, which will spawn a shell that can be “fed” into the pool program. We will call this program “snooker” Smile

Our aim is to make the program pool overflow in to the buffer that the program snooker has given it and make the EIP point to where our shellcode within this buffer and then to make snooker accidentally execute this shellcode.

Obviously for this to work we need to know where our shellcode is stored in the buffer!

There two main ways of doing this: Using a NOP sled or by flooding the end of a buffer with quite a few “return addresses”.

No Operation (NOP)

As the name suggests this is an instruction that does nothing, its sole purpose is to take up a byte of memory so nothing else can occupy it.

Why is this useful to us?

For a few reasons really.

1. If our NOP is occupying a byte of memory we know that our shell code couldn’t possibly be there!
2. The processor will skip over a NOP until it gets to something that tells it to do something, i.e. our shellcode (hopefully)
3. A program wont crash if it hits a NOP as the NOP isn’t telling it to do anything, it will just move down or up to the next memory “block”

Consider this (each number represents a bock of memory in our buffer)

Pool Snooker Snooker Shellcode Snooker Snooker Snooker Snooker
1………..2…………3………….4………….5………….6………..7………….8…..
For us to execute our shellcode we would have to ensure the EIP was pointing at “4” and no where else, otherwise snooker would continue to run. There would be a lot of trial and error not to mention luck in executing the shell code!

But, what about if we done this:

Pool Snooker NOP NOP NOP NOP NOP Shellcode
….1……2……..3…….4…….5…….6…….7…….8
As long as the EIP was pointing at either 3,4,5,6,7 or 8 our shellcode would be executed, because as I said earlier the processor would just skip along them NOP’s until it got to something it could execute!
Obviously this gives us a bigger area of error for the EIP to execute the shellcode
So along as we overwrite the EIP with any address in the NOP we can be assured our shellcode will be executed

Thanks!
Nokia

TAZ Forum :: A Computer, Gaming, and Social Network Community of Friends :: View topic – Tutorial – Buffer Overflows Part 2

Advertisements

Tutorial – Buffer Overflows Part 1

Buffer Overflows – what they are and how they work.

This can be quite a complicated issue, so I will try to break it down into different parts and put it into everyday language.

I will assume that if you are reading this you understand a little programming (functions, integers etc)

To understand buffer overflows it helps to know a bit about how a program utilizes memory.

First it will help to understand what an EIP is:

[it is essential to understand an EIP to understand how a buffer overflow works]

EIP:
Extended Instruction Pointer.

The processor has a very small chunk of memory itself, divided into what is called registers.
The most common register is the EIP; this tells the processor where to look in the system memory for the function (or piece of code) that it has to execute.

I.e. the code could be to print the word antionline on to your monitor and has been written to the memory at the address of 0x12345678. (Memory uses the hex numbering system).
The EIP would now tell the processor to go to 0x12345678 and do what ever the code is telling it to do, hence the word “antionline” will be printed on the screen.

Program memory:

There are five types of program memory, text, heap, stack, bss and data.
Each one of these is a special piece of memory reserved for a certain type of purpose.

I will cover text and stack for the purpose of this paper.

Text:

This is where the compiled machine language is stored. Write permissions are disabled here as it is used only to store the code, which is being executed.

When you compile a program, what you are doing is converting it from human readable form into a language the computer understands, it is the output of a compiled program that is stored in the text segment)

So for a very simplified example say you wanted to print the words Hello, goodbye, thank you, and Microsoft rules Wink

(For ease I will use 1,2,3,4,5 etc for memory addresses instead of the correct addresses.

So hello is stored at 1, goodbye at 2, thank you at 3 and Microsoft rules at 4.
Here is what the processor will do

1. Get the address for the first function to complete from the EIP and go there
2. Add the number of bytes in the instruction to the EIP
3. Do what ever the piece of code is telling it to do, (print Hello.)
4. Go back to the EIP to get the next address.

The EIP will know when the instruction has been completed because in step 2 the processor told it how many bytes there was.

Stack:

The stack memory is used as a tempory storage space for functions.

When a function (print) is called by a program it will have its own variables (hello,goodbye,thank you etc)

and the code will be at a different place in the text segment of memory.

(I.e. hello cannot be at the same memory address as goodbye otherwise they would over write each other.)

So the function is to print Hello (1) Goodbye (2) and Thank you (3)

The whole function will be read from the text segment and get passed to the stack segment.
The stack segment will remember the addresses (1,2,3) of each variable and pass this data to the EIP to tell it which memory address to return to when the function is finished.

There is a lot more to the stack segment but it’s not really relevant at this point!

BUFFER OVERFLOWS

Ok, so the programmer has specified that the word Hello with need 5 bytes of memory, but what happens when 7 characters try to write them selves to this piece of memory instead, the word goodbye for example:

|H|E|L|L|O| – No probs here
1 2 3 4 5

|G|O|O|D|B| —— |Y|E| – | – | – | – They overflow into memory held for something else
-1- 2- 3-4-5 —— -6- 7- 8- 9 – 0

5 bytes are allocated but the variable was 7 bytes long. Now it can’t just disappear, it has to be written somewhere so a buffer overflow occurs. If the data that was overwritten in 6 + 7 were a critical part of the program, the program would have crashed.

Here is a well know piece of code to cause a buffer overflow (its very well known and is in most books about the subject, so know one jump on my back for posting it, please)

TAZ Forum :: A Computer, Gaming, and Social Network Community of Friends :: View topic – Tutorial – Buffer Overflows Part 1