8/17/15

'Buffer Overflow' Hacking Attack.

Processes & Memory Allocation.

'process' is a running computer program.

for this to happen, a certain amount of computer's memory must be reserved (allocated) for the process. both for code as well as for data.

memory reserved for process is split into 'segments'.

in x86 processor machines, there are following segments:
- 'text segment' is also called 'code segment'. in this segment all of instructions written by programmer are stored in a 'machine language form'. nothing can be written there, segment's size cannot be changed after loading program into memory.
- 'data segment' contains both global variables, as well as declared constants, for example: 'character strings'.
- 'bss segment' contains static variables, as well as uninitialized global variables.
- 'heap segment' has dynamic size - can be resized during program's run; it's used for storing dynamic variables that are created & destroyed by user as programmer allowed.
- 'stack segment' is automatically used by local variables of called functions, storing for example call's arguments. it's similar to 'heap segment' in that it can be resized.


Buffer Overflow.

it's that a 'buffer overflow' is often called a 'stack overflow'.

often 'buffer overflow' affects stack, that's why we'll examine 'stack segment' properly.

'stack' can be imagined as 'tower of blocks', with a constant base, with variables being put on it's top. each of tiers makes this tower higher & higher. both stack & tower have a given size. after reaching critical maximum size tower can be toppled, stack can overflow memory. when we reach for variable on stack, we take topmost one.

operating on stack is possible with two basic commands:

PUSH - is: 'put a value on stack',
POP - is: 'get a value from stack'.

of course system must know a current address of stack's top, to remove variables one by one. processor uses ESP register for that (Extended Stack Pointer).


let's look at a following code, on an image:



code with 'stack' used in a function call.


stack after a call of func(argc) should look as on following image:


stack.


when program starts, it stores program's arguments on stack first. we have: 'int argc' & 'char *argv[]' on stack.

then main function is called, next tier (position) on stack is filled with copies of register values of EIP & EBP.

EIP is called 'instruction pointer', it points at next instruction to process during program's run. when we store that register value, we know where to return after completing called function's run.

EBP is 'Extended Base Pointer' stores last stack's top address.

next step in this program's run is calling a function func(argc). we put on stack argument(s) passed to a function, in this case: number of arguments that user passed to program as it was run. next we put EIP & EBP register values - this time they are associated with returning from function func.


Buffer.

a buffer is memory fragment reserved for storing a given amount of data. if programmer won't take care of controlling amount of data, it's easy to overflow a buffer ... leaving an opening for a hacking attack.

if amount of data is more than buffer's maximum size, rest of data is written in another memory area, nearby.


'Buffer overflow' attack.

let's look at another image with another program.



a program vulnerable to a 'buffer overflow' attack.


writing 1 or 10 of '32-bit byte long' characters did not overflow buffer, as buffer is of a size of 10.

'strcpy' function copies character strings without copying an 'end of string' character.

adding one more character did overflow buffer, however ... overwriting variable 'a' with a value of '0x41' of 'A' character.




more exercises,

'Segmentation fault' error as well.


adding too many of characters, however, will result in an 'Segmentation fault' error, meaning that program attempted to write to memory area that was not assigned to it.


how many is enough ?

this depends on a hardware-software configuration, we'll show that with an example.


depending on a 'hardware-software configuration' we can have C language compiler that allocates different amount of 'stack bytes' ... different depending on a mentioned 'hardware-software configuration'.


on used operating system (SSO v2.0) we have a gcc compiler with a preferred-stack-boundary variable, that determines amount of allocated stack bytes.

it's power of 2, so the programs will have stack space allocated equal to n-th power of 2.

by default it's assigned a value of 4, so stack will have 24 = 16 bytes allocated.


we'll show this using a gdb debugger.



stack size is 16 dec = 10 hex.


we can see we have 16 bytes allocated on stack,

a value of 'ceiling' of 24 = 16 & of size of a 'buffer' variable, 10.


lets see another image & lets compare results.



stack size is 16 dec = 10 hex, again.


we can see that assembler code is same as before, with 16 bytes allocated on stack again,

a value of 'ceiling' of 24 = 16 & of size of 'a' variable, 1.


lets change value of preferred-stack-boundary variable to 2, so we have 22 = 4 bytes of stack.



stack size is 4 dec = 4 hex.


we can see we have 4 bytes allocated on stack,

a value of 'ceiling' of 22 = 4 & of size of 'a', 1.


Attack on a 'protected application'.

we'll exploit 'scanf' function's use without checking read string's size.

let's look on image:



a buffer overflow.


we've overwritten an 'ok' variable with non-zero, a truth value.

what if there's no 'ok' variable? let's look at image with a more difficult example.



debugger's use.


we've passed 32 of 'A' characters to first argument of an application.

this resulted in a memory protection error (Segmentation fault).

why?

because EIP & EBP register values were overwritten with 0x41414141 bytes, as a result of putting there 'AAAA' string (0x41 is 'A').

when we call a function, in preparation, there are EIP & EBP register values put on stack. as we did stack overflow, we've overwritten these register values as they were stored on stack. during a return from check_login function, we retrieve these values & use stored EIP to determine where to 'jump' next with software's execution. we were trying to 'jump' to an address 0x41414141, somewhere where we do not have access to - therefore we got an error message, Segmentation fault.

how to use this situation to our advantage ?

let's check where we can actually jump to.

let's disassemble 'main' function.



'main' function disassembled.


conditional instruction if is realized in assembler using using 'test' & 'je' or 'jne' instructions.

in this case, 'je' instruction jumps in a case of 'false' tested value, when an instruction is not executed due to wrong credentials.

we're interrested in jumping to a point after 'je' instruction, where we have a 'case' for 'right credentials'.

it's 0x08048556, but we have to present it in a 'little-endian' form.



a stack overflow with a 'jump to case'.


... but why we did have to pass 32 byte-long characters to program ?

let's examine check_login function body.



'check_login' function disassembled.


we can see there three 'register push' instructions, plus there's EIP register pushed when we call a function.



a Stack.


... so it's 4x four-byte-long registers, plus 16-byte-long login variable, totalling 32 bytes.


'Buffer overflow' with a 'shellcode injection'.

let's look at code on a following image.



Buffer overflow with a core dump displayed in a debugger.


EIP was filled with 0x41414141 value, as in a previous example.

This time, however we do not have any interresting code part to 'jump' to, as application does not use 'execl'.

We have to provide that a code part, with a 'shellcode'.



a shellcode, written in assembler ... displayed with an object file's dump.


this shellcode is explained with details in this post.

looking at dump at right side of the image, we see result of command 'objdump -d shell2' where 'shell2' is name of the program to be dumped.

based on that a dump, we can write shellcode in 'more machine language form', which looks like that:



shellcode, hexadecimal notation form.


now we can write 'exploit' program that 'injects shellcode' into vulnerable application, then overwrites EIP to 'jump to shellcode'.



'exploit' program that 'injects shellcode' into to a program that is vulnerable to a 'buffer overflow'.



see also, if You wish or need ... : Buffer Overflow Attack, 'Heap Overflow' Hacking Attack, 'Format String' Hacking Attack.

source: [14].

No comments:

Post a Comment