macOS IOKit Analysis
A skill for analyzing macOS IOKit drivers, understanding kernel extension architecture, and investigating IOKit-related vulnerabilities.
What is IOKit
IOKit is an open-source, object-oriented device-driver framework in the XNU kernel that handles dynamically loaded device drivers. It allows modular code to be added to the kernel on-the-fly, supporting diverse hardware.
Key characteristics:
- IOKit drivers export functions from the kernel with predefined, verified parameter types
- Built on top of Mach messages (similar to XPC)
- Written in C++
- User-space components are open source, but no IOKit drivers are open source
Source code locations:
- Kernel IOKit: https://github.com/apple-oss-distributions/xnu/tree/main/iokit
- User-space IOKit: https://github.com/opensource-apple/IOKitUser
Driver Locations
macOS
/System/Library/Extensions- KEXT files built into the OS/Library/Extensions- KEXT files installed by 3rd party software
iOS
/System/Library/Extensions
Core Commands
List Loaded Drivers
# Print all loaded kernel extensions
kextstat
# Search by full bundle-id
kextfind -bundle-id com.apple.iokit.IOReportFamily
# Search by substring in bundle-id
kextfind -bundle-id -substring IOR
Load/Unload Extensions
kextload com.apple.iokit.IOReportFamily
kextunload com.apple.iokit.IOReportFamily
Inspect IORegistry
# List all registry entries
ioreg -l
# Don't cut lines
ioreg -w 0
# Check specific plane
ioreg -p <plane>
Common IORegistry planes:
- IOService Plane - General service objects, provider-client relationships
- IODeviceTree Plane - Physical device connections (USB, PCI hierarchy)
- IOPower Plane - Power management relationships
- IOUSB Plane - USB device hierarchy
- IOAudio Plane - Audio device relationships
Demangling C++ Symbols
IOKit is written in C++. Use these commands to get readable symbols:
# Get demangled symbols from a driver
nm -C com.apple.driver.AppleJPEGDriver
# Demangle symbols from stdin
c++filt
Example transformation:
__ZN16IOUserClient202222dispatchExternalMethodEjP31IOExternalMethodArgumentsOpaquePK28IOExternalMethodDispatch2022mP8OSObjectPv
↓
IOUserClient2022::dispatchExternalMethod(unsigned int, IOExternalMethodArgumentsOpaque*, IOExternalMethodDispatch2022 const*, unsigned long, OSObject*, void*)
Driver Communication Pattern
User-space code connects to IOKit services using this pattern:
IOServiceMatching()- Create matching dictionary for service nameIOServiceGetMatchingServices()- Get iterator over matching servicesIOServiceOpen()- Establish connection to serviceIOConnectCallScalarMethod()- Call a function by selector number
Important: You call functions by selector number, not by name. The selector is the index in the driver's external method dispatch array.
Available Call Functions
IOConnectCallScalarMethod- For scalar argumentsIOConnectCallMethod- For buffer argumentsIOConnectCallStructMethod- For struct arguments
Reversing Driver Entrypoints
Step 1: Get Driver from Firmware
Extract KEXT files from IPSW firmware images to get drivers with symbols for debugging.
Step 2: Find dispatchExternalMethod
Load the driver into a decompiler and locate the dispatchExternalMethod function. This is the entry point that receives user-space calls.
Function signature:
IOUserClient2022::dispatchExternalMethod(
uint32_t selector,
IOExternalMethodArgumentsOpaque *arguments,
const IOExternalMethodDispatch2022 dispatchArray[],
size_t dispatchArrayCount,
OSObject * target,
void * reference
)
Step 3: Define IOExternalMethodDispatch2022 Struct
The dispatch array structure is open source: https://github.com/apple-oss-distributions/xnu/blob/main/iokit/IOKit/IOUserClient.h
Define this struct in your decompiler to properly interpret the dispatch array.
Step 4: Enumerate Exported Functions
The dispatch array contains all exported functions. Each element corresponds to a selector:
- Selector 0 → First function in array
- Selector 1 → Second function in array
- etc.
Recent IOKit Attack Surface (2023-2025)
CVE-2024-27799 (IOHIDFamily)
- Issue: Permissive
IOHIDSystemclient could grab HID events even with secure input - Fix: Ensure
externalMethodhandlers enforce entitlements, not just user-client type - Impact: Keystroke capture via sandboxed apps
CVE-2024-44197 & CVE-2025-24257 (IOGPUFamily)
- Issue: OOB writes from malformed variable-length data to GPU user clients
- Root cause: Poor bounds checking around
IOConnectCallStructMethodarguments - Impact: Memory corruption from sandboxed apps
CVE-2023-42891 (IOHIDFamily)
- Issue: HID user clients remain a sandbox-escape vector
- Recommendation: Fuzz any driver exposing keyboard/event queues
Quick Triage & Fuzzing Tips
1. Enumerate Selectors from Userland
Use the enumerate_iokit_selectors.py script to list all external methods for a service:
python3 scripts/enumerate_iokit_selectors.py --service IOHIDSystem
2. Check Sandbox Reachability
Before targeting a driver, verify if it's accessible from third-party apps:
strings /System/Library/Extensions/IOHIDFamily.kext/Contents/MacOS/IOHIDFamily | \
grep -E "^com\.apple\.(driver|private)"
3. Common Bug Patterns
- Inconsistent size fields:
structureInputSize/structureOutputSizevs. actualcopyinlength → heap OOB - Missing entitlement checks: Only checking user-client type, not entitlements
- Bounds confusion: Passing oversized arrays through
IOConnectCallMethod
4. Minimal Fuzzing Harness
For GPU/iomfb bugs, oversized arrays often trigger bounds issues:
uint8_t buf[0x1000];
size_t outSz = sizeof(buf);
IOConnectCallStructMethod(conn, X, buf, sizeof(buf), buf, &outSz);
Analysis Workflow
When investigating an IOKit driver:
- Identify the driver - Use
kextstatandkextfindto locate it - Check IORegistry - Use
ioregto understand service relationships - Extract from firmware - Get symbolicated version from IPSW
- Reverse dispatchExternalMethod - Find the entry point and dispatch array
- Enumerate selectors - List all exported functions
- Check entitlements - Verify sandbox reachability
- Look for CVE patterns - Compare against known vulnerability patterns
- Build test harness - Create user-space code to call selectors
Scripts
Use the bundled scripts for common tasks:
scripts/enumerate_iokit_selectors.py- List driver selectors from userlandscripts/list_kexts.py- Enhanced kextstat with filteringscripts/demangle_symbols.py- Batch demangle C++ symbols
References
- Apple Security Updates: https://support.apple.com/en-us/121564
- Rapid7 CVE-2024-27799: https://www.rapid7.com/db/vulnerabilities/apple-osx-iohidfamily-cve-2024-27799/
- XNU IOKit Source: https://github.com/apple-oss-distributions/xnu/tree/main/iokit
- IORegistryExplorer: https://developer.apple.com/download/all/