Analyzing macOS Binaries
macOS reverse engineering is Mach-O plus a specific security model: code
signing, entitlements, the sandbox, TCC privacy, and XPC between processes. The
binary tells you what the code does; the entitlements and load paths tell you
what it is allowed to do and where an attacker could get in. Read both — most
macOS findings live in the gap between the two.
When to Use
- Analyzing a
.app bundle or a Mach-O executable/dylib/framework on macOS
- Reading entitlements, hardened-runtime flags, notarization, and Gatekeeper
quarantine state
- Auditing an XPC service or privileged helper for an authorization bug
- Hunting dylib hijacking / proxying via
@rpath and weak dylibs
- Reasoning about TCC privacy exposure and sandbox escape surface
When NOT to Use
- iOS apps — IPA decryption, FairPlay (
cryptid=1), App Store binaries —
are analyzing-ios-binaries. Same Mach-O format, different toolchain and DRM.
- Non-Mach-O or cross-platform triage with no macOS specifics —
analyzing-binaries.
- Turning a memory-corruption crash into an exploit —
exploiting-memory-corruption.
- A Mach-O that is packed/encrypted before you can read it —
unpacking-protected-binaries.
Triage the Binary and Bundle
- Thin the universal binary. macOS ships fat binaries (x86_64 + arm64); use
lipo -thin (or lipo -archs to list) so your tools work on one slice.
- Read the Mach-O.
otool -l for load commands, otool -L for linked
dylibs and their paths, nm for symbols. Note the load commands that matter
later: LC_RPATH, LC_LOAD_DYLIB / LC_LOAD_WEAK_DYLIB, and the code
signature.
- Walk the bundle.
Contents/MacOS (the binary), Info.plist (identifiers,
URL schemes), _CodeSignature, embedded Frameworks/, and any bundled
XPCServices/. The bundle layout is the map of what to analyze.
Recover Objective-C and Swift
- Objective-C keeps rich runtime metadata:
class-dump (or dsdump)
reconstructs class, method, and property declarations straight from the
binary. This is the fastest way to see the app's structure.
- Swift is harder — names are mangled and metadata is less forthcoming. Run
swift-demangle over symbols to get readable names, and expect to lean on the
decompiler (Hopper, Ghidra, IDA) more than with Objective-C.
- Note which language dominates before choosing the approach; a Swift binary
where
class-dump returns little is normal, not a failure.
Code Signing, Entitlements, and Gatekeeper
This is where macOS-specific authority lives:
codesign -dvvv --entitlements :- <binary> dumps the signature and the
entitlements — the capabilities the OS grants. Entitlements like
com.apple.security.get-task-allow (debuggable), disabled library validation,
or private TCC entitlements are the high-value reads.
- Hardened runtime flags restrict code injection and debugging; note whether
they are on, and whether library validation is disabled (which allows loading
unsigned dylibs — directly relevant to hijacking).
- Notarization and Gatekeeper. Downloaded files carry the
com.apple.quarantine extended attribute; Gatekeeper checks notarization on
first run. Understand the quarantine/notarization state when reasoning about
what will execute and what a user was warned about.
The macOS-Specific Bug Surface
- Dylib hijacking / proxying. A binary that loads a dylib from an
@rpath
that resolves to a writable location, or a LC_LOAD_WEAK_DYLIB that is absent,
lets an attacker drop a malicious dylib and get code execution in the app's
context — inheriting its entitlements. Enumerate the load paths and check which
are attacker-writable and unprotected by library validation.
- XPC services and privileged helpers. XPC is the mach-based IPC between an
app and its helpers (often a
SMJobBless root helper). The classic bug is a
helper that authorizes a client by PID — which races and is spoofable —
instead of by audit_token. Trace how the service validates its caller and
what privileged action it will perform; weak validation is local privilege
escalation.
- TCC privacy. TCC gates access to camera, mic, files, and automation. Look
at what the app is entitled to and whether it can be coerced into acting as a
confused deputy for a less-privileged process, or whether an injectable
dylib inherits its TCC grants.
- URL schemes and
Info.plist handlers register the app to handle input
from other apps and the web — an untrusted-input entry point.
Dynamic Analysis
Frida attaches to macOS processes for runtime hooking; lldb debugs (subject to
get-task-allow/SIP); dtrace traces syscalls and library calls where SIP
permits. Use these to watch XPC messages and dylib loads live rather than
inferring them from the binary alone.
Rationalizations to Reject
- "It's signed and notarized, so it's safe." Signing proves origin, not
safety, and says nothing about a dylib-hijack path or an XPC helper that
trusts its caller's PID. Read the entitlements and load paths.
- "class-dump returned almost nothing, the binary is stripped." That is the
normal signature of a Swift binary. Switch to
swift-demangle and the
decompiler rather than concluding there is nothing to see.
- "The helper checks the client PID, that's authentication." PID checks race
and are spoofable. Only
audit_token-based validation is sound; a PID check is
the finding.
- "Library validation will stop a malicious dylib." Only if it is enabled.
Check for the disable-library-validation entitlement and hardened-runtime state
before assuming the load is protected.
- "This is just the iOS process on a Mac." The DRM, toolchain, and security
model differ. Use
analyzing-ios-binaries for FairPlay IPAs; this skill for
the macOS app and its XPC/TCC/dylib surface.
References
analyzing-ios-binaries — iOS IPAs, FairPlay, and mobile toolchain
analyzing-binaries — general Mach-O triage and decompilation technique
exploiting-memory-corruption — exploiting a native bug found here
unpacking-protected-binaries — when the Mach-O is packed/encrypted first
1---2name: analyzing-macos-binaries3description: Reverse engineer and security-review macOS applications and Mach-O binaries — thinning universal binaries, recovering Objective-C/Swift structure, reading code-signing entitlements and the hardened runtime, and auditing XPC services, dylib load paths, and TCC privacy exposure. Use when analyzing a .app bundle or Mach-O on macOS, checking entitlements and notarization, hunting a dylib-hijack or XPC privilege bug, or reasoning about Gatekeeper and quarantine.4---56# Analyzing macOS Binaries78macOS reverse engineering is Mach-O plus a specific security model: code9signing, entitlements, the sandbox, TCC privacy, and XPC between processes. The10binary tells you what the code does; the entitlements and load paths tell you11what it is *allowed* to do and where an attacker could get in. Read both — most12macOS findings live in the gap between the two.1314## When to Use1516- Analyzing a `.app` bundle or a Mach-O executable/dylib/framework on macOS17- Reading entitlements, hardened-runtime flags, notarization, and Gatekeeper18 quarantine state19- Auditing an XPC service or privileged helper for an authorization bug20- Hunting dylib hijacking / proxying via `@rpath` and weak dylibs21- Reasoning about TCC privacy exposure and sandbox escape surface2223## When NOT to Use2425- **iOS apps** — IPA decryption, FairPlay (`cryptid=1`), App Store binaries —26 are `analyzing-ios-binaries`. Same Mach-O format, different toolchain and DRM.27- **Non-Mach-O or cross-platform triage** with no macOS specifics —28 `analyzing-binaries`.29- **Turning a memory-corruption crash into an exploit** —30 `exploiting-memory-corruption`.31- **A Mach-O that is packed/encrypted before you can read it** —32 `unpacking-protected-binaries`.3334## Triage the Binary and Bundle3536- **Thin the universal binary.** macOS ships fat binaries (x86_64 + arm64); use37 `lipo -thin` (or `lipo -archs` to list) so your tools work on one slice.38- **Read the Mach-O.** `otool -l` for load commands, `otool -L` for linked39 dylibs and their paths, `nm` for symbols. Note the load commands that matter40 later: `LC_RPATH`, `LC_LOAD_DYLIB` / `LC_LOAD_WEAK_DYLIB`, and the code41 signature.42- **Walk the bundle.** `Contents/MacOS` (the binary), `Info.plist` (identifiers,43 URL schemes), `_CodeSignature`, embedded `Frameworks/`, and any bundled44 `XPCServices/`. The bundle layout is the map of what to analyze.4546## Recover Objective-C and Swift4748- **Objective-C** keeps rich runtime metadata: `class-dump` (or `dsdump`)49 reconstructs class, method, and property declarations straight from the50 binary. This is the fastest way to see the app's structure.51- **Swift** is harder — names are mangled and metadata is less forthcoming. Run52 `swift-demangle` over symbols to get readable names, and expect to lean on the53 decompiler (Hopper, Ghidra, IDA) more than with Objective-C.54- Note which language dominates before choosing the approach; a Swift binary55 where `class-dump` returns little is normal, not a failure.5657## Code Signing, Entitlements, and Gatekeeper5859This is where macOS-specific authority lives:6061- **`codesign -dvvv --entitlements :- <binary>`** dumps the signature and the62 **entitlements** — the capabilities the OS grants. Entitlements like63 `com.apple.security.get-task-allow` (debuggable), disabled library validation,64 or private TCC entitlements are the high-value reads.65- **Hardened runtime** flags restrict code injection and debugging; note whether66 they are on, and whether library validation is disabled (which allows loading67 unsigned dylibs — directly relevant to hijacking).68- **Notarization and Gatekeeper.** Downloaded files carry the69 `com.apple.quarantine` extended attribute; Gatekeeper checks notarization on70 first run. Understand the quarantine/notarization state when reasoning about71 what will execute and what a user was warned about.7273## The macOS-Specific Bug Surface7475- **Dylib hijacking / proxying.** A binary that loads a dylib from an `@rpath`76 that resolves to a writable location, or a `LC_LOAD_WEAK_DYLIB` that is absent,77 lets an attacker drop a malicious dylib and get code execution in the app's78 context — inheriting its entitlements. Enumerate the load paths and check which79 are attacker-writable and unprotected by library validation.80- **XPC services and privileged helpers.** XPC is the mach-based IPC between an81 app and its helpers (often a `SMJobBless` root helper). The classic bug is a82 helper that authorizes a client by **PID** — which races and is spoofable —83 instead of by **`audit_token`**. Trace how the service validates its caller and84 what privileged action it will perform; weak validation is local privilege85 escalation.86- **TCC privacy.** TCC gates access to camera, mic, files, and automation. Look87 at what the app is entitled to and whether it can be coerced into acting as a88 confused deputy for a less-privileged process, or whether an injectable89 dylib inherits its TCC grants.90- **URL schemes and `Info.plist` handlers** register the app to handle input91 from other apps and the web — an untrusted-input entry point.9293## Dynamic Analysis9495Frida attaches to macOS processes for runtime hooking; `lldb` debugs (subject to96`get-task-allow`/SIP); `dtrace` traces syscalls and library calls where SIP97permits. Use these to watch XPC messages and dylib loads live rather than98inferring them from the binary alone.99100## Rationalizations to Reject101102- **"It's signed and notarized, so it's safe."** Signing proves origin, not103 safety, and says nothing about a dylib-hijack path or an XPC helper that104 trusts its caller's PID. Read the entitlements and load paths.105- **"class-dump returned almost nothing, the binary is stripped."** That is the106 normal signature of a Swift binary. Switch to `swift-demangle` and the107 decompiler rather than concluding there is nothing to see.108- **"The helper checks the client PID, that's authentication."** PID checks race109 and are spoofable. Only `audit_token`-based validation is sound; a PID check is110 the finding.111- **"Library validation will stop a malicious dylib."** Only if it is enabled.112 Check for the disable-library-validation entitlement and hardened-runtime state113 before assuming the load is protected.114- **"This is just the iOS process on a Mac."** The DRM, toolchain, and security115 model differ. Use `analyzing-ios-binaries` for FairPlay IPAs; this skill for116 the macOS app and its XPC/TCC/dylib surface.117118## References119120- `analyzing-ios-binaries` — iOS IPAs, FairPlay, and mobile toolchain121- `analyzing-binaries` — general Mach-O triage and decompilation technique122- `exploiting-memory-corruption` — exploiting a native bug found here123- `unpacking-protected-binaries` — when the Mach-O is packed/encrypted first