Email Threat Review March 2021

Email Threat Review March 2021


In this first installment of our monthly email threat review, we present an overview of the email-based threats observed in March 2021.

Unwanted emails by category

The following table shows the distribution of unwanted emails by categories.

Email category %
Rejected 78.91
Spam 16.08
Threat 3.99
AdvThreat 0.98
Content 0.03

The following time histogram shows the email volume per category per hour.

Filetypes used in attacks

The spike from 2021-03-20 to 2021-03-23 in rejected emails can be attributed to a large sextortion spam campaign. The emails used the German language.

Sextortion spam wave email example

As of 2021-03-28, the scammers have received three payments for a total of 0.10492057 BTC, equating to 5,267.36 € (around three times the asked extortion fee).


The listed email categories correspond to the email categories listed in the Email Live Tracking of Hornetsecurity’s Control Panel. So our users are already familiar with them. For others, the categories are:

Category Description
Spam These emails are unwanted and are often promotional or fraudulent. The emails are sent simultaneously to a large number of recipients.
Content These emails have an invalid attachment. The administrators define in the Content Control module which attachments are invalid.
Threat These emails contain dangerous content, such as malicious attachments or links, or they are sent to commit crimes, such as phishing.
AdvThreat Advanced Threat Protection has detected a threat in these emails. The emails are used for illegal purposes and involve sophisticated technical means that can only be fended off using advanced dynamic procedures.
Rejected Our email server rejects these emails directly during the SMTP dialog because of external characteristics, such as the identity of the sender, and the emails are not analyzed further.

Filetypes used in attacks

The following table shows the distribution of file types used in attacks.

Filetypes (used in malicous emails) %
Archive 38.3
HTML 16.4
Excel 12.0
PDF 10.6
Executable 7.6
Other 6.7
Disk image files 4.1
Word 3.6
Script file 0.4
Powerpoint 0.3
Email 0.0
LNK file 0.0

The following time histogram shows the email volume per file type used in attack per 7 days.

Filetypes used in attacks

Archives (.zip, .rar, .gzip, .ace, .tar.gz, etc.) are more popular. The most prevalent use for archives in attacks is compressing the malware executable and attaching it directly to the attack email. This is done in hopes that the targeted email system is not able to scan compressed attachments. Low-quality criminal threat actors often use this technique as it does not require any technical expertise. Another use for archives is to compress malicious documents. This is also done to reduce detection.

HTML files (.htm, .html, etc.) are used either for phishing, having the phishing website attached directly to the email1 (thus circumventing URL filters), redirecting victims to websites for malware downloads2 (again to not directly include a clickable URL in the email), or social engineering.

Excel files (.xls, .xlsm, .xlsx, .xslb, etc.) with their XLM macros have gained popularity last year. Unlike VBA macros malware, XLM macro malware is less detected and thus favored by many threat actors.3,4 In fact, many threat actors use the same malicious document generator called “EtterSilent” to generate their XLM macro documents.

PDFs (.pdf) use embedded links or other social engineering lures.4

Attaching executables (.exe) directly to emails is the laziest approach. It is used mainly by low-quality criminal threat actors.

Disk image files (.iso, .img, etc.) are used similarly to archives.5 Windows can automatically mount disk image files similarly to ZIP files.

Industry Email Threat Index

The following table shows our Industry Email Threat Index calculated based on the number of threat emails compared to clean emails received (in median) by each industry.

Industries Share of threat in threat and clean emails
Research industry 6.9
Manufacturing industry 6.5
Healthcare industry 6.1
Education industry 6.0
Media industry 5.9
Mining industry 5.7
Entertainment industry 5.4
Hospitality industry 5.2
Automotive industry 5.1
Retail industry 5.0
Transport industry 4.8
Construction industry 4.6
Utilities 4.6
Agriculture industry 4.4
Information technology industry 4.4
Unknown 4.4
Professional service industry 4.4
Financial industry 3.9
Real estate industry 3.7
Logistics industry 3.1

The following bar chart visualizes the email-based threat posed to each industry.

Hornetsecurity Industry Email Threat Index


Different (sized) organizations receive a different absolute number of emails. Thus, to compare organizations, we calculated the percent share of threat emails from each organization’s threat and clean emails. We then calculate the median of these percent values overall organizations within the same industry to form the industry’s final threat score.

Attack techniques

The following table shows the attack technique used in attacks.

Attack technique %
Phishing 28.0
Other 25.7
URL 23.2
Extortion 12.1
Executable in archive/disk-image 4.9
Advance-fee scam 3.1
Impersonation 2.6
Maldoc 0.4
LNK 0.0

The following time histogram shows the email volume per attack technique used per hour.

Attack techniques

From 2021-03-20 to 2021-03-23 we can see an increase in extortion emails. These are the emails of the sextortion campaign discussed previously that were not already caught by our RBL. This illustrates how Hornetsecurity’s multi-layered filtering system works. Spammers will always acquire IPs that are not blacklisted by RBLs. But these emails will simply be caught by one of our later filter stages. The data of filtered emails is analyzed and the new clean IPs of the spammers are added to the RBL. This way, our systems can also handle large-scale attacks with ease.

Impersonated company brands

The following table shows which company brands our systems detected most in impersonation attacks.

Impersonated brand %
Deutsche Post / DHL 19.7
Amazon 16.4
Facebook 8.8
PayPal 4.6
1&1 3.9
Microsoft 3.7
DocuSign 3.2
O2 2.7
HSBC 1.7
Other Rest

The following time histogram shows the email volume for company brands detected in impersonation attacks per hour.

Impersonated company brands

It’s a constant stream of phishing and other attacks impersonating big brands to entice recipients to open the emails.

Highlighted threat email campaigns

In this section, we want to highlight some malspam campaigns of prominent, well-known threat actors.

The following table shows a list of highlighted threat email campaigns with their email volume share among the highlighted threat email campaigns.

Highlighted threat email campaign %
Dridex (via Cutwail) 47.7
Hancitor (Fake DocuSign email with Google Doc link) 16.1
TrickBot (XLS,XLSB) 14.5
QakBot (XLS in ZIP) 14.1
LemonDuck (XLSM in ZIP) 4.8
IcedID (XLSM in ZIP) 1.4
Ursnif (via Cutwail) 1.1
Lokibot (EXE in RAR) 0.2
Gozi (DOC) 0.0

Please be advised that this does not contain all campaigns. The ranking, as well as volume figures, should therefore not be taken as a global ranking. We strive to expand this section of our reporting in the future.

The following time histogram shows the email volume for highlighted threat email campaigns per hour.

Highlighted threat email campaigns

We can see that the malspam waves of the selected campaigns have well defined start and end points, unlike less sophisticated mass-spam email campaigns, which will send email in a constant stream.

From the data, we can see that volume-wise the Cutwail botnet dominates. It mainly distributed Dridex malware (via various malicious document attachments) and Ursnif. Another large volume campaign was Hancitor malware spread via emails pretending to be from DocuSign using links to malware hosted on Google Docs.


Hornetsecurity observes hundreds and thousands of different threat email campaigns of varying threat actors ranging from very unsophisticated low-effort attacks to highly complex obfuscated attack schemes. Our highlighting includes only major sophisticated threat email campaigns.


Threat actors continue to leak data stolen from ransomware victims in an attempt to pressure them into paying not only for decrypting the files encrypted by the ransomware but also for not make the data stolen before encryption public. We observed the following number of leaks on ransomware leaksites:

Leaksite Number of victim data leaks
Darkside 57
Pysa 38
Conti 36
Avaddon 27
Cl0p 23
REvil 19
Babuk 17
MountLocker 7
Nephilim 7
Doppelpaymer 6
Astro Team 5
Ragnarok 2
RansomEXX 2

The following bar chart visualizes the number of victim data leaks per leaksite.


A new entry to the list is the Astro Team ransomware leaksite.

Astro Team leaksite


We hope you found the first installment of our monthly email threat review informative. Get back next month for more and updated email threat landscape insights.


Zloader email campaign using MHTML to download and decrypt XLS

Zloader email campaign using MHTML to download and decrypt XLS


Zloader1 malware (associated with the kev configuration tag) is spreading via malspam using MIME encapsulation of aggregate HTML documents (MHTML)5 attachments. These MHTML files contain a Word document with VBA macros. The VBA macro code downloads and decrypts a password-protected XLS file, and after that, the XLS file decodes and executes the Zloader malware embedded within it.


In February 2020, campaigns distributing Zloader ramped up usage of XLM (also known as Excel 4.0) macros. Detection of this old spreadsheet-based by design self-modifiable macro code format by anti-virus software is far lower than detection of regular sequential not by design self-modifiable plain-text VBA macro source code. We already highlighted the abuse of XLM macros in previous reports, e.g., XLM macros used to spread QakBot2 or BazarLoader3. However, as detection for XLM macro code has picked up with even Microsoft adding XLM macro support to AMSI4, threat actors continue to evolve.

Starting in January 2021, Hornetsecurity took notice of a new Zloader campaign using MHTML attachments. MIME encapsulation of aggregate HTML documents (MHTML)5 is a web page archive format used to combine multiple files into one. It used base64 encoding and MIME-boundaries similar to multipart MIME encoding in emails. Microsoft Word can open documents stored inside MHTML files.

Technical Analysis

The chain of infection of the Zloader MHTML campaign is as follows:

Zloader kev MHTML campaign chain of infection

We will now outline each step of the attack chain.


The attack starts with emails.

Januar (first wave)

The first emails were designed and built like purchase invoices.

Zloader kev MHTML campaign January email

The wording and pretext changed between emails of this campaign. However, the general “invoicing” theme remained constant.

Zloader kev MHTML campaign January email

Initial email attacks were of low volume, the emails templates above have not been used much.


In February, contract pretexts were added to the mix of invoice pretexts.

Zloader kev MHTML campaign February email

At one point, the numero sign () was used instead of the number sign (#).

Zloader kev MHTML campaign February email

After that, with recent changes to the email template, the campaign’s volume started to increase sharply.


The campaign targets international, Canadian, US, and British companies, mainly English-speaking users.

Zloader kev MHTML campaign by targeted recipient country

However, the time histogram shows that on 2021-02-15, the majority of Zloader MHTML emails were destined for Canadian recipients.

Zloader kev MHTML campaign time histogram

The estimated distribution of recipients by industries would suggest a bias towards the professional services industry, i.e., consultancies, freelancers, funeral homes, law firms, etc.

Zloader kev MHTML campaign time histogram

MHTML documents

The MHTML document’s extension was set to .doc, so Microsoft Word will open the documents directly.

The smaller January campaign and later February campaign MHTML document’s main difference is the image instructing the user to “enable content” and “enable editing”, i.e., activating macro execution.

The January campaign lure image looks as follows:

Zloader kev MHTML campaign January MHTML document

The February campaign lure image looks as follows:

Zloader kev MHTML campaign February MHTML document

The MHTML document is an ASCII document featuring multiple MIME-parts.

Zloader kev MHTML campaign MHTML document in ASCII

One MIME-part contains the lure image.

Zloader kev MHTML campaign MHTML document MIME-parts

The other parts contain an application/ and an application/x-mso file. Which (in addition to the text/xml files) are used by Microsoft Word to load the embedded Word document.

The document will automatically execute the macro code on closing the document:

Zloader kev MHTML campaign MHTML document VBA macro document close

The VBA code uses UserForm objects for obfuscation.

Zloader kev MHTML campaign MHTML document VBA macro userforms

Within the ComboBox objects’ initialization code in the UserForm objects and various other mechanisms, a download URL and a password are assembled and used within a call to the VBA function CallByName. This calls the Workbook object’s open function with the fileName parameter set to the download URL, the Password parameter set to the assembled password, and the other optional parameters left empty.

Zloader kev MHTML campaign MHTML document VBA macro userforms

The call will cause Word to open Excel and download the encrypted XLS file from the URL https://findinglala[.]com/down/doc.xls?ekyh_vD91041.z4730435.doc. Excel will use the provided password to decrypt the document.

The XLS document will use XLM macros to decode and use rundll32.exe to execute an embedded Zloader payload.


Zloader is a fork of the famous Zeus banking Trojan. It is a loader that allows its operator to load additional malware onto infected devices.

Coarse dynamic analysis

The via rundll32.exe started Zloader process from the XLS document will spawn a suspended msiexec.exe process and inject code into it.

Zloader kev MHTML campaign Zloader dynamic analysis

First, the original DLL running in rundll32.exe starts a msiexec.exe process.

Zloader kev MHTML campaign Zloader dynamic analysis

Then, WriteProcessMemory is used to write code into it.

Zloader kev MHTML campaign Zloader dynamic analysis

Eventually, the Zloader code running in rundll32.exe resumes the thread in the msiexec.exe process via NtResumeThread and the injected code starts running.

Zloader kev MHTML campaign Zloader dynamic analysis

Zloader will then generate a lot of random directories in %APPDATA%\Roaming.

Zloader kev MHTML campaign Zloader dynamic analysis

It then copies the original DLL into one of the folders. To this end, it first reads the original DLL into memory.

Zloader kev MHTML campaign Zloader dynamic analysis

In the next step, data from the DLL is being written back into a new file.

Zloader kev MHTML campaign Zloader dynamic analysis

The other folders remain empty but can be used at later points in time to hold additional data.

Zloader kev MHTML campaign Zloader dynamic analysis

The original DLL is deleted.

Zloader kev MHTML campaign Zloader dynamic analysis

Eventually, C2 communication initializes.

Zloader kev MHTML campaign Zloader dynamic analysis


The Zloader DLL injected into msiexec.exe can be extracted either automatically via the open-source CAPE sandbox, manually dumped by breaking on NtResumeThread in the original rundll32.exe process, then dumping the msiexec.exe process, or semi-automatically by using a tool such as hollows_hunter5 (or PE-Sieve).

Zloader kev MHTML campaign Zloader unpacking

The following analysis was performed on a Zloader DLL dumped from the msiexec.exe process.


The Zloader malware is obfuscated. It makes extensive use of junk code, i.e., adding program instructions that do not contribute to the program logic with the sole purpose of complicating analysis. Further, it often calls complicated functions to perform trivial calculations, making the code appear very complex. For example, the following is a function that performs the binary AND operation on two parameters. The code is littered with such junk code.

Zloader kev MHTML campaign Zloader obfuscation

Dynamic library, function and string resolution

Functions are dynamically resolved at runtime via a hash lookup. Instead of calling a function directly, a proxy function returning a pointer to the desired function is called. The following example shows the function with which Zloader deletes its original file. The function we named zl_get_func received two parameters, the first is a library ID (0 is ntdll) and the second is a hash of the function name that should be called.

Zloader kev MHTML campaign Zloader get function

This is standard practice in modern malware, so no suspicious imports are present in the binary. It also makes a static analysis more complicated.

Obviously, the hash calculation also uses the previous mentioned junk code obfuscation.

Zloader kev MHTML campaign Zloader function hash

However, it can be reimplemented in Python as follows.

def zl_hash(func_name):
    func_name = func_name.lower()
    hash = 0
    for c in func_name:
        a = 0 - (hash << 4)
        hash = 0 - (a - ord(c))
        b = 0x647400ac ^ 0x947400ac
        b = hash & (~(b ^ hash))
        if b != 0:
            d = 0x647400ac ^ 0x6b8bff53
            hash = (b >> 0x18) ^ (d & hash)
    return hash

With this function calls can be de-obfuscated.

Strings are XOR encoded with a static repeating ASCII keystream.

Zloader kev MHTML campaign Zloader string decode


The Zloader configuration is RC4 encrypted with a key using only ASCII as keyspace.

Zloader kev MHTML campaign Zloader config decode

The data at the location we labeled zl_encrypted_config can be decoded with the ASCII string handed as the second parameter to the function we named zl_decrypt_config. Consequently, the configuration of the Zloader sample will be revealed.

Zloader kev MHTML campaign Zloader configuration

The configuration contains a botnet name the particular sample is associated with, a campaign ID (presumably for the threat actors to keep track of infections per campaign), an RC4 key (used to encrypt and decrypt updated configuration stored in the registry) and last but not least a list of command and control URLs the malware should connect to for commands and updates.

We provide an update to the DC3-MWCP script included with the open-source CAPE sandbox that handles configuration extraction for the analyzed Zloader sample in the appendix. It helps automating the configuration extraction.

Malware objectives

The configurations of downloaded pieces of Zloader malware associates them with the kev botnet. The kev ID has been publicly observed since December 2020.

Zloader has been identified as an access vector for Ryuk and Egregor ransomware deployments. Whether the installments associated with the kev configuration tag are part of this or a different ransomware operation is currently unknown. However, by the direction the current threat landscape is moving, it is highly likely the malware is also used to deploy ransomware.

Conclusion and Countermeasures

Spreading the attack into multiple encoded stages (document in HMTL; payload URL in UserForms; download of password-protected XLS; decoding of Zloader payload from decrypted XLS) shows that much effort was put into evading detection. Even after the campaign ran for several weeks, the initial MHTML documents still only got 7 out of 61 detections when first scanned on VirusTotal.

Zloader kev MHTML campaign MHTML document VirusTotal scan

The unusual MHTML encoding of the initial Word document can pose problems for security software unfamiliar with this format. Its initial layer must be parsed differently from OLE/CDF/OpenXML-based Office documents and being ASCII plain-text may completely bypass some detections. For network-based protection software, it is impossible to investigate the intermediary downloaded XLS document with the Zloader payload – because it is encrypted. Another struggle is the low level of maliciousness of the initial Word document. While downloads from documents should always be deemed at least suspicious, in this case, only another Excel document was download. Some business workflows may require Word documents to download resources from web. Consequently, the observed behaviour may fly under the radar. Hence, spreading the malicious components (download; dropper; Zloader malware) over multiple stages can bypass detection for some security solutions.

Hornetsecurity’s Spam and Malware Protection detects and quarantines the outlined threat. Hornetsecurity’s Advanced Threat Protection extends this protection by also detecting yet unknown threats.



DC3-MWCP / CAPE configuration parser

The following DC3-MWCP configuration parser is an update to CAPE’s Zloader parser and can be used as a drop in replacement (additionally we opened a pull request with the upstream project):

# Copyright (C) 2020 Kevin O'Reilly (
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <>.

from mwcp.parser import Parser
import struct
import string
import pefile
import yara
import re
from Crypto.Cipher import ARC4
import logging
log = logging.getLogger(__name__)

rule_source = '''
rule Zloader
        author = "kevoreilly"
        description = "Zloader Payload"
        cape_type = "Zloader Payload"
        $rc4_init = {31 [1-3] 66 C7 8? 00 01 00 00 00 00 90 90 [0-5] 8? [5-90] 00 01 00 00 [0-15] (74|75)}
        $decrypt_conf = {e8 ?? ?? ?? ?? e8 ?? ?? ?? ?? e8 ?? ?? ?? ?? e8 ?? ?? ?? ?? 68 ?? ?? ?? ?? 68 ?? ?? ?? ?? e8 ?? ?? ?? ?? 83 c4 08 e8 ?? ?? ?? ??}
        uint16(0) == 0x5A4D and any of them


yara_rules = yara.compile(source=rule_source)

def decrypt_rc4(key, data):
    cipher =
    return cipher.decrypt(data)

def string_from_offset(data, offset):
    string = data[offset : offset + MAX_STRING_SIZE].split(b"\0")[0]
    return string

class Zloader(Parser):

    DESCRIPTION = 'Zloader configuration parser'
    AUTHOR = 'kevoreilly'

    def run(self):
        filebuf = self.file_object.file_data
        pe = pefile.PE(data=filebuf, fast_load=False)
        image_base = pe.OPTIONAL_HEADER.ImageBase
        matches = yara_rules.match(data=filebuf)
        if not matches:
        for match in matches:
            if match.rule != "Zloader":
            for item in match.strings:
                if '$decrypt_conf' in item[1]:
                    decrypt_conf = int(item[0])+21
        va = struct.unpack("I",filebuf[decrypt_conf:decrypt_conf+4])[0]
        key = string_from_offset(filebuf, pe.get_offset_from_rva(va-image_base))
        data_offset = pe.get_offset_from_rva(struct.unpack("I",filebuf[decrypt_conf+5:decrypt_conf+9])[0]-image_base)
        enc_data = filebuf[data_offset:].split(b"\0\0")[0]
        raw = decrypt_rc4(key, enc_data)
        items = list(filter(None, raw.split(b'\x00\x00')))
        self.reporter.add_metadata("other", {"Botnet name": items[1].lstrip(b'\x00')})
        self.reporter.add_metadata("other", {"Campaign ID": items[2]})
        for item in items:
            item = item.lstrip(b'\x00')
            if item.startswith(b'http'):
                self.reporter.add_metadata("address", item)
            elif len(item) == 16:
                self.reporter.add_metadata("other", {"RC4 key": item})

Indicators of Compromise (IOCs)



  • Agreement information#?[0-9]+
  • Agreement info#?[0-9]+
  • Contract info#?[0-9]+
  • Contract information#?[0-9]+
  • Payment data#?[0-9]+
  • Invoicing data#?[0-9]+
  • Contract data#?[0-9]+
  • Invoicing information#?[0-9]+
  • Invoice data#?[0-9]+
  • Invoicing details#?[0-9]+
  • Payment info#?[0-9]+
  • Invoicing info#?[0-9]+
  • Agreement data#?[0-9]+
  • Contract details#?[0-9]+
  • Invoice information#?[0-9]+
  • Invoice details#?[0-9]+
  • Payment information#?[0-9]+
  • Invoice info#?[0-9]+
  • Agreement details#?[0-9]+
  • Payment details#?[0-9]+
  • Important agreement #?[0-9]+ update
  • Essential contract No. #?[0-9]+ update
  • Essential agreement No. #?[0-9]+ documentation
  • Important contract No. #?[0-9]+ update
  • Important contract №#?[0-9]+ update
  • Essential agreement Number #?[0-9]+ update
  • Necessary contract №#?[0-9]+ update
  • Important contract № #?[0-9]+ update
  • Important agreement No. #?[0-9]+ documentation
  • Important agreement #?[0-9]+ documentation
  • Necessary agreement Number #?[0-9]+ documentation
  • Important contract № #?[0-9]+ documentation
  • Important contract #?[0-9]+ documentation
  • Important agreement № #?[0-9]+ documentation
  • Essential contract #?[0-9]+ update
  • Essential agreement No. #?[0-9]+ update
  • Necessary agreement Number #?[0-9]+ update
  • Necessary contract № #?[0-9]+ update
  • Important agreement Number #?[0-9]+ update
  • Essential contract No. #?[0-9]+ documentation
  • Important contract #?[0-9]+ update
  • Essential agreement #?[0-9]+ update
  • Necessary agreement № #?[0-9]+ update
  • Important agreement No. #?[0-9]+ update
  • Necessary contract Number #?[0-9]+ documentation
  • Necessary contract No. #?[0-9]+ update
  • Necessary agreement #?[0-9]+ update
  • Essential contract Number #?[0-9]+ documentation
  • Essential contract № #?[0-9]+ documentation
  • Essential agreement №#?[0-9]+ update
  • Necessary agreement №#?[0-9]+ update
  • Essential contract Number #?[0-9]+ update
  • Necessary contract No. #?[0-9]+ documentation
  • Important contract №#?[0-9]+ documentation
  • Important agreement № #?[0-9]+ update
  • Essential contract №#?[0-9]+ documentation
  • Essential contract #?[0-9]+ documentation
  • Necessary contract №#?[0-9]+ documentation
  • Necessary agreement #?[0-9]+ documentation
  • Important contract Number #?[0-9]+ documentation
  • Necessary contract #?[0-9]+ update
  • Important agreement №#?[0-9]+ update
  • Essential contract №#?[0-9]+ update
  • Essential agreement №#?[0-9]+ documentation
  • Necessary contract #?[0-9]+ documentation
  • Important agreement Number #?[0-9]+ documentation
  • Essential agreement № #?[0-9]+ documentation
  • Necessary agreement № #?[0-9]+ documentation
  • Essential agreement Number #?[0-9]+ documentation
  • Essential contract № #?[0-9]+ update
  • Necessary contract Number #?[0-9]+ update
  • Necessary agreement No. #?[0-9]+ update
  • Essential agreement № #?[0-9]+ update
  • Essential agreement #?[0-9]+ documentation
  • Important contract No. #?[0-9]+ documentation
  • Necessary agreement No. #?[0-9]+ documentation
  • Important contract Number #?[0-9]+ update
  • Necessary contract № #?[0-9]+ documentation
  • Necessary agreement №#?[0-9]+ documentation
  • Important agreement №#?[0-9]+ documentation


The following regular expressions describe the attachment names used in the campaigns:

  • ([a-z]{4,8}_){1,2}[a-z]{4,8}[0-9]+.doc
  • [A-z0-9][A-z][0-9]+.doc


Hashes of publicly available files:

MD5 Filename Description
6743ca84f7e9929c2179238e20934f57 nG772044.doc Zloader MHTML document
7a888f899a4850f02bad194bf01daaa7 eU107462.doc Zloader MHTML document
35ee0681eb3076674e01efec565f663b L1978883.doc Zloader MHTML document
25e2cffc5621cab99bd0a36d234c234f QG915014.doc Zloader MHTML document
222cb61e1041f3e4dbdc3493572388e6 dY433632.doc Zloader MHTML document


  • https://findinglala[.]com/down/doc.xls?ekyh_vD91041.z4730435.doc


  • findinglala[.]com
  • funkstarnews[.]com
  • heavenlygem[.]com
  • 2tut[.]com
  • khalilmouna[.]com
BazarLoader’s Elaborate Flower Shop Lure

BazarLoader’s Elaborate Flower Shop Lure


Since 2021-01-20 Hornetsecurity observes a new malspam campaign using a fake flower shop in an elaborate social engineering lure to spread the BazarLoader malware. The campaign sends invoices from a fake flower shop in hopes that potential victims will manually find the fake flower shop website and download the BazarLoader malware.

In order to lure the victims into providing manual assistance the campaign setup a fully functional flower shop website and can thus evade automated detection schemes looking for malicious content, as the malicious download will be manually downloaded by the victim following several manual steps of the social engineering trap.


BazarLoader1 is a malware loader attributed to a threat actor with a close relation to the TrickBot malware. The threat actor is tracked under the name Team9 (Cybereason) or UNC1878 (FireEye).

BazarLoader is also aptly named KEGTAP by FireEye, as in a device used to open a beer keg, because it is used to “open” the network of victims for follow up malware in order to move laterally on the network and eventually deploy the Ryuk ransomware.2

We have previously reported on a BazarLoader campaign using an employment termination social engineering lure to spread its malware.3

The observed campaign started on 2021-01-21 and is ongoing.

BazarLoader campaign subject histogram

It uses various subjects referring to an invoice from the Rose World flower shop. Spoiler: The flower shop isn’t real. The attached invoice is an elaborate social engineering scam to trick victims into downloaded the BazarLoader malware.

Technical Analysis

The following analysis outlines each step of BazarLoader’s new elaborate social engineering campaign.


The attack starts with an email.

BazarLoader flower shop email

The email pretends to be an invoice from the Rose World online store, an online flower shop.


Attached to the email is a PDF invoice.

BazarLoader flower shop PDF

The PDF has no clickable links. It however features a domain name under the address of the supposed invoicing party.

BazarLoader flower shop URL in PDF

Fake Flower Shop

When the recipient visits this domain a webshop for flowers is presented.

BazarLoader fake flower shop

Even though this is a fake shop it features

  • an about page

BazarLoader flower shop fake about us page

  • a blog

BazarLoader flower shop fake blog

  • a shop with fully functional checkout cart, wish list, and Twitter and Facebook share buttons

BazarLoader flower shop

However, the checkout fails because allegedly there are no available payment methods.

BazarLoader fake flower shop fake checkout

The checkout is the only thing not working on the fake shop. Thus it is very hard to identify this as a malicious website.

The Lure

Because the shop looks legit a recipient will likely try to contact the shop owner to clear up the invoice they falsely received. To do so, they visit the contact us section of the fake shop.

BazarLoader fake flower shop contact us page

Here is one last indicator that something is not quite right. The Google Maps frame is in Russian language, while the rest of the webshop pretends to be from the United States of America. However, a victim will likely continue to the convenient order number entry field.

BazarLoader social engineering lure

When the victim enters the order number – in fact any input will suffice – they are redirected via a loading screen.

BazarLoader fake loading page

The loading page is also fake, the content is already loaded under the loading page overlay.

Next, the victim is presented instructions on how to download and execute the malware.

BazarLoader flower shop malware download instructions

It includes instructions to bypass the malicious file download warning on Google Chrome.

BazarLoader flower shop malware download instructions

It even includes instructions to bypass Windows security features preventing the file from being executed because it was downloaded from the Internet.

BazarLoader flower shop malware execution instructions

The “Request Form” link will download a malicious document from hxxps[:]//rosedelivery[.]us/.

Malicious Document

The malicious document pretends to be protected by DocuSign and macros need to be allowed to decrypt it.

BazarLoader flower shop malicious document

The XLM macro code will download the BazarLoader executable from hxxps[:]//www.smowengroup[.]com/fer/iertef.php and execute it.

BazarLoader flower shop malicious XLM macro script

The BazarLoader uses the decentralized Emerald DNS system based on the Emercoin blockchain to establish its C2 communication. It will download and install the BazarBackdoor1. This backdoor will be used to move laterally in the victim’s network in order to take over the domain controller. Eventually the intrusion is monetized by deploying the Ryuk2 ransomware.


The campaign is targeted towards US companies. We conclude this from the email, PDF, fake webshop, but also from the recipients, which are US companies and/or international companies with a US presence.

Conclusion and Countermeasures

The new BazarLoader campaign does not feature malicious indicators in its emails, such as macro documents or clickable URLs. It rather relies on an elaborate social engineering lure to lead the victim towards finding and downloading the malware themselves rather then directly handing it over. The amount of manual work required by victims makes this campaign difficult to detect via automated measures. This is why Hornetsecurity is closely tracking malspam operations by threat actors to quickly engage newly emerging threats. Hence Hornetsecurity is already aware of this new elaborate social engineering scheme to distribute the BazarBackdoor and Hornetsecurity’s Spam and Malware Protection, already quarantines the new BazarLoader emails.


Indicators of Compromise (IOCs)



  • Congratulations on the latest purchase you have made!Your order number is KCD[0-9]{8}G.
  • Congratulations on your purchase from our store! Your order number is KCD[0-9]{8}G.
  • Order Confirmed. Your order number KCD[0-9]{8}G will be send to you soon.
  • Purchase confirmation for order number KCD[0-9]{8}G
  • Thanks for your order, your order number KCD[0-9]{8}G.
  • Thank you for using the (Rose Deliver|Rose World) stores service. Your order number is KCD[0-9]{8}G.
  • Thank you for your order from the (Rose Deliver|Rose World) online shop, your order number is KCD[0-9]{8}G.
  • Thank you for your order from the (Rose Deliver|Rose World) online store, your order number is KCD[0-9]{8}G.
  • Thank you for your purchase, your order number is KCD[0-9]{8}G.
  • You have formed an order KCD[0-9]{8}G from (Rose Deliver|Rose World) online store.
  • Your order No. KCD[0-9]{8}G has been completed by (Rose Deliver|Rose World).

Representation was condensed by using the following regex patterns: KCD[0-9]{8}G, (Rose Deliver|Rose World)

Attachment Filenames

  • invoice_KCD[0-9]{8}G.pdf

Representation was condensed by using the following regex patterns: KCD[0-9]{8}G


MD5 Filename Description
c3347d329bda013282d32ee298c8dc45 invoice_KCD86786085G.pdf Lure PDF
e8b0cc2767cc0195570af56e9e7750fe request_form_1611584809.xlsm Downloaded Maldoc


  • hxxps[:]//roseworld[.]shop
  • hxxps[:]//rosedelivery[.]us/


  • roseworld[.]shop
  • rosedelivery[.]us
Emotet Botnet Takedown

Emotet Botnet Takedown


On 2021-01-27 it was announced by Europol that an international worldwide coordinated law enforcement and judicial action has disrupted the Emotet botnet and investigators have taken control of Emotet’s infrastructure. If successful this could mean the end of Emotet, its botnet, malspam, and malware loader operation. While the situation is still developing, we can confirm that the Emotet botnet infrastructure is disrupted. Victims will be notified by responsible country CERTs and should take appropriate actions to clean their Emotet malware and secondary malware infections to prevent still active malware that was downloaded by Emotet to deploy ransomware.


Emotet (also known as Heodo) was first observed in 2014. It was a banking trojan stealing banking details and banking login credentials from victims. But it pivoted to a malware-as-a-service (MaaS) operation providing malware distribution services to other cybercriminals. Today, Emotet is probably the most prolific malware distribution operation. To this end, it steals the emails of its victims and replies to the victim’s previous conversations. This is known as email conversation thread hijacking5. Hornetsecurity has written numerous blogposts about Emotet2,3,4,5.

What happened?

An international worldwide law enforcement and judicial effort, coordinated by Europol and Eurojust, has disrupted the Emotet botnet. The following authorities took part in this operation:

  • Netherlands: National Police (Politie), National Public Prosecution Office (Landelijk Parket)
  • Germany: Federal Criminal Police (Bundeskriminalamt), General Public Prosecutor’s Office Frankfurt/Main (Generalstaatsanwaltschaft)
  • France: National Police (Police Nationale), Judicial Court of Paris (Tribunal Judiciaire de Paris)
  • Lithuania: Lithuanian Criminal Police Bureau (Lietuvos kriminalinės policijos biuras), Prosecutor’s General’s Office of Lithuania
  • Canada: Royal Canadian Mounted Police
  • United States: Federal Bureau of Investigation, U.S. Department of Justice, US Attorney’s Office for the Middle District of North Carolina
  • United Kingdom: National Crime Agency, Crown Prosecution Service
  • Ukraine: National Police of Ukraine (Національна поліція України), of the Prosecutor General’s Office (Офіс Генерального прокурора).

The investigators obtained control over the infrastructure from one suspect located in Ukraine. Emotet’s C2 communication has been sinkholed and information of connecting victims has been given to the responsible country CERTs, which will notify the victims so they can clean up the infection.

The Dutch National Police has also obtained a database containing e-mail addresses, usernames and passwords stolen by Emotet over the years. They provide a website to check whether an email address has been compromised at

Emotet “uninstaller”

Additionally, German Federal Criminal Police (Bundeskriminalamt (BKA)) is distributing a Emotet remover program from within the Emotet botnet that will uninstall Emotet on 2021-04-25 at 12:00.

The program will create a timestamp for 2021-04-25 12:00 (note tm_month goes from 0 to 11, while tm_day goes from 1 to 31).

Emotet uninstaller timestamp

The program will spawn a thread that in a loop will sleep for 1000 minutes (16.6 hours) until the time to uninstall Emotet is reached.

Emotet uninstaller thread

Once the time to uninstall Emotet is reached Emotet’s registry key and its service are removed. The Emotet binary is moved to a temporary file path presumably to quarantine it for possible DFIR investigations on the infected system.

Emotet unistallation

The likely reason why Emotet isn’t removed immediately is to allow affected parties to run DFIR investigations to discover potentially secondary malware that was deployed via Emotet.

From our understanding the sinkholing and “uninstallation” actions are performed under the auspices of the German Federal Criminal Police (Bundeskriminalamt (BKA)), hence, the sinkhole IP addresses are owned by German ISP Deutsche Telekom.

What will happen next?

While our mail filters are still detecting sporadic emails containing malicious Emotet documents, these are likely emails that had still been lurking in queues either of the Emotet spambots or email systems and are just now being delivered even though the Emotet botnet infrastructure has been disrupted.

Emotet malspam histogram

We expect that these last drips of Emotet malspam dripping out of the dying Emotet botnet to dry out over the next days and weeks and if the takedown is successful stop entirely.

While there is always a chance that a botnet can regroup after a disruption (see TrickBot), this, however, seems unlikely in this case as not just the Tier 1 C2 proxy servers have been disrupted (as was the case with the disruption of the TrickBot botnet), but – from our information – also the Tier 2 C2 server, i.e., the real C2 server, to which the Tier 1 C2 proxy servers only relayed the traffic to, have been disruption as well.

Who will fill the void?

Emotet constituted around 20% of the malicious email traffic processed by Hornetsecurity. It distributed malware by other threat actors. While a successful takedown will mean no more Emotet malspam, it likely won’t mean a decrease in malspam, as other threat actors will try to fill the void and take over the existing customer base of Emotet’s malware-as-a-service (MaaS) operation.

One strong contender to fill the void generated by Emotet’s disruption is QakBot10. Last year QakBot added email conversation thread hijacking5 to its arsenal, i.e., like Emotet it steals emails from victims and crafts no tailored malspam by replying to existing email conversation threads. QakBot has also been observed loading other malware, such as ZLoader.8 In addition to that, QakBot’s XLM macro based malicious documents7 often have a lower detection rate then Emotet’s VBA macro base malicious documents. Thus, fulfilling all requirements a criminal would have towards an Emotet replacement.

Conclusion and Countermeasures

We congratulate all participating parties and hope for a successful longterm takedown of Emotet.

While Emotet itself may be inoperable, other threats Emotet has previously loaded such as TrickBot6, QakBot7, or Zloader8 remain active and could still deploy ransomware such as Ryuk and Egregor. If the authorities inform you of an Emotet infection you must also clean up these possible secondary infects to mitigate the complete threat.

In case the Emotet botnet can recover, Hornetsecurity’s Spam and Malware Protection, with the highest detection rates on the market, will again, as before the disruption, detect and quarantine malicious Emotet documents.


Indicators of Compromise (IOCs)


These are the IPs used by the German Federal Criminal Police (Bundeskriminalamt (BKA)) to sinkhole Emotet.



This is the hash of the program distributed by the German Federal Criminal Police (Bundeskriminalamt (BKA)) to remove Emotet on 2021-04-25 at 12:00.

MD5 Description
9a062ead5b2d55af0a5a4b39c5b5eadc Emotet “uninstaller”
SolarWinds SUNBURST backdoor assessment

SolarWinds SUNBURST backdoor assessment

Executive Summary

  • FireEye discovered a global supply chain attack trojanizing the SolarWinds Orion Platform with a backdoor that FireEye named SUNBURST.
  • Affected versions: SolarWinds Orion Platform versions 2019.4 HF 5, 2020.2 (with no hotfix installed), 2020.2 HF 1
  • Fixed version: SolarWinds Orion Platform version 2020.2.1 HF 2
  • While the trojanized SolarWinds Orion Platform versions have been spread widely to public and private organizations around the world, current information indicates that the SUNBURST backdoor was used for espionage by a nation state and only used to infiltrate a select set of victims. Other victims that installed the trojanized SolarWinds Orion Platform versions are collateral damage.
  • To figure out if you are affected (beyond checking installed SolarWinds Orion Platform versions) check DNS logs for queries to avsvmcloud[.]com or .digitalcollege[.]org (including subdomains!).
  • Hornetsecurity is not affected. Hornetsecurity does not use SolarWinds products.
  • Because this is an ongoing global incident check the linked resources for up-to-date IoCs and information.


On 2020-12-13 FireEye disclosed a backdoor in updates of the SolarWinds Orion Platform. Affected organizations should update to the fixed version immediately.

The backdoor is part of a global espionage operation and used to access government and high profile private company networks.

Hornetsecurity assessed its own situation and is not affected.


The SolarWinds Orion Platform is the market leader for network monitoring platforms with SolarWinds having over 275.000 customers in 190 countries and providing network monitoring for 400 of the Fortune 500, the US government and other high profile organizations.

On 2020-12-13 FireEye disclosed that the SolarWinds Orion Platform updates between 2020-03-01 and 2020-06-01 have been trojanized with what they called the SUNBURST backdoor.3 Previously on 2020-12-08 FireEye disclosed a breach of its own organization,2 for which it later identified the trojanized SolarWinds Orion Platform update as the intrusion vector.

FireEye attributes this intrusion to an yet unknown threat actor they are tracking as UNC2452. While many media outlets report this intrusion as attributed to APT29, we believe this to be incorrect as APT29 is threat actor designator by FireEye themselves but yet they have not attributed it directly to APT29, yet.

On 2020-12-14 SolarWinds has published a security advisory1 regarding the matter.

Technical Analysis

The backdoor is in SolarWinds.Orion.Core.BusinessLayer.dll of the SolarWinds Orion Platform software installation. After installation the backdoor waits a randomly selected amount between 12 to 14 days before executing its malicious code. It tries to establish C2 communication using a domain name generation algorithm (DGA) to <ENCODED VICTIM HOSTNAME>.appsync-api.{eu,us}-{west,east}-{1,2}.avsvmcloud[.]com. The <ENCODED VICTIM HOSTNAME> subdomain part contains the victims encoded hostname. It can be decoded using a tool provided by RedDrip7.7

Subdomain records corresponding to victim hostnames targeted by the intrusion received a CNAME DNS response redirecting them to one of the C2 domains. Victims not targeted did not receive a dedicated CNAME.6 Even though this is a large scale supply chain attack, current information indicates that the purpose behind the intrusion is espionage conducted by a nation state. This means that while (according to SEC filings by SolarWinds8) around 18,000 victims installed the compromised updates, only a very small fraction was actually the target of this attack, the rest is collateral damage.

On targeted organizations, the backdoor is used as a beach head into the organization’s network, by installing the TEARDROP and BEACON (from Cobalt Strike framework) malware to further infiltrate the network.

Conclusion and Countermeasures

Unlike the supply chain attack against the Ukrainian tax accounting package M.E.Doc, which resulted in the 2017 global NotPetya incident, this intrusion’s goal was espionage. Hence only networks of selected targets were intruded via the SUNBURST backdoor planted through the compromised SolarWinds Orion Platform software.

Organisations that have installed an affected SolarWinds Orion Platform version should treat all hosts monitored by the SolarWinds Orion Platform as compromised, identify all threat actor-controlled accounts and infrastructure within the organization and remove them, and only then rebuild the SolarWinds Orion Platform installation. Organizations with elevated protection requirements can follow the guidance in the DHS Emergency Directive 21-014 (obviously without reporting to CISA, unless the organization is part of the US government).

A good starting point to identify threat actor activity is searching for the IoCs provided by FireEye3,5 in DNS logs. In case DNS queries to one of the <ENCODED VICTIM HOSTNAME>.appsync-api.{eu,us}-{west,east}-{1,2}.avsvmcloud[.]com subdomains are found, you can use the SunBurst DGA Decoder provided by RedDrip77 to figure out which hostname in your network ran the SUNBURST backdoor code. In case you find CNAME replies to these DNS queries, this means in addition to running the backdoor code, the threat actors are/were interested in the host and elevated the connection to a full C2 connection. In the later case, we recommend contacting a competent incident response provider immediately.

We applaud our colleagues from FireEye for their thorough investigations.



Indicators of Compromise (IoCs)

For a full list of IoCs and detection signatures, please see the countermeasures published by FireEye:


  • .avsvmcloud[.]com
  • .digitalcollege[.]org

Known indicators as of 2020-12-16 only! Please, check linked resources for up-to-date information.

QakBot reducing its on disk artifacts

QakBot reducing its on disk artifacts


QakBot has been updated with more evasion techniques. QakBot’s configuration is now stored in a registry key instead of a file. The run key for persistence is not permanently present in the registry but only written right before shutdown or reboot, and deleted immediately after QakBot is executed again. QakBot’s executable is also not stored permanently on the file system anymore, but similarly to the run key registry entry, dropped onto the file system before reboots and deleted afterwards. This way security software can only detect QakBot artifacts on disk, right before system shutdown, and shortly after system boot. However, at that time security software itself is shutting down and booting up, hence may not detect QakBot’s new persistence method.

Other changes include dynamic just-in-time decoding and destruction of strings at runtime. So any string used in the malware is only decoded at runtime into memory only and destroyed right afterwards.

The delivery method for the observed QakBot campaigns identified via the regular expression pattern of abc[0-9]+ is still XLM macro documents as reported previously.


QakBot (also known as QBot, QuakBot, Pinkslipbot) has been around since 2008. It is distributed via Emotet, i.e., Emotet will download QakBot onto victims that are already infected with Emotet but it is also distributed directly via email. To this end, it uses email conversation thread hijacking in its campaigns1, i.e., it will reply to emails that it finds in its victim’s mailboxes. QakBot is known to escalate intrusions by downloading the ProLock ransomware2 or lately the Egregor ransomware.

The observed QakBot campaigns identified by campaign ID abc use XLM macro documents for infection. We previously reported on their low detection.3

An overview of the current chain of infection used by the QakBot campaign with identifiers following the regular expression pattern of abc[0-9]+ can be seen in the following flow graph.

QakBot abc chain of infection

Technical Analysis

In the following analysis we briefly analyze the infection chain of QakBot after being downloaded and launched by the malicious Excel document.

QakBot infection process tree


QakBot uses various evasion techniques to avoid detection by anti-virus software.

PE header manipulation

We observed some QakBot DLLs with a manipulated PE header. The message text This program cannot be run in DOS mode. has been altered.

QakBot PE header manipulation

This seems like an attempt to circumvent some static detection rules matching for this message in the legacy MS-DOS stub of PE binaries.

Code signing

First, the initial downloaded and executed DLL is signed with a (at the time the analyzed sample was distributed) valid code signing certificate.

$ chktrust 904400.jpg
Mono CheckTrust - version
Verify if an PE executable has a valid Authenticode(tm) signature
Copyright 2002, 2003 Motus Technologies. Copyright 2004-2008 Novell. BSD licensed.

WARNING! 904400.jpg is not timestamped!
SUCCESS: 904400.jpg signature is valid
and can be traced back to a trusted root!

The signing CA is Sectigo and the organization is given as Aqua Direct s.r.o., which is an existing company.

$ osslsigncode verify 904400.jpg 
Current PE checksum   : 00091021
Calculated PE checksum: 00091021

Message digest algorithm  : SHA1
Current message digest    : 632DCB214EE9FB08441C640D240F672A7ABA6EB1
Calculated message digest : 632DCB214EE9FB08441C640D240F672A7ABA6EB1

Signature verification: ok

Number of signers: 1
    Signer #0:
        Subject: /C=CZ/postalCode=619 00/L=Brno/street=\xC5\xBDelezn\xC3\xA1 646/8/O=Aqua Direct s.r.o./CN=Aqua Direct s.r.o.
        Issuer : /C=GB/ST=Greater Manchester/L=Salford/O=Sectigo Limited/CN=Sectigo RSA Code Signing CA

Number of certificates: 4
    Cert #0:
        Subject: /C=CZ/postalCode=619 00/L=Brno/street=\xC5\xBDelezn\xC3\xA1 646/8/O=Aqua Direct s.r.o./CN=Aqua Direct s.r.o.
        Issuer : /C=GB/ST=Greater Manchester/L=Salford/O=Sectigo Limited/CN=Sectigo RSA Code Signing CA
    Cert #1:
        Subject: /C=GB/ST=Greater Manchester/L=Salford/O=Comodo CA Limited/CN=AAA Certificate Services
        Issuer : /C=GB/ST=Greater Manchester/L=Salford/O=Comodo CA Limited/CN=AAA Certificate Services
    Cert #2:
        Subject: /C=US/ST=New Jersey/L=Jersey City/O=The USERTRUST Network/CN=USERTrust RSA Certification Authority
        Issuer : /C=GB/ST=Greater Manchester/L=Salford/O=Comodo CA Limited/CN=AAA Certificate Services
    Cert #3:
        Subject: /C=GB/ST=Greater Manchester/L=Salford/O=Sectigo Limited/CN=Sectigo RSA Code Signing CA
        Issuer : /C=US/ST=New Jersey/L=Jersey City/O=The USERTRUST Network/CN=USERTrust RSA Certification Authority


It is unknown whether the certificate was obtained from Sectigo by giving false information, the certificate was stolen from Aqua Direct s.r.o., or whether the certificate was obtained from Sectigo by giving stolen information from Aqua Direct s.r.o..

QakBot is known to steal victim emails and use them in future malspam campaigns. So it is likely that they also use stolen victim data to obtain code signing certificates. However, the actors behind QakBot can also buy the code signing certificate from a (malicious) third party.

Strings only decoded at runtime

QakBot will decode its strings only at runtime into memory. After usage the decoded strings are removed from memory again.


QakBot uses CreateToolhelp32Snapshot and Process32{First,Next}W to enumerate the running processes.

QakBot enumerating processes API log

It checks for the following processes:

  • CcSvcHst.exe
  • avgcsrvx.exe
  • avgsvcx.exe
  • avgcsrva.exe
  • MsMpEng.exe
  • mcshield.exe
  • avp.exe
  • kavtray.exe
  • egui.exe
  • ekrn.exe
  • bdagent.exe
  • vsserv.exe
  • vsservppl.exe
  • AvastSvc.exe
  • coreServiceShell.exe
  • PccNTMon.exe
  • NTRTScan.exe
  • SAVAdminService.exe
  • SavService.exe
  • fshoster32.exe
  • WRSA.exe
  • vkise.exe
  • iserv.exe
  • cmdagent.exe
  • ByteFence.exe
  • MBAMService.exe
  • mbamgui.exe
  • fmon.exe

QakBot will set specific bits in a bit mask for each running process it finds. Depending on the resulting bit mask the further infection path is altered, e.g., if avp.exe has been encountered. QakBot will later inject its code into mobsync.exe instead of explorer.exe. Because the searched process names are related to security solutions, we believe that this way QakBot tailors its execution path to evade detection by specific vendors.

Then in another loop, again using CreateToolhelp32Snapshot and Process32{First,Next}W, it checks for:

  • srvpost.exe
  • frida-winjector-helper-32.exe
  • frida-winjector-helper-64.exe

If it detects any of those processes the execution flow will run into a loop continuously calling WaitForSingleObject(handle, 0x1fa) on a handle previously generated via CreateEvent(NULL, FALSE, FALSE, ...), i.e., it runs in an infinite loop.

Device drivers

Next, QakBot uses SetupDiGetDeviceRegistryPropertyA (querying properties SPDRP_DEVICEDESC and SPDRP_SERVICE) to check for device drivers containing the following strings:

  • VBoxVideo
  • Red Hat VirtIO
  • QEMU
  • A3E64E55_pr

We believe the search for A3E64E55_pr is used to detect an artifact of the ANY.RUN sandbox.4 Alternatively, but unlikely, it could be used to detect an artifact of the long ago defunct xCore Complex Protection AV solution using a similar driver with the name A3E64E55_pr.sys.

If it detects any of those device drivers the execution flow will run into the same infinite loop continuously calling WaitForSingleObject(handle, 0x1fa) on a handle previously generated via CreateEvent(NULL, FALSE, FALSE, ...), as previously mentioned.

Process injection

QakBot starts C:\Windows\SysWOW64\explorer.exe in suspended state and injects a DLL into it using CreateProcessInternalW, NtMapViewOfSection, NtAllocateVirtualMemory, WriteProcessMemory, memcpy, NtProtectVirtualMemory and NtResumeThread.

QakBot process injection into explorer.exe API log

The injected DLL can be extracted via PE-sieve5 or other tools for simplyfied further analysis.

Injected QakBot DLL extracted with PE-sieve

Depending on whether the previous process enumeration yielded results on the list, QakBot will inject into mobsync.exe (e.g., in case a avp.exe process is found running) instead of explorer.exe. But for simplicity we will only follow the explorer.exe process injection path we observed in our analysis environment.

C2 communication

After avoiding detection, the injected QakBot code within explorer.exe will start communicating with the C2 servers.

QakBot DLL in explorer.exe C2 communication

Like in previous versions of QakBot the C2 IP list is stored RC4 encrypted in resource section 311. The first 20 bytes of the section contains the RC4 key with which the rest of the section is decrypted. The first 20 bytes of the decrypted data will contain the SHA1 sum calculated over the rest of the decrypted data. It is used as a verification for correct decryption. Unlike in previous version, the C2 list is now stored in binary form and not as ASCII text anymore.

QakBot C2 list storage

For details on how to extract the C2 list and QakBot’s configuration see the Python3 script in the appendix. The input to the script is the path to the DLL that QakBot injected into explorer.exe, which we previously extracted via PE-sieve5.

QakBot configuration extraction with Python3 script

The configuration is stored using the same RC4 encryption scheme in resource section 308. In it we can see the bot and/or campaign ID abc103 that is associated with the analyzed sample. It is still stored in plain ACSII text. For each campaign the number is increased by one. This allows the operators behind QakBot to keep track to which campaign each victim connecting to their C2 server belongs to. Another currently observed identifier is tr02. This identifier, however, stayed the same over multiple malspam campaigns.

Via the C2 connection the operators behind QakBot can remote control the malware and deploy additional malicious modules.

QakBot will not store its configuration and C2 list on disk anymore. It will use the registry for storage.

QakBot using registry for configuration storage


The previous QakBot version used to overwrite its initial executable with a copy of cmd.exe. This version will overwrite the portion of the initially downloaded DLL after the PE header with zeros.

Here is the entropy of the QakBot DLL as downloaded.

QakBot DLL entropy before being overwritten

The zeroing of data after the header can be clearly seen when comparing the previous plot against a plot of the DLL file after wiping.

QakBot DLL entropy after being overwritten


The persistence mechanism of QakBot has also changed. While it still uses a run key registry entry under HKCU\Software\Microsoft\Windows\CurrentVersion\Run, this key is only set right before the system is shutdown, rebooted or put to sleep. The corresponding DLL is also only dropped to disk right before shutdown, rebooted or sleep.

After the system boots up again, QakBot is started via the run key. The execution tree also starts via regsvr32.exe -s ... like the initial execution from Excel. QakBot follows the same steps as previously outlined resulting in process injection into explorer.exe.

QakBot process tree after reboot

QakBot will then delete the run key registry entry and delete the DLL it dropped to disk prior to the reboot.

QakBot cleaning persistence

This way QakBot’s persistence can not be detected at runtime.


While we have previously reported on QakBot deliverying the ProLock ransomware,2 latests reports indicated that QakBot is now used to deliver the Egregor ransomware. We previously reported on the Egregor ransomware as part of an article on ransomware leaksites6 in which we explain the practice of ransomware operators stealing their victims data before encrypting it to extort them not only with decryption but also public release of the stolen data.

Conclusion and Countermeasures

From our analysis we can conclude that QakBot is trying to avoid persistent file artifacts. In previous version the configuration and QakBot executable were permanently stored on disk. This made it easy for security tools to detect them. The new version tries to avoid permanently leaving its artifacts on disk. While QakBot is not going fully fileless, it new tactics will sure lower its detection.

But even though QakBot has changed, the delivery mechanism behind the QakBot “abc[A-Z]+” campaign did not. Hence, an infection by this threat actor can be successfully prevented by blocking the initial emails.

Hornetsecurity’s Spam and Malware Protection, with the highest detection rates on the market, already detects and blocks the outlined threat. Hornetsecurity’s Advanced Threat Protection extends this protection by also detecting yet unknown threats.


Indicators of Compromise (IOCs)


The hashes of the analyzed QakBot samples are:

MD5 Filename Description
6bc0584f6cbb74714add1718b0322655 904400.jpg QakBot DLL as downloaded by XLM macro
e23bc27212f61520cfb130185d74cfb1 26e0000.dll Extracted QakBot DLL


The tactics and techniques used by QakBot as defined by the MITRE ATT&CK framework are as follows:

Tactic Technique
TA0001 – Initial Access T1566.001 – Phishing: Spearphishing Attachment
TA0001 – Initial Access T1566.002 – Phishing: Spearphishing Link
TA0002 – Execution T1027 – Obfuscated Files or Information
TA0002 – Execution T1204.002 – User Execution: Malicious File
TA0003 – Persistence T1547.001 – Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder
TA0004 – Privilege Escalation T1053.005 – Scheduled Task/Job: Scheduled Task
TA0005 – Defense Evasion T1027.002 – Obfuscated Files or Information: Software Packing
TA0005 – Defense Evasion T1055 – Process Injection
TA0005 – Defense Evasion T1055.012 – Process Injection: Process Hollowing
TA0005 – Defense Evasion T1070 – Indicator Removal on Host
TA0005 – Defense Evasion T1497.001 – Virtualization/Sandbox Evasion: System Checks
TA0006 – Credential Access T1003 – OS Credential Dumping
TA0006 – Credential Access T1110.001 – Brute Force: Password Guessing
TA0006 – Credential Access T1555.003 – Credentials from Password Stores: Credentials from Web Browsers
TA0011 – Command and Control T1071.001 – Application Layer Protocol: Web Protocols
TA0011 – Command and Control T1090 – Proxy
TA0011 – Command and Control T1090.002 – Proxy: External Proxy


Qakbot configuration extraction Python3 script

import sys
import pefile
from arc4 import ARC4

pe = pefile.PE(sys.argv[1])
c2list = []
for entry in pe.DIRECTORY_ENTRY_RESOURCE.entries:
    for e in
        n =
        data = pe.get_data([0].data.struct.OffsetToData,[0].data.struct.Size)
        data = ARC4(data[:20]).decrypt(data[20:])[20:]
        if n == '311':
            for i in range(1,len(data),7):
                c2 = list(data[i:i+6])
                c2list.append("%d.%d.%d.%d:%d" % (c2[0],c2[1],c2[2],c2[3],(c2[4]<<8)+c2[5]))
        elif n == '308':
            config = data.decode().split()
print("# QakBot Config\n\n```\n" + "\n".join(config) + "\n```\n")
print("# QakBot C2\n\n```\n" + "\n".join(c2list) + "\n```\n")