macOS is a BSD-derived Unix (so ps, launchd, /etc, POSIX permissions all apply) wrapped in Apple frameworks that add code signing, consent prompts and a read-only system volume.
/System Apple only. Sealed, read-only (SSV) since Big Sur. /Library system-wide config, agents, daemons, extensions ~/Library per-user equivalent — persistence hides here /Applications app bundles (.app = a directory, not a file) /usr/local, /opt Homebrew and third-party CLI tools /private/var/log legacy text logs (mostly superseded) /tmp, /var/folders staging areas for droppers
An app bundle is a folder: Foo.app/Contents/MacOS/Foo is the executable, Info.plist the metadata. Malware frequently ships as a bundle with a document icon.
Property lists (plists) are the config format — XML or binary. Read them with plutil -p file.plist, since binary plists look like noise in a text editor.
| Layer | Question it answers | Bypassed by |
|---|---|---|
| Gatekeeper | Is this downloaded app signed and notarised? | User right-click-open; stripped quarantine attribute; stolen dev cert |
| XProtect / XProtect Remediator | Does this match known malware? | Novel samples; it is signature-based AV, updated out of band |
| SIP | May even root modify system files? | Only by disabling from Recovery — a strong tamper signal |
| TCC | May this app access mic, camera, Documents, Full Disk? | Social-engineered consent; TCC database attacks (mostly patched) |
Quarantine attribute — anything downloaded by a browser or mail client gets the extended attribute com.apple.quarantine. That flag is what triggers Gatekeeper and notarisation checks. Check it with xattr -l file; malware often removes it, and that removal is itself detectable.
/Library/LaunchDaemons runs as root at boot, no user needed /Library/LaunchAgents runs as any user at login ~/Library/LaunchAgents runs for that user — no admin rights required! /System/Library/Launch* Apple only, SIP-protected
A malicious agent is a small plist with Label, ProgramArguments, and RunAtLoad or StartInterval. Because ~/Library/LaunchAgents is user-writable, commodity macOS malware needs no privilege escalation to persist.
# enumerate
launchctl list
ls -la ~/Library/LaunchAgents /Library/Launch{Agents,Daemons}
plutil -p ~/Library/LaunchAgents/com.suspicious.updater.plist
sfltool dumpbtm, and the Background Task Management database).profiles list; a rogue profile can install certificates or lock settings.~/.zshrc, ~/.zprofile for anything that starts a terminal.Apple replaced text syslog with the unified log — a compressed, structured, memory-and-disk store queried with the log command. Much of it is ephemeral and private-redacted, which surprises people expecting Windows-style durable event logs.
log show --last 1h --predicate 'process == "sudo"' log stream --predicate 'eventMessage CONTAINS "quarantine"' log show --last 24h --predicate 'subsystem == "com.apple.TCC"'
Endpoint Security (ES) framework is the sanctioned API that EDR agents — SentinelOne included — use to subscribe to process exec, file, and mount events in kernel-adjacent user space, replacing the old kernel extensions. Consequences: agents need explicit MDM approval (a PPPC profile granting Full Disk Access and system extension permission), and if that profile is missing the agent installs but sees almost nothing.
curl | bash line into Terminal.osascript -e 'display dialog "macOS needs your password"'.curl, osascript, launchctl, defaults, xattr -d, base64, python3.# high-signal command lines to detect osascript -e 'display dialog ... with hidden answer' fake password prompt xattr -d com.apple.quarantine /path/app Gatekeeper evasion curl -fsSL http... | bash remote script exec security find-generic-password -w keychain access csrutil disable SIP tampering
EDR shows osascript invoked with display dialog containing "System Preferences requires your password", followed by security find-generic-password. What is happening?