19.11.2016 Views

Technical Analysis of the Pegasus Exploits on iOS

eNQc3Ry

eNQc3Ry

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

variables <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> JSGenericTypedArrayView can be read or corrupted. Specifically, <str<strong>on</strong>g>the</str<strong>on</strong>g> exploit<br />

writes to an <str<strong>on</strong>g>of</str<strong>on</strong>g>fset into <str<strong>on</strong>g>the</str<strong>on</strong>g> stale JSArray that overlaps with <str<strong>on</strong>g>the</str<strong>on</strong>g> length <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g><br />

JSGenericTypedArrayView, effectively setting <str<strong>on</strong>g>the</str<strong>on</strong>g> length <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> Uint32Array to 0xFFFFFFFF.<br />

Corrupting this value will allow <str<strong>on</strong>g>the</str<strong>on</strong>g> array to be treated as a view <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> entire virtual address<br />

space <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> WebC<strong>on</strong>tent process (an arbitrary read/write primitive).<br />

The exploit still must determine which <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> 4.25 milli<strong>on</strong> Uint32Arrays that were allocated aligns<br />

with <str<strong>on</strong>g>the</str<strong>on</strong>g> stale object. This can be determined by iterating through each <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> arrays and<br />

checking whe<str<strong>on</strong>g>the</str<strong>on</strong>g>r <str<strong>on</strong>g>the</str<strong>on</strong>g> length has changed to 0xFFFFFFFF. All o<str<strong>on</strong>g>the</str<strong>on</strong>g>r arrays will still have <str<strong>on</strong>g>the</str<strong>on</strong>g><br />

original backing ArrayBuffer (or a length <str<strong>on</strong>g>of</str<strong>on</strong>g> 80 / 4).<br />

for (x = attempts.length - 1; x >= 1; x--) {<br />

if (attempts[x].length != 80 / 4) {<br />

if (attempts[x].length == 0xFFFFFFFF) {<br />

memory_view = attempts[x];<br />

...<br />

break;<br />

Leaking an object address<br />

The final comp<strong>on</strong>ent needed to complete <str<strong>on</strong>g>the</str<strong>on</strong>g> exploit is <str<strong>on</strong>g>the</str<strong>on</strong>g> ability to leak <str<strong>on</strong>g>the</str<strong>on</strong>g> address <str<strong>on</strong>g>of</str<strong>on</strong>g> an<br />

arbitrary JavaScript object. The <str<strong>on</strong>g>Pegasus</str<strong>on</strong>g> exploit accomplishes this using <str<strong>on</strong>g>the</str<strong>on</strong>g> same mechanism<br />

that was used to corrupt <str<strong>on</strong>g>the</str<strong>on</strong>g> length <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> Uint32Array used for <str<strong>on</strong>g>the</str<strong>on</strong>g> read/write primitive. By<br />

writing to an <str<strong>on</strong>g>of</str<strong>on</strong>g>fset into <str<strong>on</strong>g>the</str<strong>on</strong>g> stale object, <str<strong>on</strong>g>the</str<strong>on</strong>g> buffer <str<strong>on</strong>g>of</str<strong>on</strong>g> a Uint32Array is corrupted to point to a<br />

user-c<strong>on</strong>trolled JSArray. By setting <str<strong>on</strong>g>the</str<strong>on</strong>g> first element <str<strong>on</strong>g>of</str<strong>on</strong>g> that JSArray to <str<strong>on</strong>g>the</str<strong>on</strong>g> JavaScript object to<br />

be leaked (by corrupting <str<strong>on</strong>g>the</str<strong>on</strong>g> pointer to <str<strong>on</strong>g>the</str<strong>on</strong>g> underlying storage <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> Uint32Array), <str<strong>on</strong>g>the</str<strong>on</strong>g> object’s<br />

address can be read back out <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> Uint32Array.<br />

Native code executi<strong>on</strong><br />

All that is left to do for <str<strong>on</strong>g>the</str<strong>on</strong>g> first stage <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> <str<strong>on</strong>g>Pegasus</str<strong>on</strong>g> exploit is to create an executable mapping<br />

that will c<strong>on</strong>tain <str<strong>on</strong>g>the</str<strong>on</strong>g> shellcode to be executed. To accomplish this purpose, a JSFuncti<strong>on</strong> object<br />

is created (c<strong>on</strong>taining hundreds <str<strong>on</strong>g>of</str<strong>on</strong>g> empty try/catch blocks that will later be overwritten). To help<br />

ensure that <str<strong>on</strong>g>the</str<strong>on</strong>g> JavaScript will be compiled into native code by <str<strong>on</strong>g>the</str<strong>on</strong>g> JIT, <str<strong>on</strong>g>the</str<strong>on</strong>g> functi<strong>on</strong> is<br />

subsequently called repeatedly. This behavior ensures that <str<strong>on</strong>g>the</str<strong>on</strong>g> JIT compiled (JITed) versi<strong>on</strong> <str<strong>on</strong>g>of</str<strong>on</strong>g><br />

<str<strong>on</strong>g>the</str<strong>on</strong>g> functi<strong>on</strong> (which will later be overwritten) will be marked as high priority code that is likely to<br />

be called regularly and should <str<strong>on</strong>g>the</str<strong>on</strong>g>refore not be released. Because <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> way that <str<strong>on</strong>g>the</str<strong>on</strong>g><br />

JavaScriptCore engine handles JITed code, this will reside in an area <str<strong>on</strong>g>of</str<strong>on</strong>g> memory that is mapped<br />

as read/write/execute.<br />

var body = ''<br />

for (var k = 0; k < 0x600; k++) {<br />

body += 'try {} catch(e) {};';<br />

}<br />

var to_overwrite = new Functi<strong>on</strong>('a', body);<br />

for (var i = 0; i < 0x10000; i++) {<br />

Page 9

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!