Compute iOS XNU offset from kernel cache
This blog post meticulously details an eight-phase methodology for reverse engineering iOS XNU kernelcaches to extract struct offsets, a critical step for kernel exploitation. It outlines how to navigate stripped binaries using a combination of XNU source, accessor functions, syscall implementations, and pointer chain analysis. Such deep technical dives into low-level systems and security are consistently popular on Hacker News, offering insights into Apple's closed ecosystem.
The Lowdown
The author describes a practical approach to extract crucial struct offsets from stripped iOS XNU kernelcaches. This is essential for kernel exploration and exploitation, especially after gaining kernel read/write primitives. The methodology was validated against iOS 16.7.12 and emphasizes working directly from ARM assembly rather than relying on the Kernel Development Kit.
- The Challenge: Kernelcaches extracted from IPSW files lack symbols, making it difficult to understand internal data structure layouts.
- Core Principle: Key functions like
proc_pid()act as wrappers, directly revealing field offsets when decompiled. Stripped kernelcaches still retain names of exported functions. - Phase 1: XNU Source Cross-Referencing: Use partially open XNU source as a "map" to predict struct fields, but verify against the binary as layouts can differ.
- Phase 2: Finding Anchor Points: Locate global variables (e.g.,
allproc,nprocs) in the__DATAsegment usingadrp/ldrpairs, which serve as entry points into kernel data structures. - Phase 3: Accessor Functions: Identify and decompile functions named
<struct>_<field>(e.g.,_proc_pid) to directly find field offsets and sizes from simpleldr/strinstructions. - Phase 4: Iterator and Constructor Functions: Analyze
*_iteratefunctions to find list head pointers, list entry offsets, and associated count variables, and*create*functions to trace sequential field initialization. - Phase 5: Syscall Implementations: For fields without direct accessors, examine syscall implementations (e.g.,
sys_chdir) to observe how they read/write kernel structs, revealing offsets and whether sub-structs are inline or pointers. - Phase 6: Zone ID Validation: Use
zone_require()andzone_id_require_ro()calls to determine which memory zones structs reside in and if they are read-only, informing about security architecture (e.g.,proc_rois read-only zone #5). - Phase 7: Following Pointer Chains: Combine offsets from different functions to construct multi-hop paths between objects that lack direct links, demonstrating how work is cumulative (e.g., socket to owning process).
- Phase 8: Hash Tables: Analyze lookup functions (e.g.,
_proc_find) to recover hash table structures, hash functions, and verify field offsets (e.g.,proc + 0xA0for hash entry). - Practical Tips: Look for function clusters for related fields, use
zalloc_ro_mutfor struct sizes, and interpret ARM64 instructions (ldr x,ldr w, etc.) for precise field size and offset determination.
This detailed methodology provides a comprehensive guide for security researchers and low-level developers to meticulously reverse engineer iOS kernel structures, proving that even without traditional debugging tools, a systematic approach can yield deep insights into the kernel's internal organization.