450 likes | 588 Views
Exploitation Crash Course – Spring 2013. UTD Computer Security Group – Scott Hand www.utdcsg.org. Introduction. What we will cover. We are covering software exploitation in a Linux 32-bit environment Topics Buffer overflows (stack and heap) Ret2libc. Tools. Virtualization software
E N D
Exploitation Crash Course – Spring 2013 UTD Computer Security Group – Scott Hand www.utdcsg.org
What we will cover • We are covering software exploitation in a Linux 32-bit environment • Topics • Buffer overflows (stack and heap) • Ret2libc
Tools • Virtualization software • VMware Workstation or VMware Player (free) • Virtualbox (free) • Linux Environment • GDB • Editor (Vim, emacs, etc.) • Python
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
Stack • Grows down from 0xBFFFFFFF • Argv, Environment, and Auxiliary Vectors at base Heap Stack 0xbfffffff
Stack Frame Contents of Stack Stack Pointer (ESP) Stack Base (EBP)
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
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)
Function Calls Visualized • Function A has a stack comprised of a base, contents, and a top (stack pointer) Stack Contents A ESP Base A EBP
Function Calls Visualized • Function A calls Function B, so pushes its arguments and instruction pointer on the stack EIP for A ESP Arguments for B Stack Contents A Base A EBP
Function Calls Visualized • Function B executes its prologue to set up its own stack frame. First, push the old EBP EBP for A ESP EIP for A Arguments for B Stack Contents A Base A EBP
Function Calls Visualized • Now change EBP to ESP’s value. We have a new stack frame EBP for A EBP ESP EIP for A Arguments for B Stack Contents A Base A
Function Calls Visualized • Function B sets up its own locals Stack Contents B EBP EBP for A ESP EIP for A Arguments for B Stack Contents A Base A
Function Calls Visualized • On finishing, function B first cleans up locals EBP for A EBP ESP EIP for A Arguments for B Stack Contents A Base A
Function Calls Visualized • Next, it enters its function epilogue, in which it restores the previous base pointer EIP for A ESP Arguments for B Stack Contents A Base A EBP
Function Calls Visualized • Finally, the EIP is popped and execution continues at its location Arguments for B ESP Stack Contents A Base A EBP
Function Calls Visualized • A does the rest of the cleanup Stack Contents A ESP Base A EBP
GDB • GDB runs on top of the program’s execution • What can we do with it? • Examine disassembled code • Alter the program’s execution • Watch registers • Step through program • Starting it on program “a.out”:gdba.out -silent
Some Useful Commands - Registers • i r – Information about registers (gdb) i r eax 0x1 1 ecx 0xbffff814 -1073743852 edx 0xbffff7a4 -1073743964 ebx 0xb7fcdff4 -1208164364 esp 0xbffff778 0xbffff778 ebp 0xbffff778 0xbffff778 esi 0x0 0 edi 0x0 0 eip 0x8048537 0x8048537 <main+3> eflags 0x246 [ PF ZF IF ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51 • print $regname – Prints register, ex. print $esp
Some Useful Commands - Memory • x/10x ADDR – Examine 10 words at ADDR (gdb) x/10x $esp 0xbffff778: 0x00000000 0xb7e69113 0x00000001 0xbffff814 0xbffff788: 0xbffff81c 0xb7ffeff4 0xb7fff918 0x00000001 0xbffff798: 0x00000000 0xb7fedbdb (gdb) x/10x 0xbffff000 0xbffff000: 0x00000000 0xb7ff0c7c 0x00000000 0x00000000 0xbffff010: 0x00000000 0x000000000x00000000 0xb7fde858 0xbffff020: 0xbffff088 0xb7ffeff4 • x/5i ADDR – Examine 5 instructions at ADDR (gdb) x/5i $eip => 0x8048537 <main+3>: and $0xfffffff0,%esp 0x804853a <main+6>: sub $0x420,%esp 0x8048540 <main+12>: mov %gs:0x14,%eax 0x8048546 <main+18>: mov %eax,0x41c(%esp) 0x804854d <main+25>: xor %eax,%eax • Other useful data types are w (default), s (string)
Some Useful Commands - Breakpoints • b ADDR – Break at address (gdb) b main Breakpoint 1 at 0x8048537 (gdb) b *0x8048637 Breakpoint 2 at 0x8048637 • Remember the * before a hex address • Working with breakpoints: • i b – Information on breakpoints • d – Deletes all breakpoints • d n – Deletes breakpoint n
Some Useful Commands - Execution • r <args> – Run, with optional arguments • c – Continue after breaking • ni – Next instruction (step over) • si – Step one intruction (step into) • Useful with: display/i $pc • finish – Continue until current function returns
Some Useful Commands - Frames • i f – Information about current stack frame (gdb) i f Stack level 0, frame at 0xbffff780: eip = 0x8048537 in main; saved eip 0xb7e69113 Arglist at 0xbffff778, args: Locals at 0xbffff778, Previous frame's sp is 0xbffff780 Saved registers: ebp at 0xbffff778, eip at 0xbffff77c • up, down – Move up or down frames
Some Useful Commands – Misc. • disas FUNCTION – Print disassembly of function(gdb) disas main Dump of assembler code for function main: 0x08048534 <+0>: push %ebp 0x08048535 <+1>: mov %esp,%ebp 0x08048537 <+3>: and $0xfffffff0,%esp 0x0804853a <+6>: sub $0x420,%esp… • list – Shows source if you have debugging info • set confirm off – Stop the nagging! • set disassembly-flavor – Change disas style(gdb) disas main Dump of assembler code for function main: 0x08048534 <+0>: push ebp 0x08048535 <+1>: movebp,esp 0x08048537 <+3>: and esp,0xfffffff0 0x0804853a <+6>: sub esp,0x420
Using Python for Debugging Exploits • Python can be run from the command-line:$python -c ‘print “Message”’ • This can be embedded into command-line instructions with backtick(`) marks:$./a.out `python -c ‘print “Message”’` • gdb works in the same wayr `python -c ‘print “Message”’` • The above commands result in running the program (a.out) with the argument Message
Using Python for Writing Exploits • Break up the exploit string into smaller components • Use the string repeat functionality: “A”*4 “AAAA” • If the program takes command line arguments:$./a.out `python sploit.py`
Reliable Local Exploits • You have to clear the environment, one way to do this is with Python:import ossploit = “big_scary_exploit_string”os.execve(“a.out”,[“a.out”,sploit],{}) • To debug: • gdb python • r sploit.py • b exec • Now you’re ready to debug like normal.
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
Altering Code Execution Flow • Since we can write over stack memory, we can write over the saved EIP address buf[64] Padding Stored EBP Stored EIP New EIP
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
Stack Smashing Illustrated buf[64] NOP Sled Shellcode EBP EIP Evil Pointer
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
Payload buf[64] Padding EBP EIP system() exit() Pointer to “/bin/sh”
Where to put “/bin/sh”? • In buffer, after its address • Environment • Argv • Auxiliary Vectors • Anywhere else reliable
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/exploit-writing-tutorial-part-1-stack-based-overflows/ • 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.
Thanks for coming • Let me know if there are any questions • Weekly meetings are 7pm on Wednesdays in ECSS 4.619 • Come join our team for the upcoming Capture the Flag competitions and put these skills to use