For Red Team members who are already familiar with Linux, there may be some confusion about using a Mac. Many people believe that macOS and Linux are very similar operating systems, and in many ways, they are. Both are built on Unix-like principles and rely on the command line interface for much of their functionality.

However, once you move beyond the bash/zsh prompt, macOS becomes a very different beast. It has layers of security and proprietary frameworks that Linux doesn’t have. It is not just “Linux with a better UI.” It is Darwin, a BSD-derivative with a Mach microkernel, wrapped in proprietary Apple frameworks.

In this guide, we will bridge the gap. We will cover the “BSD Trap” that catches Linux users, the nightmare of TCC (Transparency, Consent, and Control), and how to persist and execute code using Apple’s unique “Living off the Land” binaries.


1. The Core: Darwin and the BSD Heritage

macOS is built on Darwin, an open-source Unix-like operating system that combines the XNU kernel with a BSD-based userland. This is the first trap for Linux users: macOS is BSD-based, not GNU-based.

Command Line Differences (GNU vs. BSD)

As a red teamer, your shell scripts will break if you assume GNU behavior.

  • sed: On Linux, sed -i 's/foo/bar/g' file works. On macOS, you must provide an empty string for the backup extension: sed -i '' 's/foo/bar/g' file.
  • ps: Linux uses standard ps aux. macOS prefers BSD flags like ps -ax -o pid,user,comm.
  • netstat: Modern macOS has mostly deprecated netstat for process-to-port mapping. Use lsof -iTCP -sTCP:LISTEN -n -P instead.
  • grep: The macOS version of grep does not support -P (Perl Compatible Regex) by default. Use -E for extended regex.
  • base64: macOS uses base64 -i input -o output. Linux uses base64 input > output.

2. The Security Boundaries: TCC and SIP

On Linux, root is god. On macOS, even root is restricted. This is the single most important thing for an offensive operator to understand.

SIP (System Integrity Protection)

SIP prevents even the root user from modifying certain system directories (like /System, /bin, /sbin). It also prevents “code injection” into system processes via task_for_pid unless the binary is signed by Apple with specific entitlements.

  • Checking SIP: csrutil status.
  • Implication: You cannot simply drop a rootkit into /System/Library/Extensions. You are restricted to /Library or ~/Library or /usr/local.

TCC is the “sandbox” that prompts you for permission to access the camera, microphone, or “Full Disk Access” (FDA).

  • The Problem: Even if you have a root shell via SSH, if you try to ls ~/Documents, the command might fail (Operation not permitted) or hang while a GUI prompt appears on the user’s desktop—tipping them off immediately.
  • The Database: TCC permissions are stored in SQLite databases protected by SIP.
    • System: /Library/Application Support/com.apple.TCC/TCC.db
    • User: ~/Library/Application Support/com.apple.TCC/TCC.db
  • Red Team Strategy: Don’t attack TCC directly. Attack the apps that have TCC rights. If Terminal.app has Full Disk Access, running commands inside it inherits those rights.

3. Keychain Access: The Vault of Secrets

macOS stores passwords, certificates, and keys in the Keychain. For an offensive operator, this is the primary target for credential harvesting.

Dumping the Keychain via CLI

If you know the user’s login password (or have a keylogger), you can use the built-in security tool.

1
2
# Dump generic passwords (interactive prompt unless unlocked)
security find-generic-password -ga "TargetName"

[!WARNING] Accessing the Keychain often triggers a GUI prompt asking the user for permission to allow security to access the key. This is a OpSec risk.

The “Dump-All” Strategy

Tools like Chainbreaker can parse the .keychain-db files directly from ~/Library/Keychains/ if you can extract the master key. This usually requires root privileges to read the system keys.


4. Persistence: LaunchDaemons and LaunchAgents

While cron still exists on macOS (for now), the professional way to persist is via launchd.

  1. LaunchDaemons (/Library/LaunchDaemons): Run as root at boot. Used for system-wide persistence.
  2. LaunchAgents (~/Library/LaunchAgents): Run as the user at login. Used for user-land persistence.

Creating a Persistent Agent

Create a plist file (e.g., com.apple.update.helper.plist):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.apple.update.helper</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/bin/python3</string>
      <string>/Users/Shared/payload.py</string>
    </array>
    <key>RunAtLoad</key>
    <true />
  </dict>
</plist>

Load it:

1
launchctl load -w ~/Library/LaunchAgents/com.apple.update.helper.plist

5. Living off the Land: JXA and AppleScript

macOS has a unique automation layer called OSA (Open Scripting Architecture). You can script almost any application using AppleScript or JavaScript for Automation (JXA).

JXA (JavaScript for Automation)

JXA allows you to use JavaScript syntax to bridge into native Objective-C (“Cocoa”) APIs. This allows for powerful in-memory execution without dropping binaries.

Example: Reading a file using ObjC bridge

1
2
3
4
5
// Run via: osascript -l JavaScript payload.js
var fm = $.NSFileManager.defaultManager;
var data = fm.contentsAtPath("/etc/passwd");
var str = $.NSString.alloc.initWithDataEncoding(data, $.NSUTF8StringEncoding);
console.log(str.js);

AppleScript Phishing

You can invoke native-looking dialog boxes to steal passwords.

1
osascript -e 'display dialog "Software Update requires your password to continue:" default answer "" with icon file "System:Library:CoreServices:Software Update.app:Contents:Resources:SoftwareUpdate.icns" with hidden answer'

6. The “Quarantine” Flag: Gatekeeper

When you download a file via a browser, macOS adds the com.apple.quarantine extended attribute (xattr). This triggers Gatekeeper and Notarization checks.

If you curl or wget a binary, the flag is usually not added. However, unzipping a file via Finder might propagate the flag.

Removing the Mark of the Beast:

1
2
3
4
5
# Check attributes (@ sign in ls -la@ indicates xattrs)
ls -la@ payload

# Remove quarantine
xattr -d com.apple.quarantine payload

Always perform this step on any binary you upload before trying to execute it.


7. macOS Post-Exploitation Tools

If you find yourself on a Mac and need to escalate or pivot:

  1. Mythic (Poseidon / Apfell): A robust C2 framework with macOS-specific agents written in Go and JXA.
  2. SwiftBelt: An enumeration tool inspired by Seatbelt, written in Swift to avoid command-line logging.
  3. Basic Recon:
    • system_profiler SPSoftwareDataType: OS Version.
    • dscl . list /Users: List local users.
    • scutil --proxy: Check proxy settings.

Conclusion

macOS requires a shift in mindset. You are not fighting just file permissions; you are fighting Entitlements, TCC transparency, and a hardened kernel. To succeed, you must stop thinking like a sysadmin and start thinking like a macOS developer who knows how to bend launchd, JXA, and Apple Events to their will.

Happy hunting!


References