Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
<str<strong>on</strong>g>Pegasus</str<strong>on</strong>g> Persistence Mechanism<br />
The persistence mechanism used by <str<strong>on</strong>g>Pegasus</str<strong>on</strong>g> to reliably execute unsigned code each time <str<strong>on</strong>g>the</str<strong>on</strong>g><br />
device boots (and, ultimately, execute <str<strong>on</strong>g>the</str<strong>on</strong>g> kernel exploit to again jailbreak <str<strong>on</strong>g>the</str<strong>on</strong>g> device) relies <strong>on</strong> a<br />
combinati<strong>on</strong> <str<strong>on</strong>g>of</str<strong>on</strong>g> two distinct issues.<br />
The first issue is <str<strong>on</strong>g>the</str<strong>on</strong>g> presence <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> rtbuddyd service within a plist (to be launched <strong>on</strong> device<br />
boot). Note that prior to <strong>iOS</strong> 10, rtbuddyd is present <strong>on</strong> some iPh<strong>on</strong>e devices for example <str<strong>on</strong>g>the</str<strong>on</strong>g><br />
iPh<strong>on</strong>e 6S, but not <strong>on</strong> o<str<strong>on</strong>g>the</str<strong>on</strong>g>rs like <str<strong>on</strong>g>the</str<strong>on</strong>g> iPh<strong>on</strong>e 6. As a result, any signed binary that can be copied<br />
into <str<strong>on</strong>g>the</str<strong>on</strong>g> specified path (/usr/libexec/rtbuddyd) will be executed at boot time with <str<strong>on</strong>g>the</str<strong>on</strong>g><br />
arguments specified in <str<strong>on</strong>g>the</str<strong>on</strong>g> plist (specifically “--early-boot”).<br />
rtbuddyProgramArgumentsrtbuddyd --<br />
early-bootPerformInRestoreRequireSuccess<br />
Program/usr/libexec/rtbuddyd<br />
As a result <str<strong>on</strong>g>of</str<strong>on</strong>g> this behavior, any signed binary <strong>on</strong> <str<strong>on</strong>g>the</str<strong>on</strong>g> system can be executed at boot with a<br />
single argument. By creating a symlink named --early-boot within <str<strong>on</strong>g>the</str<strong>on</strong>g> current working<br />
directory, an arbitrary file can be passed as <str<strong>on</strong>g>the</str<strong>on</strong>g> first argument to <str<strong>on</strong>g>the</str<strong>on</strong>g> arbitrary signed binary that<br />
has been copied to <str<strong>on</strong>g>the</str<strong>on</strong>g> rtbuddyd locati<strong>on</strong>.<br />
The sec<strong>on</strong>d issue leveraged in this persistence mechanism is a vulnerability within <str<strong>on</strong>g>the</str<strong>on</strong>g><br />
JavaScriptCore binary. <str<strong>on</strong>g>Pegasus</str<strong>on</strong>g> leverages <str<strong>on</strong>g>the</str<strong>on</strong>g> previously described behavior in order to<br />
execute <str<strong>on</strong>g>the</str<strong>on</strong>g> jsc binary (JavaScriptCore) by copying it to <str<strong>on</strong>g>the</str<strong>on</strong>g> path /usr/libexec/rtbuddyd.<br />
Arbitrary JavaScript code can <str<strong>on</strong>g>the</str<strong>on</strong>g>n be executed by creating a symlink named --early-boot<br />
that points to a file c<strong>on</strong>taining <str<strong>on</strong>g>the</str<strong>on</strong>g> code to be executed at boot time. <str<strong>on</strong>g>Pegasus</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g>n exploits a bad<br />
cast in <str<strong>on</strong>g>the</str<strong>on</strong>g> jsc binary to execute unsigned code and re-exploit <str<strong>on</strong>g>the</str<strong>on</strong>g> kernel.<br />
JavaScriptCore Memory Corrupti<strong>on</strong> Issue<br />
The issue exists within <str<strong>on</strong>g>the</str<strong>on</strong>g> setImpureGetterDelegate() JavaScript binding (which is backed by<br />
functi<strong>on</strong>SetImpureGetterDelegate).<br />
EncodedJSValue JSC_HOST_CALL functi<strong>on</strong>SetImpureGetterDelegate(ExecState* exec)<br />
{<br />
JSLockHolder lock(exec);<br />
JSValue base = exec->argument(0);<br />
if (!base.isObject())<br />
return JSValue::encode(jsUndefined());<br />
JSValue delegate = exec->argument(1);<br />
if (!delegate.isObject())<br />
return JSValue::encode(jsUndefined());<br />
ImpureGetter* impureGetter = jsCast(asObject(base.asCell()));<br />
impureGetter->setDelegate(exec->vm(), asObject(delegate.asCell()));<br />
Page 39