Building a Quick Live Response Script for macOS Incident Response
When responding to a potential security incident, time is of the essence. Volatile data – such as running processes and active network connections – can disappear if the machine is powered off or rebooted. To capture this critical information quickly and consistently, we built a simple, effective Live Response Script for macOS today.
In this post, we’ll walk through what we created, why we created it, and how it works under the hood.
The Goal
The objective was straightforward: create a single bash script (live_response.sh) that acts as an automated triage tool. With one command, we needed to gather:
- A list of all currently running processes.
- All active network connections (to see who the computer is talking to right now, and which processes are making those connections).
- A recent snapshot of system logs.
- Cryptographic hashes of files in a commonly targeted directory (the user’s Downloads folder).
Under the Hood: The Four Pillars of Triage
Here is a breakdown of the core commands powering our script.
1. Running Processes
To see exactly what code is executing on the machine at the moment the script is run, we utilized the standard ps utility:
bashps aux
This command provides a comprehensive list of all processes (a), including those without a controlling terminal (x), and displays the process owner (u).
2. Active Network Connections
Is malware beaconing out to a command-and-control server? To find out, we need to see the active network connections. We used lsof (List Open Files):
bashlsof -i -n -P
- -i filters for network files (Internet addresses).
- -n inhibits the conversion of IP addresses to hostnames (speeding up the command and preventing unexpected DNS lookups that might tip off an attacker).
- -P inhibits the conversion of port numbers to port names.
3. System Logs
macOS uses the Unified Logging System. To grab the most recent events, we reached for log show:
bashlog show --last 100
This extracts the final 100 entries from the system log, which can provide immediate context into recent system events, errors, or authentication attempts.
4. File Hashes (Downloads Folder)
The Downloads folder is a frequent landing zone for malicious payloads. To ensure we have a record of every file present (and to check against threat intelligence feeds later), we generated SHA-256 hashes of the contents:
bashfind "$HOME/Downloads" -type f -exec shasum -a 256 {} +
This efficiently finds all files (-type f) and passes them to shasum to calculate their cryptographic signatures.
Bringing it Together: Dual Output with tee
While it is helpful to see the output scroll by on the terminal, incident responders need a persistent, immutable record of the collected evidence.
To solve this, we wrapped our commands in a structure that outputs to the console and writes to a securely timestamped file in the same directory:
bashTIMESTAMP=$(date +"%Y%m%d_%H%M%S")OUTPUT_FILE="live_response_report_${TIMESTAMP}.txt"# Example wrappingecho "[*] Gathering Currently Running Processes..." | tee -a "$OUTPUT_FILE"ps aux | tee -a "$OUTPUT_FILE"
Considerations and Best Practices
One key finding during testing is the importance of privileges. While a standard user can run ps and lsof, they will only see their own processes and network connections. Furthermore, accessing the full Unified Logging System requires administrative rights. Therefore, for a complete and accurate picture, the script must be executed with root privileges:
bashsudo ./live_response.sh
Conclusion
By chaining together native macOS command-line utilities, ps, lsof, log, and shasum, we’ve created a lightweight, zero-dependency Live Response script. It provides an immediate snapshot of the system’s volatile state, empowering defenders to make informed decisions during the early stages of an incident response engagement.