Fast tethered booting.

Tethered booting is where an iDevice requires a connection to a computer in order to boot. Typically this is due to the device being jailbroken - The computer runs some sort of exploit on the device which allows the jailbreak to work.

How does tethered booting work

For the sake of this article, we’re assuming the exploit is in the secureROM (e.x. checkm8). Once we’ve achieved unsigned code execution in the secureROM we need to actually boot the system. As a final stage we need to boot the kernelcache installed on the root file system.

The iOS bootchain

There are two main bootchains used for iOS (there’s some overlap for OTA upgrades but that’s irrelivant here). The restore bootchain:

secureROM -> iBSS -> iBEC -> Kernel

In stock iOS this is used exclusively to boot restore ramdisks (iBECs are the only bootloaders with ramdisk loading support). The iBSS is uploaded over USB, then the iBEC is uploaded over USB and so on.

The other bootchain is the regular bootchain used for booting iOS regularly:

secureROM -> LLB -> iBoot -> Kernel

This bootchain is loaded from the NOR flash memory, unlike the restore bootchain loaded over USB.

Both of these bootchains can be used for tethered booting, as explained below.

Traditional Tethered Boot

This is the method used for a lot of tethered boots where images aren’t pre-patched.

In essence you upload the iBSS and iBEC as normal, patching the iBSS signature checks, and patching the ‘go’ command of the iBEC.

Commands in the iBEC and iBoot are setup with a structure like this:

typedef struct {
	void* command_name; // The name of the command, e.x. "go"
	void* command_handler; // The function executed when the command is called
	void* command_description; // A description, typically on RELEASE bootloaders this isn't actually populated
} iboot_command_t;

By pointing the command_handler to the load address (the address where images uploaded over USB are stored) we can take full control over execution by uploading a payload to this address. This payload proceeds to patch the iBEC, loads the kernelcache from the filesystem, patches it on the fly and then boots it.

iBooty tethered boot

This method was first used (to my knowledge) by iH8Sn0w in iBooty.

For this method, you simply restore the device with a patched iBoot and kernelcache. Then you upload a patched LLB to your device and it will load all the images automatically. This method is significantly faster than the more traditional method.

n1ghtshade tethered boot

In n1ghtshade a mixture of the two methods was required. n1ghtshade doesn’t patch any images it uploads to the device (this is by design, huge databases of firmware keys and patchers required to do this is messy and doesn’t allow for people to customise their devices as they like). So we must use the more traditional tethered boot method as this enables the patching to happen on the fly. The problem is that this method is slow and terrible, so instead we try and blend the two methods.

First, we modify our Pwned DFU payload to allow for patching of images we upload on the device, as this is much cleaner than doing it on the computer. We add some specific patches:

Because we haven’t patched the iBoot signature checks, we’ll now end up in recovery mode. However, we’ve modified our ‘go’ command handler. This means we can upload a payload, just like with the traditional method, and allow that payload to boot the system.

This method maintains the advantage of the iBooty method being much, much faster; while also permitting more flexibility as we don’t need to patch images on the fly, or enforce the use of images we have decryption keys for.