macOS userland mitigations
TL;DR: Hardened Runtime, Library Validation, dyld_shared_cache, ASLR, NX, stack canaries, and PAC on ARM64e — each blocks a classic exploit primitive; you bypass them by stealing pointers, finding signed-but-vulnerable gadgets, or pivoting to scripting engines whose JIT regions are exempt.
What it is
Recent macOS userland binaries ship with a stack of mitigations Apple has layered on over the last decade. The relevant set for an exploit developer:
- ASLR + NX — baseline.
/usr/bin/otool -hvshowsMH_PIE | MH_ALLOW_STACK_EXECUTION_FLIPflags. - Hardened Runtime — codesign flag; disables
dyldenv vars (DYLD_INSERT_LIBRARIES), forbids unsigned executable pages, requires entitlements fortask_for_pidand JIT. - Library Validation — only libraries signed by Apple or the same TeamID can be loaded; blocks attacker-supplied dylibs unless an
com.apple.security.cs.disable-library-validationentitlement is present. - dyld_shared_cache (DSC) — most system frameworks live in one giant pre-linked cache. ASLR slides the entire DSC as a unit.
- PAC (Pointer Authentication) on Apple Silicon (ARM64e) — function pointers, return addresses, Obj-C
isa, vtable slots are signed with a per-process key. - Stack canaries (
-fstack-protector-strong), PIE,__DATA_CONST(read-only after dyld fixups), CFI on some Apple binaries.
Preconditions / where it applies
- Userland process on macOS 12+ on Apple Silicon (most aggressive set) or x86_64 (no PAC, otherwise similar).
- You have an initial primitive (info leak + write) and want to reach RCE.
Technique
Defeating Hardened Runtime + Library Validation.
- If the target has the
com.apple.security.cs.disable-library-validationorcs.allow-dyld-environment-variablesentitlement (electron apps, dev tools, Adobe), DYLD_INSERT_LIBRARIES is back on the table. Scan withcodesign -d --entitlements - /Applications/Target.app/Contents/MacOS/Target. - Otherwise pivot via Mach-O side loading: drop a dylib with the same name as a weakly-linked one and rely on dyld’s search order.
Defeating DSC randomisation.
- One leak of any DSC-resident pointer reveals the slide for every library —
_dyld_get_shared_cache_range()returns base+size for the calling process. Use ROP gadgets from the whole cache once you have it. - Extract gadgets with
dyld-shared-cache-extractororipsw dyld extract; see dyld-shared-cache-extraction.
Defeating PAC on ARM64e.
- Sign primitives that exist in the codebase (signing oracles): any function that takes user-controlled pointer and calls
ptrauth_sign_*on it gives you a forged signed pointer. - Cross-context: PAC keys differ per-context (
IA/IB/DA/DB); a leaked B-key pointer doesn’t help with A-key authentications. - Stripping:
ptrauth_stripexists but is gated; in practice you target unsigned pointers (rawvoid*casts in C code) and signed wrappers. - See pac-arm64e-bypass for primitives and the public WebKit / kernel research.
JIT regions and scripting engines.
- WebKit / V8 / SquirrelFish JITs map RWX regions (W^X is enforced via PROT toggles via
pthread_jit_write_protect_np). A confused-deputy bug that flips the protection while attacker code is in the buffer is the classic JIT escape. - Hardened Runtime allows JIT only with
com.apple.security.cs.allow-jitentitlement.
Stack canary + PIE.
- Same defeats as Linux: leak the canary via formatted-output, then overflow precisely.
__stack_chk_guardresolves through__DATA_CONST.
Detection and defence
- For defenders: keep Hardened Runtime + Library Validation enabled; never request
disable-library-validationunless absolutely required. - Monitor
codesign --verify --deep --strictregressions in CI. - Endpoint Security framework (
es_event_exec_t,ES_EVENT_TYPE_NOTIFY_MMAP) catches DYLD injection attempts and unsigned-page mappings. - Treat any entitlement that re-enables old behaviour as a privilege boundary worth auditing.
References
- Apple — Hardened Runtime — official entitlement list
- Pointer Authentication on ARMv8.3 — Qualcomm whitepaper, original PAC design
- macOS and iOS Internals, Volume I — Jonathan Levin; chapters on Mach-O loading and dyld
- Project Zero — Examining Pointer Authentication on iPhone XS — canonical PAC analysis