vectors-part3of4 - Hacking In HindSight

advertisement
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. “
Download