SuperAPI AI Directory

re-macos

Design & creation

View repository

Updated 10-15 21:35

About this skill

macOS application reverse engineering

When to use / when not to use

  • Use: macOS native/closed-source applications (.app/.dylib/.framework), targets with signing notarization and sandboxing, Keychain/Secure Enclave hardware key scenarios
  • Use: authorization/distribution state determination—who the signer, notarization, hardened runtime, and Team ID are (distribution surface/trust surface analysis)
  • Use: trust chain issues—Dylib Hijacking, injection surface, TCC dependencies (which privacy capabilities are requested/used)
  • Do not use: iOS applications (switch to [[re-ios]]); pure Mach-O format parsing (switch to [[re-format-macho]])
  • Do not use: Linux/Windows targets (go to [[re-gdb]] / [[re-x64dbg]] respectively)
  • Do not use: when you only want to capture network traffic/file behavior (when there is no macOS-specific surface, go through the [[re-behavior]] / [[re-netcap]] generic path)
  • Note: TCC and Keychain data fall within the scope of system privacy; analyze read-only and do not export contents (red line)

Tool preparation

codesign / spctl / otool / lipo (signing and Mach-O tools, built into macOS)

  • macOS: built into the system (Xcode command line tools xcode-select --install)
  • Linux: can statically analyze Mach-O (llvm-otool,brew install llvm or the distribution's llvm package), signature parsing is limited
  • Verify: codesign --version、macOS: otool --version;Linux: llvm-otool --version

plutil / xattr (Info.plist and quarantine inspection, built into macOS)

  • Verify: plutil -help、xattr -h
  • Purpose: Info.plist key parsing (plutil -p);com.apple.quarantine extended attributes determine whether Gatekeeper blocks

Hopper / IDA / Ghidra (decompilation base)

  • For installation and verification see [[re-ida]] / [[re-ghidra]]

lldb (dynamic debugging)

  • For installation and verification see [[re-lldb]]; handle PT_DENY_ATTACH before attach (step 6)

Operation steps

Execute in order, archive each step's artifacts (path + sha256, see [[re-triage]]). Record signing/entitlements information according to the [[re-analyze/analysis-contract]] contract.

  1. Bundle structure and signature inspection:

    file Sample.app/Contents/MacOS/Sample
    codesign -dv Sample.app 2>&1 | head            # 签名者/Team ID(要求需 `-d -r-` 查看)
    spctl -a -vv Sample.app 2>&1                   # 公证状态(Gatekeeper)
    defaults read Sample.app/Contents/Info.plist   # Info.plist 关键键
    
    • Focus on: signer (Apple developer/distribution certificate), Team ID, CDHash, Hardened Runtime (runtime flag), Info.plist's CFBundleIdentifier/version/minimum system version
    • Architecture confirmation:file output/x86_64 and arm64 universal binary (lipo -archs)—determines decompilation and dynamic environment (arm64e on Apple Silicon has PAC differences, see [[gotchas]])
    • Notarization-derived check:spctl -a passing does not guarantee a local staple—xcrun stapler validate Sample.app check whether the ticket accompanies the bundle
    • Quarantine attribute inspection:xattr -l Sample.app look at com.apple.quarantine(quarantine flag + timestamp + responsible app;does not contain the source URL—source information is in Spotlight attributes, use mdls -name kMDItemWhereFroms Sample.app to check)
  2. entitlements and sandbox:

    codesign -d --entitlements :- Sample.app 2>&1 | head -30
    
    • Key key groups:com.apple.security.app-sandbox(sandbox master switch),network.client/server(network),files.user-selected.*(user-selected files),device.camera/microphone(device),application-groups(group sharing),cs.allow-dyld-environment-variables / cs.disable-library-validation(injection surface),get-task-allow(debug entitlement, should not be present in release builds)
    • The sandbox profile determines the capability boundary—when analyzing authorization logic and attack surface, look at the entitlements list first, then cross-validate with dynamic behavior
    • Anomalous signals: release build carrying get-task-allow(should only be used for development debugging) or privilege-escalation combinations (e.g., no UI but enabling device.camera)—record as suspicious items into the conclusion
  3. TCC permission database:

    # 用户级 TCC 库(授权记录)
    ls ~/Library/Application\ Support/com.apple.TCC/
    # 系统级 TCC 库
    ls /Library/Application\ Support/com.apple.TCC/
    
    • Pre-check: TCC.db itself is protected by TCC—reading it without Full Disk Access will fail with a permission error, so confirm authorization before reading
    • TCC.db (SQLite) records each App's authorization for privacy resources; analyze the target's dependency on TCC (what permissions were requested, when they were requested, failure paths)
    • Note: TCC data is system privacy data; read-only analysis only, do not export contents (red line)
  4. Keychain and Secure Enclave:

    • Keychain item types (generic password/internet password/key) and access conditions—kSecAttrAccessible isaccessibility(what state the device must be in for it to be readable: unlocked/after first unlock/this device only),not ACL; access control is kSecAttrAccessControl/SecAccessControl(biometric/passcode gate); macOS traditional ACL additionally has SecAccess/kSecAttrAccess(see [[gotchas]])
    • Secure Enclave keys: generated on-device using SecKeyCreateRandomKey(with attribute kSecAttrTokenID: kSecAttrTokenIDSecureEnclave)—SecKeyCreateWithData is import/restore from external key data; the SE private key never leaves the chip and cannot be imported, so do not treat it as an SE generation API; the private keyis non-extractable(equivalent to Android Keystore hardware backing, see [[re-android-native]] Keystore audit)
    • Analysis: which keychain items the target reads (SecItemCopyMatching call sites), whether keys are Secure Enclave bound (non-extractable → record purpose and access conditions rather than looking for bytes)
  5. dyld load chain:

    otool -L Sample.app/Contents/MacOS/Sample | head    # LC_LOAD_DYLIB 依赖
    otool -l Sample.app/Contents/MacOS/Sample | grep -A4 LC_RPATH
    
    • Dependency list and RPATH → Dylib Hijacking surface (writable directory + missing dependency combination)
    • Injection surface: DYLD_INSERT_LIBRARIES is restricted by hardened runtime—entitlements without cs.allow-dyld-environment-variables it does not take effect; under system integrity protection, injection into system paths is ineffective
    • Injection verification: environment variable + trial run in sandbox DYLD_INSERT_LIBRARIES=/path/to/hook.dylib ./Sample; if ineffective, return to the static path ([[re-ghidra]]), do not force injection
  6. Anti-debugging and protection:

    • Debugger detection:PT_DENY_ATTACH(ptrace request returns deny on attach)—first statically locate the ptrace call site ([[re-ghidra]] / [[re-ida]]), patch or bypass before attaching
    • Signature verification:SecStaticCodeCheckValidity / SecRequirementCheck call sites—typical points that trigger verification failure when signature is changed or injection occurs; locate them point by point (pitfall 1)
    • Countermeasure surface record: code signature verification, debugger detection, anti-injection (DYLD_INSERT_LIBRARIES check)—the respective call sites and trigger conditions for each of the three categories
  7. Evidence verification (wrap-up): originals of signer/Team ID/entitlements, TCC dependency points, keychain item purposes, dyld dependency list—file them per [[re-analyze/analysis-contract]]; compare dynamic conclusions against static lists (capability boundary is based on dynamic behavior, see [[decision-tree]])

Cross-domain combination

  • [[re-format-macho]]: Mach-O format foundation (LC_* parsing)
  • [[re-ios]]: iOS-side complement (jailbreak ecosystem and entitlements differences)
  • [[re-lldb]]: dynamic debugging
  • [[re-frida]]: dynamic instrumentation (macOS desktop support)
  • [[re-sandbox]] / [[re-analyze/platform-tips]]: dynamic execution isolation (signature/behavior observation performed within the sandbox)
  • [[re-analyze/analysis-contract]]: signature/entitlements information passed according to the data contract
  • [[re-patching]]: persistent handling of PT_DENY_ATTACH and signature verification points
  • Swift layer analysis (mangling/witness table) → [[re-swift]]

Common pitfalls and traps

  • Signature verification triggered at multiple points: Symptom—exits immediately when run after patching; Cause—multiple verification points at load/run/update; Countermeasure—locate point by point (step 6), handle verification points first, then proceed to logic
  • Secure Enclave keys are not extractable: Symptom—private key cannot be found in memory; Cause—hardware-backed; Countermeasure—record purpose and access conditions, do not search for bytes (see step 4)
  • TCC permissions cause missing functionality: Symptom—target functionality grayed out; Cause—TCC not authorized; Countermeasure—analyze its request logic rather than bypassing system permissions (red line)
  • Notarization checks cannot be reproduced offline: Symptom—abnormal spctl results in an offline environment; Cause—notarization requires a network query (including revocation status); Countermeasure—use codesign local signature information instead, and annotate "notarization status unverified"
  • hardened runtime restricts injection: Symptom—DYLD_INSERT_LIBRARIES has no effect; Cause—the runtime flags do not include the allow-dyld environment variable; Countermeasure—static analysis path ([[re-ghidra]]), do not hard-inject
  • quarantine interferes with execution: Symptom—crash/popup when the target is downloaded from a source; Cause—com.apple.quarantine triggers Gatekeeper checks; Countermeasure—xattr -dr com.apple.quarantine remove and retest (test environment only)
  • Nested signatures missed in handling: Symptom—runtime verification fails after patching; Cause—framework/helper/extensions each have independent signatures; re-signing only the main program is insufficient; Countermeasure—codesign --deep or re-sign layer by layer, and verify the CDHash of each layer
  • For decision branches (dynamic feasibility determination/data target grading), see [[decision-tree]]; for signature/injection/TCC boundaries and counterexamples, see [[gotchas]]; all executed within the sandbox (the highest principle of [[re-analyze/platform-tips]])