Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Exploitation Crash Course

80 views

Published on

This presentation goes over basic exploitation techniques. Topics include:

- Introduction to x86 paradigms used exploited by these techniques
- Stack overflows including the classic stack smashing attack
- Ret2libc
- Format string exploits
- Heap overflows and metadata corruption attacks

Published in: Technology
  • Login to see the comments

  • Be the first to like this

Exploitation Crash Course

  1. 1. EXPLOITATION CRASH COURSE UTD Computer Security Group – Scott Hand www.utdcsg.org
  2. 2. Introduction
  3. 3. What we will cover  We are covering software exploitation in a Linux 32-bit environment  Topics  Buffer overflows (stack and heap)  Format string  Ret2libc
  4. 4. Tools  Virtualization software  VMware Workstation or VMware Player (free)  Virtualbox (free)  Linux Environment  GDB  Editor (Vim, emacs, etc.)  Python
  5. 5. Exploit-Exercises - Protostar  Great learning environment  Stack, heap, format string, etc. vulnerabilities  Can be downloaded and run from VMware or Virtualbox
  6. 6. x86 Background
  7. 7. Linux Memory Structure  .text  Contains program instructions  Readable, executable, not writable  Heap  Contains dynamically allocated memory objects  Readable, writable, (usually) executable  Stack  Contains static variables and base pointers  Readable, writable, (sometimes) executable
  8. 8. Stack  Grows down from 0xBFFFFFFF  Argv, Environment, and Auxiliary Vectors at base Stack Heap 0xbfffffff
  9. 9. Stack Frame Contents of Stack Contents of Stack Stack Base (EBP) Stack Pointer (ESP)
  10. 10. Common Register Conventions  ESP – Stack Pointer  EBP – Stack Frame Base Pointer  EIP – Instruction Pointer  EAX, EBX, ECX, EXD – Fairly widely used, often used as function arguments
  11. 11. Function Calls  The x86 instruction CALL is used, which automatically does the following:  Put all the arguments onto the stack (right to left)  Put instruction pointer (EIP) onto stack  Now in the callee, push base pointer onto stack and set base pointer to stack pointer (function prologue)  Execute instructions in new function  Clean up locals  Set stack pointer to base and restore base pointer by popping the stack (function epilogue)
  12. 12. Function Calls Visualized  Function A has a stack comprised of a base, contents, and a top (stack pointer) ESP EBP Stack Contents A Base A
  13. 13. Function Calls Visualized  Function A calls Function B, so pushes its arguments and instruction pointer on the stack ESP Stack Contents A Base A EIP for A Arguments for B EBP
  14. 14. Function Calls Visualized  Function B executes its prologue to set up its own stack frame. First, push the old EBP EBP for A Stack Contents A Base A EIP for A Arguments for B ESP EBP
  15. 15. Function Calls Visualized  Now change EBP to ESP’s value. We have a new stack frame ESPEBPEBP for A Stack Contents A Base A EIP for A Arguments for B
  16. 16. Function Calls Visualized  Function B sets up its own locals EBP EBP for A Stack Contents A Base A EIP for A Arguments for B Stack Contents B ESP
  17. 17. Function Calls Visualized  On finishing, function B first cleans up locals EBP for A Stack Contents A Base A EIP for A Arguments for B ESPEBP
  18. 18. Function Calls Visualized  Next, it enters its function epilogue, in which it restores the previous base pointer Stack Contents A Base A EIP for A Arguments for B EBP ESP
  19. 19. Function Calls Visualized  Finally, the EIP is popped and execution continues at its location Stack Contents A Base A Arguments for B EBP ESP
  20. 20. Function Calls Visualized  A does the rest of the cleanup Stack Contents A Base A EBP ESP
  21. 21. Stack Based Buffer Overflows
  22. 22. Overview  Stack based buffer overflows occur when writing goes past the boundaries of local variables  Example: char buf[64]; strcpy(buf, argv[1]);  The previous example will overflow buf’s boundaries and write onto stack memory if argv[1] contains more than 64 bytes  This allows us to alter local variables and also change the execution of the program
  23. 23. Altering Code Execution Flow  Since we can write over stack memory, we can write over the saved EIP address Stored EIP Stored EBP buf[64] Paddin g New EIP
  24. 24. Demos – Stack1 through Stack4
  25. 25. Stack Smashing  Now we want to achieve execution of arbitrary code  Instead of giving EIP the address of another function, we give it the address of our buffer  Our buffer contains machine code instructions (known as shellcode)  For reliability, we use 0x90 opcodes to pad before our shellcode, these are NOP instructions and execution will slide past them if it lands there
  26. 26. Stack Smashing Illustrated buf[64] EBP EIP Shellcode NOP Sled Evil Pointer
  27. 27. Demo – Stack Smashing
  28. 28. Ret2libc
  29. 29. Overview  What happens if we’re working with a slightly more modern machine with non- executable stack memory?  Rather than write our own code to spawn a shell, let’s use libc!  We will use system() for the demonstration for simplicity, but bear in mind that system drops privileges, so execv() is needed for privilege escalation
  30. 30. Payload buf[64] EBP EIP Padding system() exit() Pointer to “/bin/sh”
  31. 31. Where to put “/bin/sh”?  In buffer, after its address  Environment  Argv  Auxiliary Vectors  Anywhere else reliable
  32. 32. Demo – Ret2libc
  33. 33. Format String
  34. 34. Background  printf() and similar format string functions such as sprintf() are used for string interpolation in many languages including C  Intended use:  Give a string containing text and format flags  Format flags are replaced with arguments to printf  Example: printf(“%d %dn”, 3, 3+4); // Prints 3 7
  35. 35. What could go wrong?  How are user provided strings printed?  Good: printf(“%s”, str);  Bad: printf(str);  Why is this important? The user could supply their own format flags and your program will trust it.  GCC will give a very stern warning if you try to do this
  36. 36. What can we do with this?  Giving lots of flags will mean that variables will be pulled from the stack – even if they weren’t passed to printf  This leads to information leakage.  Lets look at an example…
  37. 37. sf.c #include <stdio.h> int main(int argc, char *argv[]) { int a = 0xDEADBEEF; int b = 0xABCDABCD; int c = 0x12345678; printf(argv[1]); printf("n"); return 0; }
  38. 38. sf.c Exploited  ./sf AAAA  Output: AAAA  ./sf AAAA%x  Output: AAAAb7fd7ff4  ./sf AAAA%x%x%x%x%x  Output: AAAAb7fd7ff48048450bffff7e8b7ec6365de adbeef
  39. 39. sf.c Exploited  There one of the local variables. Is there an easier way?  ./sf AAAA%5$x  Output: AAAAdeadbeef  ./sf AAAA%6$x  Output: AAAAabcdabcd
  40. 40. It gets worse  One of the flags, %n, has the following effect:  The number of characters written so far is stored into the integer indicated by the int * (or variant) pointer argument. No argument is converted.  So now we can write where ever we want!  What’s the process?  First, put the address to write to in the payload  Increment the number of characters written using the %x flag with a number. Ex: %10x prints ten spaces.  Call %n on the appropriate stack byte containing the pointer  Repeat
  41. 41. Example with sf.c – Finding offsets  Modified sf.c checks if a==c, so 0xabcdabcd needs to be replaced with 0xdeadbeef  First, find how many %x flags needed to reach your payload on the stack.  With our python harness to keep environment constant, we get 107  Looking in GDB gives an address of 0xbffffe58 for the the value 0xabcdabcd
  42. 42. Example with sf.c – Calculations  The last byte should be 0xEF (239)  We’ve written 5 bytes (4 and the spam one we’re crafting), so we want to write 234 more  Due to having to pad our string with As to line the address up, our payload now looks like: x58xfexffxbfA%234x%108$n  Running this confirms that now there’s a 0x000000ef where 0xabcdabcd was  What now?
  43. 43. Example with sf.c – 2 at a time  We could write the last byte, then the one before, and so on. This takes four writes, so it wastes shell code space. It clobbers the preceding byte, but we probably don’t care too much  Example: 00000000000000ef Wrote 0xEF 000000000000beef Wrote 0xBE 0000000000adbeef Wrote 0xAD 00000000deadbeef Wrote 0xDE
  44. 44. Example with sf.c – Using hc  Luckily, adding h in front of n writes a 16-bit integer instead  For 0xdeadbeef, that means two writes. Increment by 48874, write the 0xbeef half, then increment that by 8126 to write the 0xdead half.  This all gets a bit messy and the addresses will start to shift around depending on the length of the exploit, so use a script to pad it to the same length every time.
  45. 45. Example with sf.c – Script  After having to tweak addresses again, final payload building script: payload = “x38xfexffxbfx3axfexffxbfA%48870x%108$hn%8126x %109$hn” payload += "A" * (40 - len(sploit)) print payload  Running it, we see in gdb that we were successful, and we also get the victory message.
  46. 46. Other nefarious uses  Overwrites return addresses  Overwrites GOT entries  Overwrite terminators to cause overflow  Write shellcode to non-stack memory  Leaking information to bypass ASLR
  47. 47. Demo – Echoserver Format String
  48. 48. Heap Based Overflows
  49. 49. Heap Overview  We learned about the stack. Programs store local variables there.  Heaps are for storing globals as well as variables too large for the stack  In Linux:  .data – Initialized globals  .bss – Uninitialized globals  Heap – Dynamically allocated space, grows upwards  Stack – Local variables, grows down
  50. 50. Memory Allocation Data Structures  glibc uses a version of the popular dlmalloc algorithm  Memory is allocated in chunks. Each chunk is 8-byte aligned with a header and data.  Each chunk contains:  Size information before and after the chunk – Easy to combine chunks and allows bidirection traversal from any chunk. Trailer fields are sometimes omitted in recent implementations  Chunks are stored in a linked list of bins, sorted by size in continuous increments of 8 for sizes under 512. Over 512 can be any multiple of 8.  Upon freeing a chunk, it is combined with freed neighbors to lower fragmentation  The final “top” chunk is empty and its size records the remaining about of free space
  51. 51. Binning Size: 16 Size: 24 Size: 32 Size: 512 Size: 576 Size: 231 … … Chunk 1 Chunk 2 Chunk 3 Chunk 4 Chunk 5
  52. 52. Some Consequences  Locality Preservation  Chunks allocated at the same time tend to be referenced similarly and have coexistent lifetimes  Important for good performance, reduces cache misses  A tweaked version of nearest-fit is used that results in consecutive blocks when there is space  This is good for us  Easy to create overflows, as memory allocated after vulnerable variables is often given to other variables nearby that may be for things such as function pointers or file paths
  53. 53. Malloc Example  We want to see what the heap looks like as more memory is allocated  We will allocate three strings: a, b, c. Each is 32 bytes.  Code: char *a, *b, *c; a = malloc(32); b = malloc(32); c = malloc(32);  This will serve as an introduction to the heap3 problem
  54. 54. First Allocation 0x0804c000 8 Byte Size – 0x29 0x0804c008 32 Byte Data Chunk 1 a Remaining Space: 0xFD9
  55. 55. Second Allocation 0x0804c000 8 Byte Size – 0x29 0x0804c008 32 Byte Data Chunk 1 a 0x0804c028 8 Byte Size – 0x29 0x0804c030 32 Byte Data Chunk 2 b Remaining Space: 0xFB1
  56. 56. Third Allocation 0x0804c000 8 Byte Size – 0x29 0x0804c008 32 Byte Data Chunk 1 a 0x0804c028 8 Byte Size – 0x29 0x0804c030 32 Byte Data Chunk 2 b 0x0804c050 8 Byte Size – 0x29 0x0804c058 32 Byte Data Chunk 3 c Remaining Space: 0xF89
  57. 57.  Now, the interesting (and exploitable) part involves the free() implementation in dlmalloc  Let’s examine the contents of memory after successive free() commands are executed.  Code: free(c); free(b); free(a); Free Example
  58. 58. Before First Free 0x0804c000 8 Byte Size – 0x29 0x0804c008 “AAAA0” Chunk 1 a 0x0804c028 8 Byte Size – 0x29 0x0804c030 “BBBB0” Chunk 2 b 0x0804c050 8 Byte Size – 0x29 0x0804c058 “CCCC0” Chunk 3 c Remaining Space: 0xF89
  59. 59. After First Free 0x0804c000 8 Byte Size – 0x29 0x0804c008 “AAAA0” Chunk 1 a 0x0804c028 8 Byte Size – 0x29 0x0804c030 “BBBB0” Chunk 2 b 0x0804c050 8 Byte Size – 0x29 0x0804c058 “0” * 32 Chunk 3 Remaining Space: 0xF89
  60. 60. After Second Free 0x0804c000 8 Byte Size – 0x29 0x0804c008 “AAAA0” Chunk 1 a 0x0804c028 8 Byte Size – 0x29 0x0804c030 “0x0804c050” Chunk 2 0x0804c050 8 Byte Size – 0x29 0x0804c058 “0” * 32 Chunk 3 Remaining Space: 0xF89
  61. 61. After Third Free 0x0804c000 8 Byte Size – 0x29 0x0804c008 “0x0804c028” Chunk 1 0x0804c028 8 Byte Size – 0x29 0x0804c030 “0x0804c050” Chunk 2 0x0804c050 8 Byte Size – 0x29 0x0804c058 “0” * 32 Chunk 3 Remaining Space: 0xF89
  62. 62. Demos – Protostar Heap Problems
  63. 63. Heap3  We know from Heap3’s description that it “introduces the Doug Lea Malloc (dlmalloc) and how heap meta data can be modified to change program execution.”  What metadata in particular?  Let’s review the process of freeing a chunk from the last presentation…
  64. 64. Before First Free 0x0804c000 8 Byte Size – 0x29 0x0804c008 “AAAA0” Chunk 1 a 0x0804c028 8 Byte Size – 0x29 0x0804c030 “BBBB0” Chunk 2 b 0x0804c050 8 Byte Size – 0x29 0x0804c058 “CCCC0” Chunk 3 c Remaining Space: 0xF89
  65. 65. After First Free 0x0804c000 8 Byte Size – 0x29 0x0804c008 “AAAA0” Chunk 1 a 0x0804c028 8 Byte Size – 0x29 0x0804c030 “BBBB0” Chunk 2 b 0x0804c050 8 Byte Size – 0x29 0x0804c058 “0” * 32 Chunk 3 Remaining Space: 0xF89
  66. 66. After Second Free 0x0804c000 8 Byte Size – 0x29 0x0804c008 “AAAA0” Chunk 1 a 0x0804c028 8 Byte Size – 0x29 0x0804c030 “0x0804c050” Chunk 2 0x0804c050 8 Byte Size – 0x29 0x0804c058 “0” * 32 Chunk 3 Remaining Space: 0xF89
  67. 67. After Third Free 0x0804c000 8 Byte Size – 0x29 0x0804c008 “0x0804c028” Chunk 1 0x0804c028 8 Byte Size – 0x29 0x0804c030 “0x0804c050” Chunk 2 0x0804c050 8 Byte Size – 0x29 0x0804c058 “0” * 32 Chunk 3 Remaining Space: 0xF89
  68. 68. Free Algorithm on Chunk p 1. Load the chunk’s size as psize, previous chunk is p-psize 2. A few scenarios can occur, but what we’re interested in is the case in which the surrounding chunk is also free 3. To consolidate, call: unlink(nextchunk, bck, fwd)
  69. 69. unlink(P, BK, FD) - Highlights … FD = P->fd; BK = P->bk; … FD->bk = BK; BK->fd = FD; …
  70. 70. Disassembled… 0x80498fa <free+214>: mov edx,DWORD PTR [ebp-0x18] 0x80498fd <free+217>: mov DWORD PTR [eax+0xc],edx 0x8049900 <free+220>: mov eax,DWORD PTR [ebp-0x18] 0x8049903 <free+223>: mov edx,DWORD PTR [ebp-0x14] 0x8049906 <free+226>: mov DWORD PTR [eax+0x8],edx The underlined instructions correspond with the previous two lines in unlink. bk is 12 bytes offset, fd is 8 bytes offset.
  71. 71. Exploit Idea  We overwrite the size information for our b pointer, so that when it tries to find the previous memory chunk (previously c), we point it elsewhere.  Giving it a negative size means it will go forward to a “fake” previous chunk with fd and bk of our choosing.
  72. 72. Crafting the Fake Chunk  Give a size of 0xFFFFFFFC = -4 to chunk 2  This pushes it forward 4 bytes, so it will then look to b+16 for the bk pointer and b+12 for the forward pointer.  Adjusting for header, that means fd and bk will be 4 and 8 bytes into our body respectively  chunk2 = “BBBB”+word1+word2+”B”*20
  73. 73. What Now?  So now we can:  Load word1’s address into the memory at location word2 + 8  Load word2’s address into the memory at location word1 + 12  Actually pretty restrictive, as word1 and word2 need to be able to serve as a pointer to a writable region as well as data to write
  74. 74. Ideas  One word is the address of winner() – 12, the other is the stored EIP  Doesn’t work – We can’t write at winner() – 12   Overwrite the GOT entry for puts  Still doesn’t work. Any time we are trying to put winner()’s address somewhere, we can’t because that memory is not writable
  75. 75. Better Idea  One word will be a pointer to stack memory, the other will be a pointer to the stored EIP  Both locations are writable  Our stack is executable, and our program arguments are there. Let’s just overflow chunk 3’s contents to store the payload.  Exploit strategy:  Hijack EIP and send it to the heap  Execute custom shellcode that goes to winner()  Victory!
  76. 76. Writing the Shellcode  All we want our shellcode to do is jump to winner() and exit cleanly  There are some space considerations. Because of the double write, one byte gets clobbered after 16 bytes  Some trial-and-error shows that winner() returns to a location that’s under ESP in the stack as soon as our shellcode begins execution
  77. 77. Payload Pseudocode  Pop the stack  Push original stored EIP  Push winner  Return Why do we push original stored EIP? It’s nice to avoid segfaulting when we can.
  78. 78. Payload ASM Code POP eax PUSH 0xb7eadc76 PUSH 0x8048864 RET (Note: Your addresses may vary)
  79. 79. Payload Shellcode “ x58x68x76xdcxeaxb7 ” . x68x64x88x04x08xc3 ” I used metasm for this. Does its work in 12 bytes.
  80. 80. Slightly Nicer Shellcode  Something I use since originally giving the Heap3 presentation is the 0xEB opcode. It takes a single byte and jumps that far ahead.  So EB 06 would skip ahead 1 byte (and a half for the other half of this byte)
  81. 81. Results Starting program: /opt/protostar/bin/heap3 `python ~/solutions/h3.py` dynamite failed? that wasn't too bad now, was it? @ 1329993598 Program exited with code 056.
  82. 82. Conclusion
  83. 83. Future Reading  We didn’t cover any Windows exploitation. If you want to learn the tools and techniques for the Windows environment, check out the Corelan tutorials at: https://www.corelan.be/index.php/2009/07/19/ex ploit-writing-tutorial-part-1-stack-based-over flows /  We covered Ret2libc, but the next step in mitigation evasion, Return Oriented Programming (ROP) wasn’t covered. It’s worth it to read up on this, as it’s complex, but extremely powerful.
  84. 84. Thanks for coming  Let me know if there are any questions  The next CSG Crash Course will cover Cryptography and will be at 2pm on September 22 in ECSS 2.415  Weekly meetings are 7pm on Wednesdays in ECSS 4.619  Come join one of our teams for the upcoming CSAW2012 Capture the Flag competition and put these skills to use

×