dscl
, which can show up user accounts that might be hidden from display in the System Preferences app and the login screen. $ dscl . list /Users UniqueID
/Users
folder with something like ls
, which won’t show you hidden users or those whose home folder is located elsewhere, so be sure to use dscl
to get a complete picture.dscl list
command is that it will flood you with perhaps a 100 or more accounts, most of which are used by the system rather than used by console (i.e., login) users. We can narrow the list down by filtering out all the system accounts by ignoring those that begin with an underscore:$ dscl . list /Users UniqueID | grep -v ^_
w
, which tells you every user that is logged in and what they are currently doing._mrmalicious
, which wouldn’t have appeared if we filtered the dscl
list by grepping out underscores, is using bash
.w
utility is a great way to check out who is currently active, it won’t show up a user that has been and gone, so let’s supplement our hunt for users with the last
command, which indicates previous logins.$ last
/var/root
. netstat
and lsof
to help check for this.$ netstat -na | egrep 'LISTEN|ESTABLISH'
$ lsof -i
ps
utility for more information on each process.$ ps -p <pid>
ps
command has a lot of useful options and is one of a number of tools you can use to see what’s running on a Mac at the time of collection. $ ps -axo user,pid,ppid,%cpu,%mem,start,time,command
PPID
, the parent process identifier, is something other than 1, indicating a user process that’s also spawning child processes. $ lsappinfo list
launchctl
utility. I find the older, deprecated (but still functional) syntax somewhat easier to parse than the newer syntax, but that may be just my preference from habit, so experiment with either.$ launchtl list
sudo
will produce a list of services running in the system-wide domain. $ launchctl print user/501
$ launchctl print system
grep
out anything with a com.apple
label so that I can focus on (mostly) non-system processes. However, some macOS malware does deliberately use the name “apple” in their labels precisely in an attempt to hide in the weeds, so if you do follow that suggestion be sure that you’re parsing items with “apple” labels somewhere else, too (e.g., such as from the data you received from examining the Launch folders or from using the ps
utility). lsof
with the -i
option to list open ports, but we can also list all open files by just running lsof
without any flags at all. That produces quite a mountain of information and you’ll want to quickly narrow it down to make it manageable. csrutil status
), I will normally parse the output of lsof
in something like BBEdit and remove all lines that contain references to the System
folder. Bear in mind that doing so could cause you to miss something – not all System folders are protected by SIP, but in the early stages of an investigation I will leave that kind of possibility for later in the event that I don’t find any other IOCs (Indicators of Compromise)./Library
and ~/Library
folders, and the Application Support
folders within all of those (remember there’s a separate Library folder for every user as well as the one at the computer domain level).$ ls -al ~/.* ~/Library /Library ~/Library/Application Support /Library/Application Support/
sudo
and iterate over users with a bash script if there’s more than one user account on the Mac./Users/Shared
folder, and the temp directories at /private/tmp
and the user’s Temporary Directory (these are not the same), which you can get to using the $TMPDIR
environment variable.$ ls -al /Users/Shared
$ ls -al /private/tmp
$ ls -al $TMPDIR
Cron
jobs from your investigation into persistence mechanisms. More often than not the program arguments of these will have already led you to other locations of interest.find
search to look for any files created since or between a certain time or date. For example, this will find any files modified in the current working directory in the last 30 minutes. You can substitute the m
for h
to specify hours, or leave off a specifier and it will default to days.$ find . -mtime +0m -a -mtime -30m -print
LSQuarantine
database to see what items have been downloaded by email clients and browsers. $ sqlite3 ~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV* 'select LSQuarantineEventIdentifier, LSQuarantineAgentName, LSQuarantineAgentBundleIdentifier, LSQuarantineDataURLString, LSQuarantineSenderName, LSQuarantineSenderAddress, LSQuarantineOriginURLString, LSQuarantineTypeNumber, date(LSQuarantineTimeStamp + 978307200, 'unixepoch') as downloadedDate from LSQuarantineEvent order by LSQuarantineTimeStamp' | sort | grep '|' --color
mdfind
query on the quarantine bit:$ mdfind com.apple.quarantine
$ ifconfig
$ plutil -p /Library/Preferences/SystemConfiguration/preferences.plist
$ scutil --proxy
system_profiler
and sysdiagnose
utilities, unified logging, fsevents
and a plethora of sqlite
caches that hold almost every detail you could ever wish to know. In the majority of cases, the steps outlined above will be sufficient to find evidence of even the most stealthy of macOS malware, but digging down into the hidden depths of macOS may provide you with more evidence that can help in detection, remediation, and attribution. /Library/LaunchDaemons
/Library/LaunchAgents
~/Library/LaunchAgents