Understanding how your tweaks get enabled in Electra.
The trigger
It all started from this tweet:
If you want to enable tweaks after jailbreaking without tweaks on Electra: pic.twitter.com/eA1GqxJbGd
— Jake James (@Jakeashacks) July 18, 2018
Before some developer wraps this procedure into an useful tweak, I tried to understand what’s actually happening there. Luckily, CoolStar had just open-sourced an Electra1131 build a couple hours before Jake’s tweet. Thank you, CoolStar!
The magic line
inject_criticald 1 /electra/pspawn_payload.dylib
Its arguments are pretty simple: take a pid (in our case, pid 1 equals launchd) and inject a library into it.
Down the rabbit hole
Most subroutines are already described in previously released Ian Beer’s exploitations:
Take launchd pid -> get a task port # -> achieve tfp0.
Since we have root access (and now, tfp0), the injection can be achieved.
We proceed to find the start address of *launchd* process by using Ian Beer’s binary_load_address (it grabs the address from the second argument of mach_vm_region. Check it at triple_fetch for a deep understanding).
We’ve arrived at the first console logging line (Address is at 0000…).
Here’s the final inject_criticald procedure call:
call_remote(remoteTask, dlopen, 2, REMOTE_CSTRING(loaded_dylib), REMOTE_LITERAL(RTLD_NOW));
This procedure uses dlopen()
function to load our library into launchd. The RTLD_NOW flag makes sure all undefined symbols in the library are resolved before dlopen() returns.
Somewhere along the call_remote road, the second console logging line warns us about the success of the find_blr_x19_gadget()
function, which has to do with ROP and the inner workings of (again) Ian Beer’s triple_fetch exploit.
Our loaded_dylib (/electra/pspawn_payload.dylib, if you remember well) is successfully injected :)
Why dylibbin’?
Here’s a brief look into *pspawn_payload* bin:
There it is:
The rebindings described allow us to fake spawn Daemons (more specifically, every Daemon found at /Library/LaunchDaemons/), including our dearest /usr/libexec/cydia/startup, which activates our tweaks without (luckily!) causing panics/loops that would require a reboot.
Since we’re already at a jailbroken state, CoolStar’s *jailbreakd* Daemon is already active before these steps — and thus, it is skipped. The same goes on for *sshd* (OpenSSH).
Making tweaks appear (Windows’ “restart to apply changes”)
If we compare Jakes’ flow against CoolStar’s, we’ll see the only diff is the post injecting process to make changes apply: while Jake’s only resprings the device, CoolStar’s does a wider cleaning by using ldrestart
as described in his tweet:
Little known tip: run “ldrestart” as root to restart iOS without rebooting the kernel or exiting jailbroken state (preserves uptime)
— CoolStar (@coolstarorg) May 3, 2018
That’s all, folks. Thank you for reading this far :)
Special thanks to:
Coolstar and Electra Team for an amazing jailbreak tool
Ian Beer for amazing iOS kernel research
Jake James for provoking my curiosity
Jay Freeman for battling jailbreak legality for all these years
Apple for the most amazing mobile OS ever