HN
Today

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.

5
Score
0
Comments
#16
Highest Rank
5h
on Front Page
First Seen
Apr 12, 3:00 PM
Last Seen
Apr 12, 7:00 PM
Rank Over Time
1916192729

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 __DATA segment using adrp/ldr pairs, 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 simple ldr/str instructions.
  • Phase 4: Iterator and Constructor Functions: Analyze *_iterate functions 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() and zone_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_ro is 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 + 0xA0 for hash entry).
  • Practical Tips: Look for function clusters for related fields, use zalloc_ro_mut for 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.