Buffer Overflows
IntroductionBuffer overflows are a class of attack that take advantage of poor
programming, to execute arbitrary commands on a system. They can be
exploited both locally and remotely, depending on the vulnerable piece
of software. Because buffer overflows rely on overwriting certain parts
of the system’s memory, they are both processor and operating system
specific.
Buffers
A buffer is a contiguous piece of memory that contains the same type of
data. In the case of overflow attacks, this block of data is usually an
array of characters. Dynamic variables declared in the code of the
application are allocated space on the stack. To overflow the stack is to
write data past the end of the buffer allocated for any of these variables.
The Stack
The stack can be thought of as a separate memory space that is used to
store local variables when a function or procedure is called. Two
important registers associated with the stack are:
• The Stack Pointer - This points to the top of the stack.
• The Instruction Pointer - This points to the next instruction to
execute.
The Instruction Pointer is the key to executing arbitrary code on the
system, because it contains the address of the next instruction to
execute. If this value is overwritten to point to our own code, this will
be executed when the function completes.
Stack Operation
When a procedure is called, the current Instruction Pointer, Stack
Pointer and all local variables and parameters to the procedure are
pushed onto the stack. The following code extract demonstrates this:
void doSomething(int a, int b, int c) {
char buffer1[5];
char buffer2[10];
}
void main() {
doSomething(1,2,3);
}
When the function, doSomething is called the following operations are
performed:
1. The parameter “3” is pushed onto the stack.
2. The parameter “2” is pushed onto the stack.
3. The parameter “1” is pushed onto the stack.
4. The current value of the Instruction Pointer is pushed onto the stack
and the Instruction Pointer register is updated, to point to the
function's code.
5. The current Stack Frame Pointer is pushed onto the stack and the
register updated.
6. Buffer1 is pushed onto the stack and takes up 8 bytes.
7. Buffer2 is pushed onto the stack and takes up 12 bytes.
Values on the stack can only be in multiples of “words” i.e. 4 bytes. So
even though buffer1 is defined as using 5 bytes, it will have to use 8 (2
words) and buffer2 will have to use 12 bytes (3 words).
The function then executes its code and once it is completed, it looks at
the value of the Instruction Pointer stored in the stack and points the
actual Instruction Pointer to this address, where execution continues.
No comments:
Post a Comment