Hacking QuickTime: Exception or Exploit? Jared DeMott Quote to Remember • “Bugs are found in a variety of ways. But good exploits are created in a debugger, by someone who knows the trade well.” What am I talking about? • The scoop – Former student of mine, says the hardest part about his job (he extends and uses fuzzers) is • “identifying what my exceptions are and what causes them” • The answer – Ok, well maybe not “the” answer, but this talk is tended to introduce you to this problem set and shed some light on finding the answer • How long does it take to create an exploit anyway, once you think you’ve got a good bug? It depends … on a lot of things Heap Overflow on Vista could take 36-94 work days (or more) to determine/develop reliable exploit -- Nicolás Waisman from “Apology of 0days” “One researcher's obscure crash is another researcher's reliable exploit. What determines the difference between 'just a bug' and 'fully exploitable' is often a mix of skill, determination and sheer chance” (but once patch is out stating exploitability) “Considering the skill levels of modern public security researchers, the time frame from security update to exploit has gone down from weeks to – in some cases – hours.” -- Bas Alberts from “A Bounds Check on the Microsoft Exploitability Index” What does it depend on again? • Platform protections – /gs, aslr, dep, SEHOP, etc • Type of vulnerability – Not memory corruption • Most like web app data input like XSS or SQL injection – Memory corruption • generally read or write issue to heap or stack • Skill of researcher – Some simply know more than others – Have a stronger support team, peers, or mentors – Funding and time allocated to researcher MS uses the color by number system “We have established that an exploitability index is an indicator of likelihood and hence, not an exact science … All this represents a considerable effort, but it is an effort that has to be made if an exploitability index is to represent something meaningful. The Microsoft Exploitability Index represents a major public commitment of the security….” • As it stands, Microsoft commits to three different degrees of exploitability for the index: “1 - Consistent exploit code likely” “2 - Inconsistant exploit code likely” “3 - Functioning exploit code unlikely” Quick Disclaimer • We’ll see as we move through - not an exact science • If it were easy Microsoft would be right more than 40% – As to rather exploit code will show up or not for a particular bug • http://tech.slashdot.org/article.pl?sid=08/11/14/0617229&from=r ss • Other the other hand, getting a handle on the basics is certainly possible in a 1hr talk – Getting hands on practice is of course something different … so go and fuzz something • The hardest part of most projects is still getting started Target Background • It goes without saying that we’ll assume you have some idea of the type of exploit you’re hoping to create – Working a client side for vista will be much different than working an old server exploit for SCO Unix Most Interesting Target(s) • For Windows, client side exploitation is probably the most interesting currently – Server side stuff is hard to exploit, and less gain if you’re a spammer, adware, malware type • More heavily/knowledgably monitored as well – Plus, with client side stuff … you get the yummy land of browserhood • Stack overflows in plug-ins are nice – Example: In Vista, could leverage techniques like the .Net or Java RWX heap, to gain control of the victim if you have the plug-in attack ready – XP is even easier since strait heap spraying works Fuzzing Background • The idea with fuzzing is to monitor an application while you “run it through it’s paces” with semi-valid and ideally semiintelligent data • When the monitor (normally a debugger or the like) records an exception, you know you have a bug • But, if you’re new to the game, and just cooked up your first fuzzer, what do you make of those exceptions? 8 Main Steps for Bit Flipper Fuzzing • • • • Find/Create Fuzzer Find sample files Generate semi-invalid samples Fuzz Application – Log such that you know which file caused fault • Review Faults • AptDiff( GoodFile , Mutated file) • Change each difference back, to identify the byte that caused the fault • Verify/Debug to determine exploitability A Fuzzer in Action – Example 1 • One simple fuzzer from our book (Chpt 9) – Randomly flips a few bytes in sample – DEMO: Finds crashes in QuickTime – Here’s one such example • • • • • • • • Process: QuickTime Player [44996] Code Type: X86 (Native) Parent Process: bash [36856] Date/Time: 2008-07-22 14:09:41.453 -0400 OS Version: Mac OS X 10.5.4 (9E17) Report Version: 6 Exception Type: EXC_ARITHMETIC (SIGFPE) Exception Codes: EXC_I386_DIV (divide by zero) So is that bug Serious? • Well, all bugs are serious to the development team – But we want to know if we could turn this into and exploit and make some cash selling it • First, what was the exception code? “SIGFPE” – type ‘kill –l’ if you’re not sure of the name numbers 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGEMT 8) SIGFPE 9) SIGKILL 10) SIGBUS 11) SIGSEGV 12) SIGSYS 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGURG 17) SIGSTOP 18) SIGTSTP 19) SIGCONT 20) SIGCHLD 21) SIGTTIN 22) SIGTTOU 23) SIGIO 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGINFO 30) SIGUSR1 31) SIGUSR2 This is the part of the talk where you hate me • And that’s because security researches are constantly coming up with new ways/techniques to exploit bugs previously thought unexploitable – The classic example of this comes from: http://documents.iss.net/whitepapers/IBM_XForce_WP_final.pdf • “The vulnerability in question is an exploitable NULLpointer dereference of …” • So really, it’s tough to say “this isn’t exploitable” if an exploit cannot be developed. So then what can we say? • If we think it is exploitable… – And can prove it is; case closed • If we think it’s iffy… – Good chance could be exploitable, but we just don’t know how • But, if in your organization, it looks to be beyond a reasonable level of effort, that’s fine. Move on. • If we think it’s not… – Since there’s no known/clear way to exploit – And you don’t currently have time/budget to research totally new exploitation techniques • Normally a good idea to close the books on it and move to more fertile ground. If you can find one crash, good chance you can find two. Given that, what’s the point of this Talk? • Training – While it’s true it’s tough to positively rule a crash out, you can “triage” or weed through a bunch of exceptions quickly, so that you can focus on the ones that stand a better chance of being exploitable – This is only possible if you know about different exception types Yes, perhaps I do have AD/HD • But that’s why were here, so back to the QuickTime crash from my Mac – SIGFPE is the signal sent to computer programs that perform erroneous arithmetic operations on POSIX compliant platforms. The symbolic constant for SIGFPE is defined in the header file signal.h. Symbolic signal names are used because signal numbers can vary across platforms. • So….. is it exploitable or not? Probably not. – Why? Because the chance for memory corruption, and thus execution redirection looks minimal. See example: int main() { int x = 42/0; return 0; /* Never reached */ Why? • Ok, so, true, if QuickTime wasn’t crashing on a normal movie, but after a few bytes flipped we get the SIGFPE, how can we rule this out as exploitable condition without extensive reverse engineering? – I hear that. You really always need to reverse each exception to gain full understanding of the crash • GET TO THE ROOT CAUSE VIA REing – If the value is used to influence allocation or similar functions, it could still have a chance of being exploitable – On the other hand, no invalid memory access is Reverse, Reverse, Reverse • Manually Twiddling bits – Identify the fuzzy byte that caused the crash, and try to give a proper byte(s) • Helps with REing • File format specifications – I’ve found good docs from Apple in the past like the one describing QT movies • Dynamic analysis – gdb, olly, … • Static analysis – IDA pro What exceptions are the most interesting? • Signal 11– SIGSEGV – Always the hottest because it means we’re already dealing with a memory read/write issue • Signal 6 – SIGABRT – On Linux (glibc) Interesting since this often indicates heap issues when fuzzing • Other signals – Have to be considered less interesting and prioritized for reverse engineering as such • BUT, again could still be issues! • In fact, there could be issues that don’t show up as signals at all – oh … missed bugs… Say that again? • Yah, sorry, the worst case, and toughest exception to analyze is the one you didn’t get • It’s not just about the exceptions though – Out of bounds READS aren’t normally all that helpful for exploitation • We want a SEGV based on a write operation • Is there more advanced monitoring? Sure, you can get as fancy as it as you like – Monitoring things like memory allocations, CPU usage, and more – Occasionally used in fuzzing • But that type of stuff is more for the traditional QA expert • Exception understanding in terms of exploitation is more geared toward security testing – Building complex tools is cool and needed • But right now for soft targets like QT… no need Example 2: Malloc Failure in QT (in a .mov file) • Noticed this entry in system.log – Jan 15 14:31:19 jared-demotts-macbook-pro QuickTime Player[30572]: QuickTime Player(30572,0xa025b720) malloc: *** mmap(size=1593843712) failed (error code=12)\n*** error: can't allocate region\n*** set a breakpoint in malloc_error_break to debug • Did not cause a crash like the SIGFPE which makes this possibly less attractive Which byte(s) are the issue? • I use AptDiff – Compare original file vs. Mutated file • Change each modified byte back to original until you identify the one byte(s) that caused the issue – Should probably automate this, but I’ve found it to be easy enough by hand File formats • A container format is a computer file format that can contain various types of data, compressed by means of standardized audio/video codecs • The container file is used to identify and interleave the different data types – Simpler container formats can contain different types of audio codecs – more advanced container formats can support multiple audio and video streams, subtitles, Simple Reversing the File Format Go and get http://developer.apple.com/DOCUMENTATION/QuickTime/QTFF/qtff.pdf .mov Use sample size atoms to specify the size of each sample in the media. Sample size atoms have an atom type of 'stsz'. The sample size atom contains the sample count and a table giving the size of each sample. This allows the media data itself to be unframed. The total number of samples in the media is always indicated in the sample count. If the default size is indicated, then no table follows. STSZ Data • Size (01 00 00 01) – A 32-bit integer that specifies the number of bytes in this sample size atom. • Type (‘stsz’) – A 32-bit integer that identifies the atom type; this field must be set to 'stsz'. • Version (7a) – A 1-byte specification of the version of this sample size atom. • Flags (00 00 00) – A 3-byte space for sample size flags. Set this field to 0. • Sample size (00 00 00 00) – A 32-bit integer specifying the sample size. If all the samples are the same size, this field contains that size value. If this field is set to 0, then the samples have different sizes, and those sizes are stored in the sample size table. • Number of entries (00 00 00 00) – A 32-bit integer containing the count of entries in the sample size table. • Sample size table (01 00 00 3c) – A table containing the sample size information. The sample size table contains an entry for every sample in the media’s data stream. Each table entry contains a size field. The size field contains the size, in bytes, of the sample in question. The table is indexed by sample number—the first entry corresponds to the first sample, the second entry is for the second sample, and so on. Things that make you go hmmmm… 70707070 is the number that gets used as a bad malloc size .gdbinit file to get QT in GDB break ptrace commands 1 return continue end The BackTrace in GDB Breakpoint 2, 0x91eec4a9 in malloc_error_break () (gdb) bt #0 0x91eec4a9 in malloc_error_break () #1 0x91ee7497 in szone_error () #2 0x91e148d6 in allocate_pages () #3 0x91e150c2 in large_and_huge_malloc () #4 0x91e0c228 in szone_malloc () #5 0x91e0c018 in malloc_zone_malloc () #6 0x91e0bfac in malloc () #7 0x128b4621 in loadTheChunk () #8 0x128b8bf3 in addNewSchedule () #9 0x128b9610 in LoadAFrame () #10 0x128be76b in v2m_doWhatTheMentorTellsUs () #11 0x128c0375 in Video2MoviesTask () #12 0x9606112f in CallComponentFunctionCommon () #13 0x128af505 in Video2ComponentDispatch () #14 0x96060a95 in CallComponentDispatch () #15 0x004d1003 in MediaMoviesTask () #16 0x0042cf54 in TaskMovie_priv () #17 0x129758d1 in doIdleMovie () #18 0x12984770 in internalDoAction () #19 0x12975732 in _MCIdle () #20 0x1297097d in _MCComponentDispatch () #21 0x96060a95 in CallComponentDispatch () #22 0x00517db3 in MCIdle () #23 0x00516196 in QTOMovieObject::SendCommand () #24 0x004169ae in DispatchQTMsg () #25 0x004166d5 in QTObjectTokenPriv::SendMessageToObject () #26 0x00415ca6 in QTObjectTokenPriv::DispatchMessage () #27 0x0051601a in QTSendToObject () … Register Dump gdb) up #1 0x91ee7497 in szone_error () (gdb) #2 0x91e148d6 in allocate_pages () (gdb) #3 0x91e150c2 in large_and_huge_malloc () (gdb) #4 0x91e0c228 in szone_malloc () (gdb) #5 0x91e0c018 in malloc_zone_malloc () (gdb) #6 0x91e0bfac in malloc () (gdb) i r DEMO edx 0x91e0b1c6 1847545402 ebx 0x91e0bfd5 1847541803 esp 0xbfffd8c0 0xbfffd8c0 ebp 0xbfffd8d80xbfffd8d8 esi 0x0 0 edi 0x70707084 1886417028 eip 0x91e0bfac0x91e0bfac <malloc+55> eflags 0x246 582 cs 0x1723 ss 0x1f 31 ds 0x1f 31 es 0x1f 31 Final Guesstimate • I can twiddle the 70707070 number to get large mallocs – Tried boundaries • • • • ffffffff 00000000 7fffffff etc. – None caused crashes • Probably QT validates if the number is negative and such? • only see the malloc issue with inputs 5dxxxxxx – 7fxxxxxx – Exploitation seems unlikely since a crash was not found • GuardMalloc didn’t allow such large allocations Example 3: Non-aligned Free in QT (in a .3g2 file) • Noticed this entry in system.log – Jan 22 12:58:06 jared-demotts-macbook-pro QuickTime Player[449]: QuickTime Player(449,0xa025b720) malloc: *** error for object 0xbfffd408: Non-aligned pointer being freed\n*** set a breakpoint in malloc_error_break to debug • Also did not cause a crash – GuardMalloc didn’t like this saying • “Freeing a pointer that we didn’t allocate that was not claimed by any registered zone” esds this time esds • An MPEG-4 elementary stream descriptor atom – This extension is required for MPEG-4 video • MPEG-4 is a collection of methods defining compression of audio and visual (AV) digital data – .3g2 was the file extension • 3GP is a multimedia container format defined by the Third Generation Partnership Project (3GPP) for use on 3G mobile phones but can also be played on some 2G and 4G phones. esds header data • Size ( ca 00 00 00) – An unsigned 32-bit integer holding the size of the elementary stream descriptor atom. • Type (‘esds’) – An unsigned 32-bit field containing the four-character code 'esds' • Version (00) – An unsigned 8-bit integer set to zero. • Flags (00 00 00) – A 24-bit field reserved for flags, currently set to zero. • Elementary Stream Descriptor (rest of data in this block?) – An elementary stream descriptor for MPEG-4 video, as Elementary Stream Descriptor • Trouble finding a solid file format • ‘QLCMfmt’ and ‘Qcelp 13K’ turn up – http://www.potaroo.net/ietf/idref/draftgarudadri-qcp/ – Explains bytes from QLCMfmt on, but our issues is before that • Found this – http://red5.googlecode.com/svn/java/server/bran ches/paulg_mp4/refs/mp4-layout.txt Dug this out of that paper • 8+ bytes vers. 2 ES Descriptor box = long unsigned offset + long ASCII text string 'esds‘ • if encoded to ISO/IEC 14496-10 AVC standards then optionally use: = long unsigned offset + long ASCII text string 'm4ds‘ 4 bytes version/flags = 8-bit hex version + 24-bit hex flag (current = 0) … -> 1 byte decoder specific descriptor type tag = 8-bit hex value 0x05 (ours was Back Trace (gdb) bt #0 0x9710a4a9 in malloc_error_break () #1 0x97105497 in szone_error () #2 0x9702f523 in szone_free () #3 0x9702f38d in free () #4 0x901ab755 in CSMemDisposePtr () #5 0x901ab716 in CSMemDisposeHandle () #6 0x901ab6c1 in DisposeHandle () #7 0x95c8319e in QCelpUtilsMapMP4AudioEntryToSoundDescription () #8 0x95c7ac0c in threegpp2moov_ProcessSampleDescriptionsAtom () #9 0x95c785cf in threegpp2moov_ProcessAtomContainer () #10 0x95c789d9 in threegpp2moov_ProcessGenericAtomList () #11 0x95c78e1c in threegpp2moov_ProcessSampleTableAtom () #12 0x95c785cf in threegpp2moov_ProcessAtomContainer () #13 0x95c789d9 in threegpp2moov_ProcessGenericAtomList () #14 0x95c78d8d in threegpp2moov_ProcessMediaInfoAtom () #15 0x95c785cf in threegpp2moov_ProcessAtomContainer () #16 0x95c789d9 in threegpp2moov_ProcessGenericAtomList () #17 0x95c78bdc in threegpp2moov_ProcessMediaAtom () #18 0x95c785cf in threegpp2moov_ProcessAtomContainer () #19 0x95c789d9 in threegpp2moov_ProcessGenericAtomList () #20 0x95c78afa in threegpp2moov_ProcessTrackAtom () #21 0x95c785cf in threegpp2moov_ProcessAtomContainer () #22 0x95c789d9 in threegpp2moov_ProcessGenericAtomList () Tried to free Null Pointer 0x9702f381 <free+94>: mov %esi,(%esp) 0x9702f384 <free+97>: mov %eax,0x4(%esp) 0x9702f388 <free+101>: call 0xa0a9d547 <dyld_stub_malloc_zone_free> 0x9702f38d <free+106>: add $0x2c,%esp (gdb) i r eax 0x0 0 Example 4: Crash from a .mov • Exception Type: EXC_BAD_ACCESS (SIGSEGV) • Exception Codes: KERN_INVALID_ADDRESS at 0x00000000003da000 • Thread 0 Crashed: DEMO • 0 ...ickTimeComponents.component 0x927188cb marker_detect + 273 • 1 ...ickTimeComponents.component 0x92721702 jpegpredecompress + 280 • 2 ...ickTimeComponents.component This part of the file format is simpler get Meaning for Movie Data Atom Type “mdat” JPEG Start Of Image marker FF D8 Motion-JPEG APP1 marker FF E0 Marker Content Length 00 10 (Other markers, for example JFIF ) “JFIF” Hrm… • So why would changing the “JPEG Start Of Image marker” from FF D8 FF F2 cause a crash? • Pretty sure it’s a heap issue since guard malloc catches it, but otherwise goes unnoticed • If you’ve ever put QuickTimeComponents into IDA … it’s well, it’s huge! • But anyway it obviously has to do with – jpegpredecompress marker_detect Marker_Detect at a Glance Used static and dynamic REing • Using gdb, back up to a point above where the bad memory access occurs – Trace forward to the error and see what happens along the way – Interesting, we build a number out of the current (heap) memory pointer to the mdat record + 2 bytes • • • • ptr -> ff f2 ff e0 newptr = ptr + ff e0 mov [newptr] -> esi cmp [esi], ff – The crash happens when newptr points to invalid Ideas toward popular heap exploitation techniques • Clobber function pointer on Heap with overwrite • Get that function called – Other Notes: » File is 16k long, cannot write negative, so pointer would have to be after file on heap ~50k range » The big problem here is that the pointer we create doesn’t seem to be used to write to anything • The pointer we supply is searched for the byte 0xff Final Guesstimate 0:000> !load winext\msec.dll 0:000> !exploitable Exploitability Classification: UNKNOWN Recommended Bug Title: Read Access Violation starting at QuickTime!JPEG_DComponentDispatch+0x7573 (Hash=0x14012070.0x1849147b) • UPDATE: Fixed Example 5: From a .mpg • Exception Type: EXC_BAD_ACCESS (SIGSEGV) • Exception Codes: KERN_INVALID_ADDRESS at 0x000000007520741e • Thread 10 Crashed: – 0 ...ple.QuickTimeMPEG.component 0x00660147 ParseMpaLayer2IntensityStereo + 1921 – 1 ...ple.QuickTimeMPEG.component 0x0065b352 SetupThenDoMpaFrameDecode + 452 – 2 ...ple.QuickTimeMPEG.component 0x006587c0 AudioThreadEntry + 1751 – 3 ...ple.QuickTimeMPEG.component 0x0063313a MacThreadFunc + 136 – 4 libSystem.B.dylib 0x9085d095 _pthread_start + 321 Darn, no 4 byte string tags nearby Tried some values other than ‘6A’: AA, FF, 00, & 80. But only ‘6A’ crashed. From another file that caused a crash I see ’78’ also works. It’s not immediately obvious to me what’s special about 6A and 78. Another diff Repeating pattern: I see ‘FF FD 42 40 88 55 6D’ a lot in the file. What is it? • • • • • • gdb (gdb) i r eax 0x714a70e8 ecx 0x13 edx 0x295110ebx 0x45f9d7 esp 0xb06203b0 ebp 0xb0620e78 esi 0x0 0edi 0x28 eip 0x460147 <ParseMpaLayer2IntensityStereo+1921> (gdb) disass $eip-40 $eip+40 Dump of assembler code from 0x46011f to 0x46016f: add %eax,(%eax) <ParseMpaLayer2IntensityStereo+1883>: add %bh,0x20(%ecx) <ParseMpaLayer2IntensityStereo+1889>: sub %esi,%ecx <ParseMpaLayer2IntensityStereo+1891>: mov -0x948(%ebp),%edx <ParseMpaLayer2IntensityStereo+1897>: shr %cl,%edx <ParseMpaLayer2IntensityStereo+1899>: mov %esi,%ecx <ParseMpaLayer2IntensityStereo+1901>: shll %cl,-0x948(%ebp) Read Issue <ParseMpaLayer2IntensityStereo+1907>: lea (%edx,%edx,1),%eax <ParseMpaLayer2IntensityStereo+1910>: add %edx,%eax <ParseMpaLayer2IntensityStereo+1912>: mov -0x928(%ebp),%edx <ParseMpaLayer2IntensityStereo+1918>: lea (%edx,%eax,4),%eax <ParseMpaLayer2IntensityStereo+1921>: movss (%eax),%xmm2 <ParseMpaLayer2IntensityStereo+1925>: movss 0x4(%eax),%xmm1 <ParseMpaLayer2IntensityStereo+1930>: movss 0x8(%eax),%xmm0 <ParseMpaLayer2IntensityStereo+1935>: mulss %xmm3,%xmm2 <ParseMpaLayer2IntensityStereo+1939>: mov -0xa50(%ebp),%edx <ParseMpaLayer2IntensityStereo+1945>: movss %xmm2,-0x4(%edx,%edi,1) <ParseMpaLayer2IntensityStereo+1951>: mulss %xmm3,%xmm1 Is it just me or are these bugs a pain? • Non trivial to track down • In this case, we don’t see a direct correlation between input value and resultant problem – Clear that a bad pointer is being constructed – Backing up in current thread doesn’t reveal where this value comes from • Must come from thread that started this thread Phun with Threads • Thread 0: • 0 libSystem.B.dylib 0x9082c20e semaphore_wait_signal_trap + 10 • 1 libSystem.B.dylib 0x9085e206 _pthread_cond_wait + 1267 • 2 libSystem.B.dylib 0x908a3539 pthread_cond_wait + 48 • 3 ...ple.QuickTimeMPEG.component 0x00632e51 QTYieldToThread + 470 • 4 ...ple.QuickTimeMPEG.component 0x006437bb MPEGSystemIdle + 635 • 5 ...ple.QuickTimeMPEG.component 0x00645257 MPEGSystemDispatcher + 733 • 6 ...ple.CoreServices.CarbonCore 0x95027a95 CallComponentDispatch + 29 Hrm, couldn’t find value there Repeating pattern • Interestingly, if you scramble that byte in an earlier same-pattern, in the file it crashes but quicker – Conversely, if one of the later patterns is scrambled it’s well in the movie before it crashes – Thus, I’m lead to believe this pattern is a repeated section header of some type, obviously in the “ParseMpaLayer2IntensityStereo” – Where can I get more info?? My New Favoritest Tool: 010 Another Bad (crashed with) Good Kibbles and bits! • 01 1. C h a n n e l M o d e M o d e E x t e n s i o n 1 0 C o p y r i g h t O r i g i n a l .. E m p h a s i s So: 68, 69, 6a, 6b 78, 79, 7a, 7b Yes. Others 7C …Yes. Probably just bits 5 and 6. Yes. So: 6x or 7x will cause crash. e.g. ChannelMode 1 ModeExtension 2|3 Conclusions from IDA pro • Did some more reversing and two things lead me to want to let this one go – The exception happens on a “read” not a “write” operation • I don’t see where a write happens soon after either – We can’t directly/easily control the address at which we read – But more reversing is Example 6: .avi • 0 ??? 0x15512a4c 0 + 357640780 • 1 com.apple.CoreFoundation 0x90c58768 _CFRelease + 216 • 2 com.apple.CoreFoundation 0x90bef530 __CFAllocatorDeallocate + 48 • 3 com.apple.CoreFoundation 0x90c58aea _CFRelease + 1114 • 4 com.apple.CoreFoundation 0x90c1d436 __CFDataDeallocate + 118 • 5 com.apple.CoreFoundation 0x90c58768 _CFRelease + 216 • 6 com.apple.AppKit 0x966f73e0 [NSBitmapImageRep _freeData] + 250 • 7 com.apple.AppKit 0x966f72b1 [NSBitmapImageRep _freeImage] + 39 Unrepeatable • This happen once before as well actually • Try as I might I was unable to repeat the crash – Even by using GuardMalloc – And by replaying the whole sequence again – The issue didn’t show back up … hrm…. • Oh well, not really sure what to make of that, could have been some other unrelated system issues that made it crash?? Example 7: A different .mov file • Exception Type: EXC_BAD_ACCESS (SIGSEGV) • Exception Codes: KERN_INVALID_ADDRESS at Always here 0x00000000e276cc60 – Thread 8 Crashed: – 0 ...ickTimeComponents.component 0x92ced553 Decompress_c::DecodeChromaDC(int*) + 39 – 1 ...ickTimeComponents.component 0x92ced7b4 Decompress_c::DecodeChromaBlock(long, int, int) + 38 – 2 ...ickTimeComponents.component 0x92cfb22d Decompress_c::DecodeInterFrame(int, int*) + 2311 – 3 ...ickTimeComponents.component 0x92cf0eb1 Decompress_c::DecompressFrame(unsigned char*, int, FrameBuffer_c*, DecompressParams_t*) + 1091 Hrm, again no obvious ‘text’ nearby Other bytes like 00, 11, 80, and FF caused the exception as well And bummer, there’s no .mov template freely available for 010 I suppose I’ll need to figure out what that byte represents. We could get “arbitrary” value into eax If we control contents in eax or ebx Strange to see NOPs in eax Odd, and in my file as well gdb) i r eax 0x90909090 ecx 0x19a9cb48 edx 0x9f5600 ebx 0x92ced53a esp 0xb04cb900 ebp 0xb04cb948 esi 0x9f5600 edi 0x1c727fff eip 0x92ced553 Interesting, looks like exec addr, since similar to EIP Has Potential • No write, but we do control a pointer that gets constructed • If it writes to that pointer later we could be in business • So, well, go ahead you have homework now – Not fixed – “0day” crash Example 8: .avi file • Breakpoint 1, 0x900e8c50 in ptrace ()QuickTime Player(39147,0xa004b720) malloc: *** mmap(size=1778397184) failed (error code=12)*** error: can't allocate region*** set a breakpoint in malloc_error_break to debug Blah, doesn’t look good • • • • • • • • • • • • • • (gdb) bt #0 0x9018f4a9 in malloc_error_break () #1 0x9018a497 in szone_error () #2 0x900b78d6 in allocate_pages () #3 0x900b80c2 in large_and_huge_malloc () #4 0x900af228 in szone_malloc () #5 0x900af018 in malloc_zone_malloc () #6 0x900aefac in malloc () #7 0x91aec76e in v2m_allocateFakeCodecMemory () #8 0x91af0494 in loadTheChunk () #9 0x91af4bf3 in addNewSchedule () #10 0x91af5610 in LoadAFrame () #11 0x91afa76b in v2m_doWhatTheMentorTellsUs () #12 0x91afc375 in Video2MoviesTask () Example 9: 3rd .mov Thread 8 Crashed: 0 QuickTimeH264.scalar 1 QuickTimeH264.scalar 2 QuickTimeH264.scalar 3 QuickTimeH264.scalar 4 QuickTimeH264.scalar 5 libSystem.B.dylib 6 libSystem.B.dylib 0x1562212e JVTCompEncodeFrame + 2662083 0x156e967b JVTLibDecoDispose + 131805 0x156a618c JVTCompEncodeFrame + 3202849 0x156a40db JVTCompEncodeFrame + 3194480 0x15671565 JVTCompEncodeFrame + 2986746 0x9085d095 _pthread_start + 321 0x9085cf52 thread_start + 34 Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_PROTECTION_FAILURE at address: 0x00000044 [Switching to process 12516 thread 0x9b03] 0x1564312e in JVTCompEncodeFrame () Classic Null Ptr Exception (gdb) bt #0 0x1564312e in JVTCompEncodeFrame () #1 0x1570a67b in JVTLibDecoDispose () #2 0x156c718c in JVTCompEncodeFrame () #3 0x156c50db in JVTCompEncodeFrame () (gdb) disass $eip-40 $eip+16 0x1564312e <JVTCompEncodeFrame+2662083>: (gdb) i r edx 0x0 0 mov 0x44(%edx),%edi Example 10: Mac Hackers Handbook • Charlie is a big tease. He let on that if I could land the bug from his soon to be out book at the time, I could get my own pwn2own prize – Couldn’t resist a quick look, but of course the CanSec/ZDI folks ruled that this bug couldn’t win • Lame since there was no exploit out for it – The note in the book isn’t even close to a working sploit • Also, during my look at this bug I noticed another related bug in similar area The JPEG 2000 (.jp2) file Used as a short len Example10: Mac Hacker Book An exploitable • Verify with gmalloc that it dies at Yah! write bug!! – mov – mov ecx, [ebp+var_B0] [ecx+0Eh], edx ; dies here – inside JP2DecoPreflight – Pg 133 of their book shows how use gmalloc • In GDB: – set env DYLD_INSERT_LIBRARY=/usr/lib/libgmalloc.dylib – set env MALLOC_ALLOW_READS = 1 What’s happening? • byte swapping, endieness? • runs off the end of the buffer in X cases • heap fung shui – spray ptrs on heap – free every other one toward the end – get our buff allocated in one of those holes – clobber a func ptr – trigger the ptr with member func before clean up – but … the devil’s always in the details • FIXED NOW The related bug If size greater then filesize, read beyond error Conclusion • I hope you now have a better appreciation for how the bug sploit process could work • As was shown, the process is non-exact and non-trivial for a host of reasons – but write crashes are the key! • Next generation of fuzzers should include analysis such as provided by the !exploitable plug-in for windbg • Keep on fuzzing – It should be part of most every software development project