macOS Persistence & Auto-Start Locations
This skill provides comprehensive guidance on macOS persistence mechanisms and auto-start locations for security testing and analysis.
⚠️ IMPORTANT: Only use these techniques on systems you own or have explicit authorization to test. Unauthorized access is illegal.
Quick Reference
| Category | Location | Trigger | Root Required |
|---|---|---|---|
| LaunchAgents | ~/Library/LaunchAgents/ |
User login | No |
| LaunchDaemons | /Library/LaunchDaemons/ |
System boot | Yes |
| Shell Startup | ~/.zshrc, ~/.bashrc |
Terminal open | No |
| Login Items | ~/Library/Application Support/com.apple.backgroundtaskmanagementagent |
User login | No |
| Cron | /usr/lib/cron/tabs/ |
Scheduled | Yes (or crontab access) |
1. Launchd Persistence
User LaunchAgents
Location: ~/Library/LaunchAgents/
Trigger: User login
Permissions: User-owned (no root required)
Example plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.example.persistence</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>-c</string>
<string>touch /tmp/persistence_test</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<dict>
<key>SuccessfulExit</key>
<false/>
</dict>
</dict>
</plist>
Commands:
# List all launch agents
cat ~/Library/LaunchAgents/*.plist
# Load a plist
launchctl load ~/Library/LaunchAgents/com.example.plist
# Unload a plist
launchctl unload ~/Library/LaunchAgents/com.example.plist
# List running agents
cat ~/Library/LaunchAgents/*.plist | grep -A5 "Label"
System LaunchDaemons
Location: /Library/LaunchDaemons/
Trigger: System boot
Permissions: Root required
Commands:
# List all launch daemons
sudo ls -la /Library/LaunchDaemons/
# Load a daemon
sudo launchctl load /Library/LaunchDaemons/com.example.plist
# Check loaded daemons
sudo launchctl list | grep -i daemon
PreLoginAgents
Location: /Library/LaunchAgents/ (with PreLoginAgent key)
Trigger: Before user login (for assistive technology)
Note: Requires specific configuration in the plist
2. Shell Startup Files
Zsh (Default on macOS)
Locations:
~/.zshrc- Interactive shell~/.zprofile- Login shell~/.zshenv- All zsh instances~/.zlogin- Login shell (after .zprofile)/etc/zshrc- System-wide (root required)
Trigger: Terminal opens with zsh
Example:
# Add to .zshrc
echo 'touch /tmp/zshrc_test' >> ~/.zshrc
# Verify
cat ~/.zshrc | tail -5
Bash
Locations:
~/.bashrc- Interactive shell~/.bash_profile- Login shell~/.profile- Fallback login shell/etc/bashrc- System-wide (root required)
Trigger: Terminal opens with bash
3. Login Items
Location: ~/Library/Application Support/com.apple.backgroundtaskmanagementagent
Trigger: User login
Commands:
# List login items
osascript -e 'tell application "System Events" to get the name of every login item'
# Add login item
osascript -e 'tell application "System Events" to make login item at end with properties {path:"/path/to/app.app", hidden:false}'
# Remove login item
osascript -e 'tell application "System Events" to delete login item "itemname"'
4. Terminal Preferences
Location: ~/Library/Preferences/com.apple.Terminal.plist
Trigger: Terminal app opens
Commands:
# Set startup command
/usr/libexec/PlistBuddy -c "Set :\"Window Settings\":\"Basic\":\"CommandString\" 'touch /tmp/terminal_test'" $HOME/Library/Preferences/com.apple.Terminal.plist
# Remove startup command
/usr/libexec/PlistBuddy -c "Set :\"Window Settings\":\"Basic\":\"CommandString\" ''" $HOME/Library/Preferences/com.apple.Terminal.plist
5. iTerm2 Persistence
Location: ~/Library/Application Support/iTerm2/Scripts/AutoLaunch/
Trigger: iTerm2 opens
Example:
# Create auto-launch script
mkdir -p "$HOME/Library/Application Support/iTerm2/Scripts/AutoLaunch"
cat > "$HOME/Library/Application Support/iTerm2/Scripts/AutoLaunch/persistence.sh" << 'EOF'
#!/bin/bash
touch /tmp/iterm2_persistence
EOF
chmod +x "$HOME/Library/Application Support/iTerm2/Scripts/AutoLaunch/persistence.sh"
# Or use preferences
/usr/libexec/PlistBuddy -c "Set :\"New Bookmarks\":0:\"Initial Text\" 'touch /tmp/iterm_prefs'" $HOME/Library/Preferences/com.googlecode.iterm2.plist
6. Cron Jobs
Locations:
/usr/lib/cron/tabs/- User cron jobs (root to view)/etc/periodic/- Periodic scripts~/.crontab- User crontab
Trigger: Scheduled time
Commands:
# List user cron jobs
crontab -l
# Add cron job
echo '* * * * * /bin/bash -c "touch /tmp/cron_test"' | crontab -
# List periodic scripts
ls -la /etc/periodic/daily/
# Run periodic scripts manually
sudo periodic daily
7. SSH RC Files
Locations:
~/.ssh/rc- User SSH RC/etc/ssh/sshrc- System SSH RC (root required)
Trigger: SSH login
Example:
# Create SSH RC
cat > ~/.ssh/rc << 'EOF'
#!/bin/bash
touch /tmp/ssh_rc_test
EOF
chmod +x ~/.ssh/rc
8. Folder Actions
Location: ~/Library/Scripts/Folder Action Scripts/
Trigger: Folder accessed in Finder
Example:
# Create folder action script
cat > /tmp/folder_action.js << 'EOF'
var app = Application.currentApplication();
app.includeStandardAdditions = true;
app.doShellScript("touch /tmp/folder_action_test");
EOF
# Compile script
osacompile -l JavaScript -o /tmp/folder_action.scpt /tmp/folder_action.js
# Move to folder actions directory
mkdir -p "$HOME/Library/Scripts/Folder Action Scripts"
mv /tmp/folder_action.scpt "$HOME/Library/Scripts/Folder Action Scripts/"
9. QuickLook Plugins
Locations:
~/Library/QuickLook//Library/QuickLook/(root required)/System/Library/QuickLook/(root required)
Trigger: File preview (space bar in Finder)
Note: Requires compiled plugin bundle
10. Audio Plugins
Locations:
~/Library/Audio/Plug-ins/Components//Library/Audio/Plug-ins/Components/(root required)/Library/Audio/Plug-Ins/HAL/(root required)
Trigger: Audio service restart
11. Screen Savers
Locations:
~/Library/Screen Savers//Library/Screen Savers/(root required)/System/Library/Screen Savers/(root required)
Trigger: Screen saver activated
12. Spotlight Importers
Locations:
~/Library/Spotlight//Library/Spotlight/(root required)/System/Library/Spotlight/(root required)
Trigger: File with supported extension created
Commands:
# List loaded importers
mdimport -L
# Check specific importer
plutil -p /Library/Spotlight/iBooksAuthor.mdimporter/Contents/Info.plist
13. Authorization Plugins
Location: /Library/Security/SecurityAgentPlugins/
Trigger: User authentication
Permissions: Root required + authorization database configuration
Note: Complex setup, can lock out users if misconfigured
14. PAM Modules
Location: /etc/pam.d/
Trigger: Authentication events
Permissions: Root required
Example (for testing only):
# Check PAM configuration
sudo cat /etc/pam.d/sudo
15. Periodic Scripts
Locations:
/etc/periodic/daily//etc/periodic/weekly//etc/periodic/monthly//etc/daily.local/etc/weekly.local/etc/monthly.local
Trigger: Scheduled (daily/weekly/monthly)
Permissions: Root required
Detection & Enumeration
Comprehensive Check Script
#!/bin/bash
# macOS Persistence Enumeration
echo "=== Launch Agents ==="
ls -la ~/Library/LaunchAgents/ 2>/dev/null
echo "\n=== Launch Daemons ==="
sudo ls -la /Library/LaunchDaemons/ 2>/dev/null
echo "\n=== Shell Startup Files ==="
ls -la ~/.zshrc ~/.bashrc ~/.profile ~/.zprofile 2>/dev/null
echo "\n=== Login Items ==="
osascript -e 'tell application "System Events" to get the name of every login item' 2>/dev/null
echo "\n=== Cron Jobs ==="
crontab -l 2>/dev/null
echo "\n=== SSH RC ==="
cat ~/.ssh/rc 2>/dev/null
echo "\n=== Terminal Preferences ==="
plutil -p ~/Library/Preferences/com.apple.Terminal.plist 2>/dev/null | grep -A2 "CommandString"
echo "\n=== iTerm2 AutoLaunch ==="
ls -la "$HOME/Library/Application Support/iTerm2/Scripts/AutoLaunch/" 2>/dev/null
echo "\n=== Folder Actions ==="
ls -la "$HOME/Library/Scripts/Folder Action Scripts/" 2>/dev/null
echo "\n=== QuickLook Plugins ==="
ls -la ~/Library/QuickLook/ 2>/dev/null
echo "\n=== Screen Savers ==="
ls -la ~/Library/Screen\ Savers/ 2>/dev/null
echo "\n=== Spotlight Importers ==="
ls -la ~/Library/Spotlight/ 2>/dev/null
echo "\n=== Audio Plugins ==="
ls -la ~/Library/Audio/Plug-ins/Components/ 2>/dev/null
Removal & Cleanup
Remove Launch Agent
launchctl unload ~/Library/LaunchAgents/com.example.plist
rm ~/Library/LaunchAgents/com.example.plist
Remove Login Item
osascript -e 'tell application "System Events" to delete login item "itemname"'
Remove Cron Job
crontab -r
Remove Shell Persistence
# Edit and remove malicious lines
nano ~/.zshrc
# or
sed -i '' '/malicious_command/d' ~/.zshrc
Best Practices for Security Testing
- Document everything - Keep track of all persistence mechanisms you create
- Test in isolated environments - Use VMs or test machines
- Have removal procedures ready - Know how to clean up after testing
- Check for conflicts - Some mechanisms may interfere with each other
- Verify triggers - Test that each mechanism actually executes
- Monitor logs - Check system logs for detection