We recently came across an interesting malicious Word document that used an embedded Word macro to detect whether or not it was being opened inside a VM. If no VM was detected, the macro proceeded to attempt to download a payload (executable) to infect the machine. Let’s take a look at our analysis and how VMRay’s Function logs can aid in analysing heavily obfuscated code such as the macro in this document.
SwiftOnSecurity, a well-known infosec commentator referred to the ‘Enable Content’ button in Word as the ‘Infect-my-computer-button’ with some justification as we see here.
In our example, a little social engineering was used to coax the potential victim to enable content, allowing the macro to run, as shown in Figure 1:
Fig. 1 – A little social engineering by the malware author
If the user falls for it and enables content, a macro starts automatically and triggers the function
Document_Open(). This leads to heavily obfuscated Visual Basic code running that will both detect if the document is open inside a VM and download an executable that will infect the system.
Fig. 2 – Document_Open() starts the obfuscated macro.
We start the analysis by uploading the document to VMRay Analyzer. The results come back a couple minutes later unambiguously malicious – 100/100 on the VTI (VMRay Threat Identifier) Threat Score. One of the main reasons for the high score is that an attempt is made to download an executable file – singularly suspicious behavior for a Word document.
Fig. 3 – Analysis generates a high VTI Threat Score
A closer look at this behavior shows something interesting. The Word macro uses WMI (Windows Management Instrumentation) to detect the presence of a VM. To extract this behavior, we have to de-obfuscate the Visual Basic code in the macro. Normally this is hard work for an analyst, but with the aid of the function log extracted by the VMRay analysis, it is much easier. This function log is created while the analysis is running. It contains in plain text every function call and associated parameter. For example, we can see in Figure 4 the download link inside the function logfile.
Fig. 4 – Malicious download link in plain text in Function Logfile
Typically, an attacker who obfuscates macros will also obfuscate the function calls. For this they use a simple trick. Visual Basic allows creation of class objects with the function CreateObject(). This function needs a string as input. For example: CreateObject(“WScript.Shell”) creates a shell-object. The attacker then encrypts this string and decrypts it on use.
As an example, first the attacker encrypts the string “
Wscript.Shell” to “
lhtrWxaHLlSpcG.xS9e.iSkycrB” and writes it to a list named “
doTNALtI” at index “
QJnANGYgOwW”. From then on “
doTNALtI.QJnANGYgOwW” will point to “
lhtrWxaHLlSpcG.xS9e.iSkycrB” which is the decrypted “
Wscript.Shell”. In the next step the attacker creates a subroutine for
CreateObject() named “
WkKQhrg04” and a subroutine for the decrypt-function named “
kFfxtZGj54a” that will decrypt the input string.
As a result, the simple call of
CreateObject(“WScript.Shell”) is obfuscated to
This makes it very hard to reconstruct the macro.
Fig. 5 – Obfuscation of CreateObject(“WScript.Shell”)
However, with the aid of the function log, the reconstruction won’t be as hard as it looks. We only have to look for strings and functions in the function log that make sense. For example, our familiar “Wscript.Shell” will be found in the function log as follow:
CLSIDFromProgIDEx (in: lpszProgID="WScript.Shell", lpclsid=0x2130e0 | out: lpclsid=...)) returned 0x0
With this information we resolved
kFfxtZGj54a(360, doTNALtI.QJnANGYgOwW) to “
Wscript.Shell” without bothering to decrypt the string. This can be done for every obfuscated string in the macro, so that a complete reconstruction of the Visual Basic macro is possible. While doing this we found an interesting embedded VM detection routine.
Before the Visual Basic macro starts its infection it tries to detect the presence of a VM environment with the
VMDetectionFails method. If this method returns true, the infection will start. Otherwise the macro stops running.
Public Sub MAIN() if VMDetectionFails then runInfection else error end if
VMDetectionFails method contains three detection methods with the following logic:
Private Function VMDetectionFails() As Boolean if Detection01 Or Detection02 then VMDetectionFails = Detection03 else VMDetectionFails = True end if
If Detection01 or Detection02 detects a VM, Detection03 decides whether the macro should run. Otherwise if Detection01 and Detection02 detect no VM, the method returns true.
The first detection method has two stages. The first stage checks if the environment variable “USERNAME” is equal to “USER” and “USERDOMAIN” is equal to “HOST”. If both values are true the detection is triggered. Otherwise it proceeds to stage two.
In the second stage with the aid of WMI (Windows Management Instrumentation) the detection method calls the command: GetObject(“winmgmts:“).InstancesOf (“Win32_ComputerSystem“). This creates with the WMI command “winmgmts” an instance of “Win32_ComputerSystem”. This instance contains all the information about the System.
Now the detection method looks specifically for information about the “Manufacturer” and “Model” and checks if it contains one of the following strings: “KVM”, “QEMU”, “RED HAT”, “VIRTUAL”, “VMWARE”, “XEN”. If it does, the detection method triggers and returns true.
The second detection method uses WMI as well. With the following WMI command the detection method will get a list of all running processes:
GetObject("winmgmts:").ExecQuery ("Select * from Win32_Process")
With this list it will check if it contains one of the following processes:
“FIDDLER”, “PROCEXP”, “PROCMON”, “SNORT”, “SURICATA”, “WIRESHARK”
If the detection method has a match it will return true.
This detection method checks if the string “1461591186_usa” is part of the document path. If it is, the detection method returns true, so that the infection starts. The check takes place as follows:
InStr(1, callByName(ThisDocument, "Path", 2), "1461591186_usa") <> 0
We can only speculate on the author’s intention here in using this particular string and test.
This analysis shows that VM detections can also be embedded into Visual Basic macros. Fortunately, the VMRay Analyzer environment remains undetected by the malware so it executes and we get a full analysis. This can be confirmed by the attempted download of
which starts only if no VM environment is detected.
However, at the time of our analysis the C2 (command and control) server had already been taken down, so the download was not successful in any event. The function log generated in a VMRay analysis is a very useful tool for analyzing heavily obfuscated word macros. It enables easy reconstruction of the macro, providing a clear understanding of the malware’s methods and goals.
Follow us on Twitter @VMRay to get updates on future blog posts like this.