macOS Kernel Extensions & Debugging - HackTricks

# macOS Kernel Extensions & Debugging

> [!TIP] Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
> Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

> Support HackTricks
> - Check the subscription plans!
> - Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
> - Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.

## Basic Information

Kernel extensions (Kexts) are packages with a `.kext` extension that are loaded directly into the macOS kernel space, providing additional functionality to the main operating system.

### Requirements

Obviously, this is so powerful that it is complicated to load a kernel extension. These are the requirements that a kernel extension must meet to be loaded:

- When entering recovery mode, kernel extensions must be allowed to be loaded:

- The kernel extension must be signed with a kernel code signing certificate, which can only be granted by Apple. Who will review in detail the company and the reasons why it is needed.
- The kernel extension must also be notarized, Apple will be able to check it for malware.
- Then, the root user is the one who can load the kernel extension and the files inside the package must belong to root.
- During the upload process, the package must be prepared in a protected non-root location: `/Library/StagedExtensions` (requires the `com.apple.rootless.storage.KernelExtensionManagement` grant).
- Finally, when attempting to load it, the user will receive a confirmation request and, if accepted, the computer must be restarted to load it.

### Loading process

In Catalina it was like this: It is interesting to note that the verification process occurs in userland. However, only applications with the `com.apple.private.security.kext-management` grant can request the kernel to load an extension: `kextcache`, `kextload`, `kextutil`, `kextd`, `syspolicyd`

1. `kextutil` cli starts the verification process for loading an extension
   - It will talk to `kextd` by sending using a Mach service.
2. `kextd` will check several things, such as the signature
   - It will talk to `syspolicyd` to check if the extension can be loaded.
3. `syspolicyd` will prompt the user if the extension has not been previously loaded.
   - `syspolicyd` will report the result to `kextd`
4. `kextd` will finally be able to tell the kernel to load the extension

If `kextd` is not available, `kextutil` can perform the same checks.

### Enumeration (loaded kexts)

    # Get loaded kernel extensions
    kextstat

    # Get dependencies of the kext number 22
    kextstat | grep " 22 " | cut -c2-5,50- | cut -d '(' -f1

## Kernelcache

> [!CAUTION] Even though the kernel extensions are expected to be in `/System/Library/Extensions/`, if you go to this folder you won't find any binary. This is because of the kernelcache and in order to reverse one `.kext` you need to find a way to obtain it.

The kernelcache is a pre-compiled and pre-linked version of the XNU kernel, along with essential device drivers and kernel extensions. It's stored in a compressed format and gets decompressed into memory during the boot-up process. The kernelcache facilitates a faster boot time by having a ready-to-run version of the kernel and crucial drivers available, reducing the time and resources that would otherwise be spent on dynamically loading and linking these components at boot time.

### Local Kerlnelcache

In iOS it's located in `/System/Library/Caches/com.apple.kernelcaches/kernelcache` in macOS you can find it with: `find / -name "kernelcache" 2>/dev/null`
In my case in macOS I found it in:

- `/System/Volumes/Preboot/1BAEB4B5-180B-4C46-BD53-51152B7D92DA/boot/DAD35E7BC0CDA79634C20BD1BD80678DFB510B2AAD3D25C1228BB34BCD0A711529D3D571C93E29E1D0C1264750FA043F/System/Library/Caches/com.apple.kernelcaches/kernelcache`

#### IMG4

The IMG4 file format is a container format used by Apple in its iOS and macOS devices for securely storing and verifying firmware components (like kernelcache). The IMG4 format includes a header and several tags which encapsulate different pieces of data including the actual payload (like a kernel or bootloader), a signature, and a set of manifest properties. The format supports cryptographic verification, allowing the device to confirm the authenticity and integrity of the firmware component before executing it.

It's usually composed of the following components:

- Payload (IM4P):
  - Often compressed (LZFSE4, LZSS, …)
  - Optionally encrypted
- Manifest (IM4M):
  - Contains Signature
  - Additional Key/Value dictionary
- Restore Info (IM4R):
  - Also known as APNonce
  - Prevents replaying of some updates
  - OPTIONAL: Usually this isn't found

Decompress the Kernelcache:

    # img4tool (https://github.com/tihmstar/img4tool
    img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e

    # pyimg4 (https://github.com/m1stadev/PyIMG4)
    pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e

### Download

- KernelDebugKit Github

In https://github.com/dortania/KdkSupportPkg/releases it's possible to find all the kernel debug kits. You can download it, mount it, open it with Suspicious Package tool, access the `.kext` folder and extract it.

Check it for symbols with:

    nm -a ~/Downloads/Sandbox.kext/Contents/MacOS/Sandbox | wc -l

- theapplewiki.com, ipsw.me, theiphonewiki.com

Sometime Apple releases kernelcache with symbols. You can download some firmwares with symbols by following links on those pages. The firmwares will contain the kernelcache among other files.

To extract the files start by changing the extension from `.ipsw` to `.zip` and unzip it.

After extracting the firmware you will get a file like: `kernelcache.release.iphone14`. It's in IMG4 format, you can extract the interesting info with:

pyimg4:

    pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e

img4tool:

    img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e

### Inspecting kernelcache

Check if the kernelcache has symbols with

    nm -a kernelcache.release.iphone14.e | wc -l

With this we can now extract all the extensions or the one you are interested in:

    # List all extensions
    kextex -l kernelcache.release.iphone14.e
    ## Extract com.apple.security.sandbox
    kextex -e com.apple.security.sandbox kernelcache.release.iphone14.e

    # Extract all
    kextex_all kernelcache.release.iphone14.e

    # Check the extension for symbols
    nm -a binaries/com.apple.security.sandbox | wc -l

## Debugging

## Referencias

- https://www.makeuseof.com/how-to-enable-third-party-kernel-extensions-apple-silicon-mac/
- https://www.youtube.com/watch?v=hGKOskSiaQo

> [!TIP] Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
> Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

> Support HackTricks
> - Check the subscription plans!
> - Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
> - Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.