Thursday, April 26, 2012

a quick look into crashwrangler

Recently I had the opportunity of doing a crash analysis in OSX and decided to checkout CrashWrangler. Quoting a post from 2009,

Exploitable if:
Crash on write instruction
Crash executing invalid address
Crash calling an invalid address
Crash accessing an uninitialized or freed pointer as indicated by 
using the MallocScribble environment variable
Illegal instruction exception
Abort due to -fstack-protector, _FORTIFY_SOURCE, heap corruption 
Stack trace of crashing thread contains certain functions such as 
malloc, free, szone_error, objc_MsgSend, etc.

Not exploitable if:
Divide by zero exception
Stack grows too large due to recursion
Null dereference
Other abort
Crash on read instruction

Checking out the source I saw that it made a set of perfectly reasonable assumptions to help try and figure out if the crash was exploitable. In order to figure out where the corruption occurs it checks out functions which are not present in dylibs like libSystem.B.dylib - it looks higher in the stack. Also where the crash happens in the functions present in these dylibs is not as important as who called this function and the offset within the callee.

It also tries to determine whether a write, read or exec of an invalid address causes the crash. Checking if the eip == access_address_reported_in_crash should be the easiest way to check if its an exec crash. If its a call to a relative address recursion is detected, if you have something like call eax, you might have exploitability. If you have a cmp, test or fld you have a read, if you have a fst you have a write. If you have a jmp its an exec crash.

A crash at the "push <register>" instruction has two possibilities. It could be a read crash, while reading eax or a write crash while writing to esp - im not sure why, but it seems to interpret the second case as recursion. "inc" and "dec" on a register would never crash, so it would have to be a write to memory, write crash. It also checks if the instructions are "lods" "stos" or "mov".

Its interesting to note that some applications crash with assertion if the memory allocated is too big by writing a null byte to 0xbbadbeef - something i did not know. Checks for that seem to be present. Heap corruption is detected looking at the functions in the stack trace. Snippet from the code :-

585       "malloc", "calloc", "realloc", "CFRelease", "CFRetain", "_CFRelease", "_CFRetain","objc_msgSend",
586       "szone_free", "free_small", "tiny_free_list_add_ptr", "tiny_free_list_remove_ptr",
587       "small_free_list_add_ptr", "small_free_list_remove_ptr", "large_entries_free_no_lock",.
588       "large_free_no_lock", "szone_batch_free", "szone_destroy",
589       "CSMemNewPtr", "CSMemNewPtrClear", "CSMemNewHandle", "CSMemNewHandleClear",.
590       "CSMemPtrToHand", "CSMemPtrAndHand", "CSMemDisposeHandle",  "CSMemDisposePtr",.
591       "CSMemReallocateHandle", "free",  "szone_error", "WTF::fastFree(void*)",.
592       "WTF::fastMalloc(unsigned long)", "WTF::FastCalloc(unsigned long, unsigned long)",
593       "WTF::FastRealloc(void*, unsigned long)",.
594       "WTF::tryFastMalloc(unsigned long)", "WTF::tryFastCalloc(unsigned long, unsigned long)",.
595       "WTF::tryFastRealloc(void*, unsigned long)", "WTF::TCMalloc_Central_FreeList",.
596     ]

The backtrace is also checked for stack buffer overflows or guard check failures.

597     suspicious_funcs = [
598       "__stack_chk_fail", "append_int", "release_file_streams_for_task", "__guard_setup",
599       "_CFStringAppendFormatAndArgumentsAux",.
600     ] 

Finally at the part where exploitability is determined EXC_ARITHMETIC,  EXC_BAD_INSTRUCTION, EXC_CRASH, EXC_BREAKPOINT are ruled out. Write/Read Null dereferences are considered as ruled out. If the stack frame line contains a "libdispatch.dylib" or a "libxpc.dylib", its ruled out.

There is more to crashwrangler than what i've mentioned here, you have a "exc_handler" than does an execve on the target application and monitors the exception/crash - you could use this if the crash can be reproduced.

Looking into this makes me wonder about how "!exploitable" works - I also hear that there is something similar being developed for gdb on the linux platform.

No comments:

Post a Comment