Reverse Engineering iOS 18 Inactivity Reboot

Dec 20
Security Before First Unlock / After First Unlock
Did you know that entering your passcode for the first time after your phone starts is something very different then entering it later on to unlock your phone?

When initially entering your passcode, this unlocks a key store in the Secure Enclave Processor (SEP) that encrypts your data on an iPhone.

The state before entering your passcode for the first time is also called Before First Unlock (BFU). Due to the encrypted user data, your iPhone behaves slightly differently to later unlocks. You'll see that Face ID and Touch ID won't work and that the passcode is required. But there's more subtle things you might notice: Since Wi-Fi passwords are encrypted, your iPhone won't connect to Wi-Fi networks. If your SIM is not PIN-protected, your iPhone will still connect to cellular networks. 
That means, technically, you can still receive phone calls. Yet, if you receive a call, even if that number is in your contacts, the contact name won't be shown, as the contacts haven't been decrypted yet. Similarly, when you receive notifications about new messages, you'll see that you got messages, but you won't see any message previews. You can easily try this yourself!

In the After First Unlock (AFU) state, user data is decrypted. You can imagine this like a key safe that is kept open while iOS is running. Even when you see a lock screen, certain keys remain available to the operating system. This way, you stay connected to Wi-Fi networks and receive message notification previews, even when your iPhone is locked.

While it's more convenient, the AFU state is more susceptible to attacks. An attacker who can somehow bypass the lock screen can get access to decrypted data on the iPhone. To bypass the lock screen, an attacker does not necessarily need to know the passcode. Security vulnerabilities within iOS can allow attackers to get code execution and extract from an iPhone, even while it appears to be "locked".

Attackers with physical access to an iPhone have more security vulnerabilities to choose from. The attack surface is larger, as such attackers can exploit vulnerabilities in the USB stack or within wireless protocols, such as Wi-Fi, Bluetooth, or cellular, or even more invasive hardware attacks that involve opening the device. This larger attack surface tends to make exploits for these vulnerabilities cheaper on the gray market, as there's potentially more supply. Another factor that makes attacks cheaper is time – vulnerabilities that are publicly known by the vendor and patched in more recent software versions won't unlock new iPhones, but can unlock iPhones that were kept in AFU state for a long time that didn't get any software updates.

Rumors about Rebooting iPhones
In law enforcement scenarios, a lot of the forensically relevant data is available in the AFU state. Law enforcement takes advantage of this and often keeps seized iPhones powered on, but isolated from the Internet, until they can extract data. This time might be necessary to wait for an exploit to be available or for legal reasons, such as getting a warrant.

However, thieves and other criminals are also interested in getting this kind of access after stealing a device. It gives them access to bank accounts and other valuable information, by far exceeding what the iPhone itself would be worth, or which might be used for blackmail. People reuse their passwords often, and getting access to the iCloud account may allow a thief to reset activation lock for the device, increasing the resale value.

A recent news article by 404 media (while paywalled, the most important information is also contained in the related Tweet) reported on a law enforcement document about suspicious iPhone reboots. This document makes two interesting claims:

iPhones on iOS 18 will reboot, even when completely isolated from wireless networks.
iPhones on iOS 18 will tell other iPhones on lower iOS versions to reboot – wirelessly!
Especially the second claim would be huge if true. If anyone figured out how this works, they could build a large TV-Be-Gone for iPhones, forcing reboots over the air on hundreds of iPhones simultaneously. Would Apple really build such a feature into an iPhone?

Knowing a thing or two about the Apple wireless ecosystem, my interest was piqued, and I had to go down the rabbit hole!

Discovery of Inactivity Reboot
When Apple adds new features, they usually don't hide this very well. Apple software contains a lot of debug strings, which hint at new functionality. Blacktop maintains a git repository of strings found in iOS, which keeps a nice version history. I decided to do the most low-effort thing I could think of: just search for "reboot".
Bingo, that third hit looks good: "inactivity_reboot". The fact that it's in keybagd is interesting: this daemon is related to the key store that is unlocked on the first unlock.

A second search for only inactivity reboot shows the string starts occurring in iOS 18.1 and iOS 18.2. In iOS 18.2, the string changed from "inactivity_reboot" to "inactivity_reboot_enabled", hinting towards more potential changes in the latest iOS 18.2 betas.
Something that was still unclear to me at that point is: How long does it take for inactivity reboot to be triggered? A new article by 404 media claimed that it was 3-4 days. So I updated my SRD to the latest beta and made a time lapse.

Turns out, the inactivity reboot triggers exactly after 3 days (72 hours). The iPhone would do so despite being connected to Wi-Fi. This confirms my suspicion that this feature had nothing to do with wireless connectivity.

Reverse Engineering Inactivity Reboot
Let's reverse engineer what's changed! Which security guarantees does it provide?

Here is a high-level overview of what I found:
The Secure Enclave Processor (SEP) keeps track on when your phone was last unlocked. If that last unlock time exceeds 3 days, the SEP tells the AppleSEPKeyStore kernel module that the time was exceeded.

The AppleSEPKeyStore kernel module informs user space to initiate a reboot. SpringBoard will then gracefully terminate all user-space processes. This prevents potential data loss upon reboot.

If the AppleSEPKeyStore kernel module finds the iPhone to still be powered on after it should have rebooted, the kernel will panic. This case should never happen, unless someone tries to tamper with inactivity reboot.

The AppleSEPKeyStore kernel module writes an NVRAM variable aks-inactivity. After the iPhone rebooted, keybagd reads this variable and, if set, sends an analytics event to Apple including how long the iPhone was not unlocked.

The remainder of this post shows how I figured this out and what security implications the underlying design has.

Indicators in Sysdiagnose
From my search in ipsw-diffs, I knew there were some log messages that are printed on reboot. At the same time as I started looking them statically, I knew I had to see them actually logged for myself.

After my phone rebooted after three days, I took a sysdiagnose and searched for these messages. When doing this yourself, make sure that you unlocked the device before making the sysdiagnose. Otherwise, events from before the reboot will be missing.

In the AppleSEPKeyStore messages, there are the following entries around the inactivity reboot:
default 2024-11-17 01:35:14.341697 +0100 kernel "AppleSEPKeyStore":3846:0: notifying user space of inactivity reboot
default 2024-11-17 01:35:14.341766 +0100 kernel "AppleSEPKeyStore":12598:31: operation failed (sel: 35 ret: e00002f0)
default 2024-11-17 01:35:14.342053 +0100 kernel "AppleSEPKeyStore":12598:31: operation failed (sel: 35 ret: e00002f0)
default 2024-11-17 01:35:34.958218
[reboot occurs]
+0100 kernel "AppleSEPKeyStore":331:0: starting (BUILT: Oct 26 2024 08:16:35) ("normal" variant 🌽 , 1827.60.43)
default 2024-11-17 01:35:34.958381 +0100 kernel "AppleSEPKeyStore":476:0: _sep_enabled = 1

For more context, these are the unfiltered log messages before the reboot is initiated:
Reverse Engineering the SEPKeyStore Kernel Extension
The latest iOS kernel can be downloaded using the following ipsw command:

ipsw download appledb --device iPhone17,3 --os iOS --version '18.2 beta 2' --kernel

This will download and decompress the kernel. For further analysis, I loaded the whole kernel cache into Binary Ninja. ipsw also supports splitting the kernel into its modules (called "extensions" on iOS). The latest version of Ghidra also has decent support for the iOS kernel. So there's a lot of tools to choose from for this analysis.

I also downloaded an older kernel where Apple accidentally included symbols and manually diffed these versions with a focus on the code related to inactivity reboot. The kernel has three strings relating to the feature: