You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
[0x68] kOSSerializeString | 0x1C<br />
[0x6C] {payload buffer}<br />
[0x88] kOSSerializeString | 0x1C<br />
[0x8C] {payload buffer}<br />
[0xA8] kOSSerializeEndCollect<strong>on</strong> | kOSSerializeObject | 5<br />
While structurally <str<strong>on</strong>g>the</str<strong>on</strong>g>y look somewhat different, ultimately <str<strong>on</strong>g>the</str<strong>on</strong>g>y both exploit <str<strong>on</strong>g>the</str<strong>on</strong>g> same UAF<br />
vulnerability. The simpler payload (for <strong>iOS</strong> 9.3.2 and later) is <str<strong>on</strong>g>the</str<strong>on</strong>g> easiest to understand. When<br />
OSUnserializeBinary begins <str<strong>on</strong>g>the</str<strong>on</strong>g> parsing process to deserialize <str<strong>on</strong>g>the</str<strong>on</strong>g> payload, <str<strong>on</strong>g>the</str<strong>on</strong>g> functi<strong>on</strong><br />
will create a new dicti<strong>on</strong>ary object as a result <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> entry at <str<strong>on</strong>g>of</str<strong>on</strong>g>fset 0x04. Within this dicti<strong>on</strong>ary<br />
are two unkeyed objects. The first object is an OSString object with <str<strong>on</strong>g>the</str<strong>on</strong>g> value sy2 (specified<br />
in <str<strong>on</strong>g>of</str<strong>on</strong>g>fsets 0x08 and 0x0C, respectively). Offset 0x10 specifies an OSData object <str<strong>on</strong>g>of</str<strong>on</strong>g> 0x14 (20)<br />
bytes in size. The OSData object c<strong>on</strong>tains <str<strong>on</strong>g>the</str<strong>on</strong>g> payload buffer data structure. Since <str<strong>on</strong>g>the</str<strong>on</strong>g> objects<br />
are unkeyed, OSUnserializeBinary will replace <str<strong>on</strong>g>the</str<strong>on</strong>g> OSString object with <str<strong>on</strong>g>the</str<strong>on</strong>g> OSData<br />
object but leave <str<strong>on</strong>g>the</str<strong>on</strong>g> pointers in place in objsArray. With <str<strong>on</strong>g>the</str<strong>on</strong>g> OSString object having no<br />
retain() calls, <str<strong>on</strong>g>the</str<strong>on</strong>g> OSString is deallocated, <str<strong>on</strong>g>the</str<strong>on</strong>g>reby putting two memory arrays into <str<strong>on</strong>g>the</str<strong>on</strong>g> free<br />
list (<strong>on</strong>e for <str<strong>on</strong>g>the</str<strong>on</strong>g> OSString object itself and <strong>on</strong>e for <str<strong>on</strong>g>the</str<strong>on</strong>g> string associated with <str<strong>on</strong>g>the</str<strong>on</strong>g> OSString<br />
object).<br />
When OSUnserializeBinary parses <str<strong>on</strong>g>the</str<strong>on</strong>g> kOSSerializeData entry, a new OSData object<br />
is allocated and thus c<strong>on</strong>sumes <strong>on</strong>e <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> freed memory locati<strong>on</strong>s from <str<strong>on</strong>g>the</str<strong>on</strong>g> free list. When <str<strong>on</strong>g>the</str<strong>on</strong>g><br />
data associated with <str<strong>on</strong>g>the</str<strong>on</strong>g> kOSSerializeData entry is copied into <str<strong>on</strong>g>the</str<strong>on</strong>g> OSData object, a new<br />
buffer is allocated for <str<strong>on</strong>g>the</str<strong>on</strong>g> data, which c<strong>on</strong>sumes <str<strong>on</strong>g>the</str<strong>on</strong>g> remaining data locati<strong>on</strong> from <str<strong>on</strong>g>the</str<strong>on</strong>g> free list. At<br />
this point, <str<strong>on</strong>g>the</str<strong>on</strong>g> dangling pointer in objsArray has been replaced with an OSData object’s<br />
data. It is <str<strong>on</strong>g>the</str<strong>on</strong>g> data associated with <str<strong>on</strong>g>the</str<strong>on</strong>g> OSData object that c<strong>on</strong>tains <str<strong>on</strong>g>the</str<strong>on</strong>g> malicious payload that<br />
will ultimately give 32Stage2 write access into <str<strong>on</strong>g>the</str<strong>on</strong>g> kernel in order to install <str<strong>on</strong>g>the</str<strong>on</strong>g> read/write<br />
primitives.<br />
Regardless <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> <strong>iOS</strong> versi<strong>on</strong>, <str<strong>on</strong>g>the</str<strong>on</strong>g> malicious payload c<strong>on</strong>tains <str<strong>on</strong>g>the</str<strong>on</strong>g> same payload buffer. The<br />
payload buffer is a 20-byte structure c<strong>on</strong>sisting <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> following elements:<br />
[00] address <str<strong>on</strong>g>of</str<strong>on</strong>g> uaf_payload_buffer + 8<br />
[04] {uninitialized data from stack}<br />
[08] address <str<strong>on</strong>g>of</str<strong>on</strong>g> uaf_payload_buffer<br />
[0C] static value <str<strong>on</strong>g>of</str<strong>on</strong>g> 20<br />
[10] address <str<strong>on</strong>g>of</str<strong>on</strong>g> OSSerializer::serialize<br />
The layout <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> payload must c<strong>on</strong>tain <str<strong>on</strong>g>the</str<strong>on</strong>g> pointer to <str<strong>on</strong>g>the</str<strong>on</strong>g> new retain functi<strong>on</strong> at <str<strong>on</strong>g>of</str<strong>on</strong>g>fset 0x10.<br />
32Stage2 uses <str<strong>on</strong>g>the</str<strong>on</strong>g> OSSerializer::serialize functi<strong>on</strong> as <str<strong>on</strong>g>the</str<strong>on</strong>g> replacement retain. This<br />
layout means that <str<strong>on</strong>g>the</str<strong>on</strong>g> remainder <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> payload must now mimic <str<strong>on</strong>g>the</str<strong>on</strong>g> vtable <str<strong>on</strong>g>of</str<strong>on</strong>g> an<br />
OSSerializer object. As explained previously in Establishing Read/Write/Execute Primitives<br />
<strong>on</strong> Previously Rooted Devices, <str<strong>on</strong>g>the</str<strong>on</strong>g> OSSerializer::serialize functi<strong>on</strong> will call <str<strong>on</strong>g>the</str<strong>on</strong>g> functi<strong>on</strong><br />
at <str<strong>on</strong>g>of</str<strong>on</strong>g>fset 0x10 <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> supplied vtable while passing <str<strong>on</strong>g>of</str<strong>on</strong>g>fsets 0x08 and 0x0C <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> vtable to <str<strong>on</strong>g>the</str<strong>on</strong>g><br />
called functi<strong>on</strong>. Given that <str<strong>on</strong>g>of</str<strong>on</strong>g>fset 0x10 is set to OSSerializer::serialize, <str<strong>on</strong>g>the</str<strong>on</strong>g> functi<strong>on</strong> is<br />
Page 29