pop pop ret… A session on getting your sploit to exploit. What’s the master plan again? • Introduction (a repeat of earlier concepts and intro to the tools). • Vulnerabilities. • Vectors. ** YOU ARE HERE ** • Payloads. • Putting them together. • And maybe a lab if and only if requested. • Maybe a session on defensive techniques if and only if requested. So, what was a vulnerability? • A flaw in programming that allows us to do something we shouldn’t be able to. • Most of these involve allowing us to overwrite memory addresses the OS uses. • Vulnerabilities are BUGS! What’s a Vector ? • The process of overwriting something in memory, left vulnerable by the vulnerability, that will allow us to run “arbitrary code”. • Arbitrary code, aka the payload or possibly shellcode. • At a technical level, we need to get our instructions in the CPU register EIP (32 bit). – EIP is the next instruction to get executed What’s our exploit methodology? • Find the vulnerability. • Figure out what kind of vulnerability it is. – How do we create those conditions? • Figure out the vector. – What structures can we overwrite to gain control? • Write/steal/copy/buy our payload. Review of Security bugs in general • DoS – • Sanitization – • Programmer forgets to clean out infomoration. • SQL injection is actually a sanitization issue. • Real life example: Netscreen dhcp buffer filled with admin’s web passwd. Information Leak – • Easy example: pointing to invalid memory addressing can crash an application Lets user get information they aren’t supposed to have. • Directory traversal • Real life: CVE-2006-1056 allowed registers leaking between processes Oh yea, and Memory Overwrite bugs! – Why we have jobs – Usually the most powerful Memory Overwrites, aka buffer overflows • Dangerous functions – Strcpy(dst,src); – Strcpy doesn’t impose any limit on the amount of data copied, so we can flood dst and reach OS structures. Could be on stack or heap. The vectors will be very VERY different. Memory Overwrites • Dangerous functions – format strings – Came about in 1999 • char someBuffer[256]; • Printf(someBuffer); • Should have been printf(“%s”,someBuffer); – Real life examples: wu-ftpd, Linux rpc.statd, Apache + PHP3 – Includes sprintf, vprintf, fprintf, etc. as well as syslog, warn, vwarn Format Strings common manipulators • • • • • %s -> print a string %d -> print a integer %x -> print a hexadecimal %n -> WRITES MEMORY %hn -> writes 1/2 # of bytes written Dangerous Bugs – Integer issues… • Integer overflows (and underflows) – If we have unsigned short i = 32767 and I add 1 to that… whats the result? Dangerous Bugs – Integer issues… • So, you can smack an integer around… so what? – Int arrayOfIntegers[50]; – int I = userInput(); – While( i < 49){ • arrayOfIntegers[i] = array[i]; i++; } – Whats wrong with this? Dangerous Bugs – Integer issues… • So, you can smack an integer around… so what? Part Duece (that’s poker lingo for 2) – Int *arrayOfIntegers; – arrayOfIntegers=malloc(userVariable *sizeof(int)); Dangerous Bugs – Dangerous Loops • • • • Char someBuffer[10]; Int i = 0; // hacker sets X to some value greater than 9 While( i < X ) – { Memcpy(someBuffer[i], someSrc[i], 1); } Dangerous Bugs – Race Conditions • When programs fight over resources. • Process A creates a file, has a thread that puts data in it and another thread that reads it. • Process B also reads the file, if we can make process B negatively manipulate the file BETWEEN process A’s reading and writing threads then perhaps we can take advantage of it. • Usually done with semaphore’s or other shared mem. • No demo, to hard. And how were we finding vulns ? • If we were looking at a million lines of dis.asm then we’d go insane and never find anything. • Those of us in this room will rely on vulnerability releases, patches, fault injection and Fuzzers. • Vuln release: If we were looking at one function where we KNEW there was a vulnerability then its possible. • Patch: Assembly compare. • Fuzzer: throws tons of values and lengths at a program to see if it can get it to crash. If it crashes, then we look at the function that crashed. Okay, end review • Let’s talk about vectors… Okay – Lets start on Vectors – lets do something trivial first • • • • • • • • • • • • • • • #include <stdlib.h> #include <stdio.h> int badFunction(char argv[]) { int someInt; char someArray[128]; /* someArray is of small space but */ strcpy( someArray, argv); /* no limit is placed on the copy into it */ someInt = atoi(someArray); return someInt; } int main(int argc, char *argv[]) { int meaninglessVariable; meaninglessVariable = badFunction(argv[1]); printf("%d \n", meaninglessVariable); return 0; } What is the goal? • To get something of ours in EIP. – EIP is a cpu register (32 bit, not 64. Buy me a 64 bit system and I’ll be glad to explore that) – Extended Instruction Pointer – it stores the NEXT instruction to be executed. – If we can get our instructions in EIP, its running our instructions. What does the stack look like? Some Array[128] By “overflowing” this array with information we can reach the end of the stack and overwrite the return address. EBP Return Address The return address is used to return execution flow to to the Operating System. But, that’s pretty limited • Requires executable stack • Requires simple addressing (what if our call stack changed?) • Requires non-randomized addressing • Very, very inflexible • Not portable (might work on one flavor but not another) So, lets look at return-to-libc or ret2libc first. • Used to get around non-executable stacks. • Technique – Like the basic buffer overflow we are going to alter the return address. – But not to anything on the stack, instead we will return into a system function. – How about libc is the standard C library, it is linked to all C programs. – How about system() ? – System(“/bin/sh”); // ?? Diagram of ret2libc Some Array EBP RET Some Array SomeRet System() addy 4 /bin/sh EBP address system() So, how does it avoid the nonexecutable stack? • Where is the code that executes ? • What is the payload or shellcode ? Recap – further explanation • What’s the real problem here? – A program has to load .so’s or .dll’s to run prepared functions. – We can use the functions in these libraries by changing pointers to point to them. – We can get arbitrary code to run in this manner – • In our example we ran /bin/sh because its really clear and easy. • BUT, for example on a windows box, if kernel32.dll was loaded we could have createthread(). Our shellcode would be the options and process code necessary to get it to run. Ret2libc On Windows… Applies to Windows and Linux, but on Windows… Using stdcall* multiple functions can be chained together in windows ret2libc calls. At one time, could be used to disable software DEP** and run shellcode. Ponder loading libs for a moment… Thinking about activeX ? • *win api, similar to cdecl • ** software DEP probably doesn’t do what you think it does Function Pointer Overwrites • Lets start with the basics… what is a pointer ? – A pointer is a programming language data type whose value refers directly to another value stored elsewhere in the computer memory using its address. (source: wikipedia) – What does it mean to reference and dereference a pointer ? • So, What is a function pointer ? – A pointer that when dereferenced invokes a function passing it zero or more arguments just like a normal function. Guess how it works as a vector then? • If we can overflow some value or buffer and overwrite the function pointers address, then the next time the function pointer is called, control can transfer to the attackers code. • So, function pointer FP points to memory address REALFUNCTION. • Somewhere in the program we insert our shellcode into memory at memory address SHELLCODEMEM. • We overwrite the value of FP to point to the memory address SHELLCODEMEM instead. • When FP is called, it points, and SHELLCODEMEM is called. Overwriting Pointers cont. • So, think about this… – What if I overwrite a pointer to point to a pointer. • Overwrite once to point to an arbitrary location, overwrite a second time to change that location. • What does **pointer; // reference? • Or in .asm if arg+0 is a pointer… – – – – Mov edx [ebp + arg_0] Mov eax [edx] Mov edx [eax] Etc etc Wow, that’s cool. What are the pro’s and cons • Everything depends on the program… (mostly true with all vectors) • Can be either stack or heap (note: it would require executable stack or heap). • Couldn’t we also overwrite a function pointer and point it to system like a ret2libc? Yes, it’s a good workaround for non-exec stack. • Alternatively, we could point it to a table… Lets look at using linking tables next • CTOR, DTORs, GOT, PLT • Are all linking tables in ELF. • Think about how a program works when it calls a function. The function is housed in the OS libs, how does the program get to the function code? • Linking (pointing) memory addresses! • If we can overwrite those then we can run arbitrary code. ELF – PLT and GOT diagram GOT overwrites • Global Offset Table – Part of an ELF executable – Stores the absolute location of a function (which is in the OS) – Gets populated at run time by the trld • Real time linker (aka, _dl_runtime_resolve ) • Not populated in advance, literally at run time. FYI - This is known as “lazy resolution”. ELF – PLT and GOT diagram What happens if we overwrite the… ? • GOT points to… – Actual code to be run via memory addresses. • PLT points to… – GOT addresses, which are links to actual library functions. – Read only Lets walk through a demo… • I learned this from the c0ntex demo (like everyone else). • Demo is his, but if fits so nicely into ours… • BSD notes… Pointers point… • So, lets over write that pointer to point towards the GOT table with the overflow. • THEN on the next overflow we will be overwriting the GOT table itself. • Overwrite the GOT table with an address of something we’d rather run… system() comes to mind. • PWND? Other pointers we can overwrite… • DTORs – Gcc function - Destructors – Functions that execute AFTER main() exits • CTORs – Gcc function - Constructors – Functions that execute BEFORE main() starts – Ctors and dtors are always there, even when there are no functions marked as constructors or destructors. • Vtable – Table of special C++ functions called virtual method. – Table of pointer to the “functions”. – Usually done by overwriting the instance pointer. • Frame Pointer – Worth a closer look… Frame Pointers. • Used to access memory within the current frame (psst, whats a frame? The chunk of memory we are currently using) • 2 pointers used to navigate the memory stack. – Stack pointer – Is the last memory address (lowest). This is a variable and moves as the stack grows and shrinks. • ESP – extended stack pointer – usually used as the stack pointer – Frame pointer – is the first memory address (highest). This is a static and does not move. Used as a reference to move in the stack. • FP + 128 would take you to the frame pointer + 128 bytes • EBP – Extended Base Pointer – usually used as the frame pointer • WHA?!?!?!!??! – EBP is the frame pointer? Yup. Are some things starting to come together for you now? Lets back up for a second and cover frame pointers in more detail • • • • • • Push and Pop off the stack… EIP gets saved off first (this is the return addy). When you call a function, EBP is stored at the top of the stack (yea, top and bottom get confused, think highest address). Next, the stack is incremented for variables. When the function returns, the funcs EBP is restored as the stack pointer, ESP. IF I can modify EBP, then when the calling function returns it will use the bogus frame pointer. (EBP will get loaded into ESP on the return) – • Make the next frame return into our shellcode, or perhaps a function pointer. Easier to see by looking at some assembly What’s so special about frame pointers? • Partial overwrites are possible. – This gives birth to an off-by-one vulnerability. • Char string[12]; • Memset(string[12], userInput(), 1); – The code above is an off by one. – What comes after the buffer on that stack? • EBP • And as you recall, if I can overwrite EBP, then EBP gets loaded into ESP. • Now, ask yourself. If EBP was random, but I overwrote the first 2 bytes of it, where would that take me? • HINT: little endian systems only What does the stack look like? Some Array[128] By “overflowing” this array with information we can reach the end of the stack and overwrite the return address. EBP Return Address The return address is used to return execution flow to to the Operating System. So maybe I had… • A random 0x08048496 • And I overwrote that into a 0x08048400 • The stack grows down, so I wrote myself into a lower address… • If it ends up getting loaded as an EIP, where did I land? Lets look at some windows stack specifics.. • Much harder, much more complex. • SEH is the one I know okay, but it’s a bit dated. Still works on XP sometimes... • Was what all the exploits were using until recently. • Now that you understand some vectors, you’ll understand why XP2 was more secure. – Jumping AND returning into DLL’s is forbidden – so is jumping into the stack. • SEH re-opened up stack based exploits on Windows boxes, there is a lesson to be learned here. What is the SEH? • Structured Exception Handler – A smart thing windows implemented to handle exceptions. – Is a standard way for the OS to handle errors. – Uses an exception chain, passing the exception to ntdll!RtlRaiseException which then passes to – ntdll!KiUserExceptionDispatcher – The exception dispatcher then starts rolling through the registered exceptions. • LIFO, like a stack • Registered Exception handler can handle the exception or pass it to the next handler in the chain. • Exception records stored on the stack, can be either before or after return addy. How do I get a SEH record? • Its done for you by the compiler when you do a • __try/__except/__finally SEH Chains EXCEPTION_DISPOSITION ExceptionHandler( IN EXCEPTION_RECORD ExceptionRecord, IN PVOID EstablisherFrame, IN PCONTEXT ContextRecord, IN PVOID DispatcherContext); EstablisherFrame is the address of the base of the fixed stack allocation for this function. Points to the EXCEPTION_REGISTRATION_RECORD, which is the NEXT pointer (this is how it chains). So a pop/pop/ret will pop 2 addresses and then return into EstablisherFrame. Which is the NEXT pointer, showing the SEH to go to the next SEH in the chain. So, to get it to run our code we change the NEXT pointer to jump into our shellcode. Damn this is ugly, lets do a demo to clear this up. What the stack looks like when we call an exception handler? Return Addy Pointer to type of exception Address of EXCEPTION_REGISTRATION structure • Er, wait, what was EXCEPTION_REGISTRATION ? (go back 2 slides) Hhmmm… this pop-pop-ret thing is interesting… • Pop/pop/ret is an Opcode • Opcode - Small groups of assembly located *anywhere* we can reach that do something advantages to us. • Can be used with frame-pointer overwrites on Windows. • Lots of other potential applications. Where can I find the opcodes? • Metasploit opcode database of course! – Its online, a bit dated though. • Don’t forget msfpescan! – Included in your metasploit download. Can scan any PE for your pop-pop-ret op code. • What about my linux op codes? – Well, as you gathered, Linux is a bit different. – BUT, try msfelfscan. What the heck is SafeSEH ? • Microsoft’s answer to SEH overwrites (and it’s a good one). • Quietly implemented in VS 2003, works with DEP. • “Safe SEH works by producing a list of all valid exception handlers at the time the application is compiled and linked. When an exception occurs at runtime, the exception handler being used is only run if it is pre-registered “ • Only works if all the executable parts were compiled with SafeSEH turned on (its on by default now). • What’s the other thing that can go wrong with SEH? You can write an exception handler that swallows all faults. This allows for brute forcing, regardless of other security measures. Lets look at some heap before we leave… • Heap is how OS’s handle dynamic memory. • Uses internal control structures used to navigate it. • We can abuse these with an overwrite to run arbitrary code. • This is how 90% of XP SP2 and 2003 exploits work. • Most of what we see on the Linux side as well. • Lets take a closer look at how the heap works… How Heap works… • Depends on the heap allocator. We’ll mostly talk about dlmalloc by Doug Lea which is what Linux uses (glibc). • At the end of your chunk of heap memory is a piece of metadata called the malloc_chunk. Defined by this struct: struct malloc_chunk { INTERNAL_SIZE_T prev_size; // tail end is flags 4bytes INTERNAL_SIZE_T size; // 4 bytes struct malloc_chunk* fd; // 4 bytes forward ptr struct malloc_chunk* bk; // 4 bytes bckwrd ptr }; • Heap memory is stored in doubly linked list. Capitalizing on the heap structs • So, if there is an error in the code we can fill up the heap space and then overwrite – Prevsize with the appropriate flags – Size – Fd – Bk • Advanced Heap? Review… Part 1 • How does it work? – Ret2libc – Function Pointer Overwrite – GOT overwrite – Frame Pointer overwrite – Heap – SEH Which vectors defeat… • Non-executable stack ? • ASLR ? – Which work if OS libraries aren’t randomized? • Non-executable heap ? – Note: Non-exec heap would break a ton of stuff, like LISP. • Which ones can work with an off-by-one type of error? • Intel and AMD have made some strides forward in security, things like a stack aware CPU (XD and NX cpu’s). Now that you know some vulns and vectors, what else could they do? • What about GS cookies? Or Stackguard? (any canary) • SafeSEH ? Closing thought. Direct quote from McAfee: – “Entercept prevents all three major types of buffer overflow exploits: stack-based, heap-based, and returninto-libc. “