You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
structure and <str<strong>on</strong>g>the</str<strong>on</strong>g> kernel address space. This value is <str<strong>on</strong>g>the</str<strong>on</strong>g>n stored in a global variable for use by<br />
functi<strong>on</strong>s that must access kernel memory for <str<strong>on</strong>g>the</str<strong>on</strong>g> purposes <str<strong>on</strong>g>of</str<strong>on</strong>g> code executi<strong>on</strong>.<br />
Whenever 32Stage2 wants to execute code within <str<strong>on</strong>g>the</str<strong>on</strong>g> kernel, <str<strong>on</strong>g>the</str<strong>on</strong>g> following data structure is<br />
written to <str<strong>on</strong>g>the</str<strong>on</strong>g> write pipe <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> generated pipe set:<br />
[00] argument 1<br />
[04] argument 2<br />
[08] address <str<strong>on</strong>g>of</str<strong>on</strong>g> code to execute<br />
In order to call <str<strong>on</strong>g>the</str<strong>on</strong>g> functi<strong>on</strong> specified in <str<strong>on</strong>g>of</str<strong>on</strong>g>fset 8 <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> data structure, ano<str<strong>on</strong>g>the</str<strong>on</strong>g>r DWORD is<br />
prepended to <str<strong>on</strong>g>the</str<strong>on</strong>g> structure and passed to <str<strong>on</strong>g>the</str<strong>on</strong>g> real-time clock’s getattr handler (accessed via<br />
OSSerializer::serialize), which places argument 1 into R3 and argument 2 into R1<br />
before calling <str<strong>on</strong>g>the</str<strong>on</strong>g> address specified for <str<strong>on</strong>g>the</str<strong>on</strong>g> functi<strong>on</strong> to execute. By prepending <str<strong>on</strong>g>the</str<strong>on</strong>g> unused<br />
DWORD to <str<strong>on</strong>g>the</str<strong>on</strong>g> data structure, <str<strong>on</strong>g>the</str<strong>on</strong>g> data structure becomes <str<strong>on</strong>g>the</str<strong>on</strong>g> vtable replacement for<br />
OSSerializer. This technique is used in two different functi<strong>on</strong>s within 32Stage2. One functi<strong>on</strong><br />
allows arbitrary kernel functi<strong>on</strong> calls and <str<strong>on</strong>g>the</str<strong>on</strong>g> o<str<strong>on</strong>g>the</str<strong>on</strong>g>r is used to write DWORD values into <str<strong>on</strong>g>the</str<strong>on</strong>g><br />
kernel address space.<br />
Patching <str<strong>on</strong>g>the</str<strong>on</strong>g> Kernel to Allow Kernel Port Access<br />
With <str<strong>on</strong>g>the</str<strong>on</strong>g> ability to read, write, and execute arbitrary locati<strong>on</strong>s within <str<strong>on</strong>g>the</str<strong>on</strong>g> kernel address space,<br />
<str<strong>on</strong>g>the</str<strong>on</strong>g> next step involves gaining more direct access to <str<strong>on</strong>g>the</str<strong>on</strong>g> kernel through <str<strong>on</strong>g>the</str<strong>on</strong>g> kernel port. The<br />
functi<strong>on</strong> task_for_pid will return an error if called with <str<strong>on</strong>g>the</str<strong>on</strong>g> PID value <str<strong>on</strong>g>of</str<strong>on</strong>g> 0. In order to bypass<br />
this protecti<strong>on</strong>, Stage 2 modifies four different locati<strong>on</strong>s within <str<strong>on</strong>g>the</str<strong>on</strong>g> task_for_pid functi<strong>on</strong>.<br />
Before <str<strong>on</strong>g>the</str<strong>on</strong>g> patching <str<strong>on</strong>g>of</str<strong>on</strong>g> task_for_pid begins, Stage 2 determines if <str<strong>on</strong>g>the</str<strong>on</strong>g> area requiring <str<strong>on</strong>g>the</str<strong>on</strong>g><br />
patch is within a regi<strong>on</strong> <str<strong>on</strong>g>of</str<strong>on</strong>g> memory that is read/execute. If <str<strong>on</strong>g>the</str<strong>on</strong>g> memory is n<strong>on</strong>-writable, Stage 2<br />
will directly modify <str<strong>on</strong>g>the</str<strong>on</strong>g> permissi<strong>on</strong>s <str<strong>on</strong>g>of</str<strong>on</strong>g> <str<strong>on</strong>g>the</str<strong>on</strong>g> memory regi<strong>on</strong> to allow for write access and <str<strong>on</strong>g>the</str<strong>on</strong>g>n<br />
invalidate <str<strong>on</strong>g>the</str<strong>on</strong>g> dcache and flush <str<strong>on</strong>g>the</str<strong>on</strong>g> data and instructi<strong>on</strong> TLBs in order to ensure that <str<strong>on</strong>g>the</str<strong>on</strong>g><br />
memory regi<strong>on</strong> is updated with <str<strong>on</strong>g>the</str<strong>on</strong>g> new permissi<strong>on</strong>s.<br />
After patching <str<strong>on</strong>g>the</str<strong>on</strong>g> task_for_pid functi<strong>on</strong> to allow <str<strong>on</strong>g>the</str<strong>on</strong>g> caller to gain a port to <str<strong>on</strong>g>the</str<strong>on</strong>g> kernel, Stage<br />
2 will attempt to get a kernel port by calling task_for_pid(mach_task_self, 0, &port)<br />
up to five times with a 100 mllisec<strong>on</strong>d delay between each attempt before calling <str<strong>on</strong>g>the</str<strong>on</strong>g> assert<br />
callback and exiting.<br />
Page 31