There are new articles available, click to refresh the page.
Before yesterdayNVISO Labs

Building an ICS Firing Range – Part 2 (Defcon 29 ICS Village)

22 September 2021 at 11:06

As discussed in our first post in the series about our ICS firing range, we came to the conclusion that we had to build a lab ourselves. Now, this turned out to be a quite tricky task and in this blog post I am going to tell you why: which challenges we faced and which choices we made on our way to building our very own lab.
This was a rather long project and involved quite some steps. So to structure this post, I will guide you through the process of how we designed our lab by dividing it into the tasks we worked on in chronological order.

Requirements Analysis

Well, we knew that we were going to build this lab but we needed more information about the exact requirements it should meet so we could focus on those specifically. During internal discussions and meetings with the client we worked out this list of initial, key requirements:

  1. The lab shall feature IT and OT components that represent a realistic bridge-operation scenario.
  2. The lab shall be mobile so it can be transported, set up and worked with on different sites.
  3. The lab shall be extensible: scenarios and both hardware and software components can be added in the future.

These requirements were intentionally left rather broad so that we could work out different feasible concepts for individual challenges and decide with the client which way to go. This approached allowed us to keep in close contact to the client and make sure that we meet their needs.

Designing an ICS Firing Range

In order to build great things, you will need great plans. In this phase, we worked out said plans, starting with our very first concept.

1. The First Concept

Once we knew our key requirements, we started doing our research on the topic of operating bascule bridges. This was certainly easier said than done: it turned that publicly available information about critical infrastructure, such as bridges, was not that easy to find.
Eventually we found a very good resource, the “Bridge Maintenance Reference Manual” provided by the Florida Department of Transportation (FDOT). This manual was a very good find since it detailed the general structure of bascule bridges and explained the most relevant components. Using this, we developed our first, simplified concept:

First 2D Concept of our Bridge Operation Scenario

It features the core components of bascule bridges:

  • Structural components such as the leaves, counterweights and pits (bottom part of the bridges)
  • Drives that move the actual bridge leaves, road barriers and counterweights-locks
  • LEDs that indicate STOP/GO signals for maritime and road traffic
  • An alarm (buzzer) that is turned on and beeps while the leaves are moving
Simple Blender 3D Mock-Up

We translated this into a first, early 3D model in Blender to get an idea of the dimensions and looks. While it was very much simplified, it allowed up to work out some ideas about shapes and placement of components.

This way we found out that a modular setup might provide much needed flexibility for assembly and maintainance: the pits would provide a strong foundation to mount the remaining components onto while the upper part (shown in green-ish color in the picture) would be made of two halves that were set atop the pit. Resting inside the pit there would be a large stepper motor that drove a pinion gear, which in turn drove a rack that is install underneath the bridge leaf.

Satisfied with this concept, we moved on to working on the underlying infrastructure of the lab.

2. Blocking out the Infrastructure

From the start we knew that it would take a good number of systems and networks to represent a somewhat realistic ICS environment: we expected a bridge operator to have an enterprise network that their regular office workstations are connected to, which are probably domain joined. Furthermore, they would have a SCADA network that contains operator workstations for monitoring and controlling the remote bridge-sites, historians to record operational data, and engineering workstations to program PLCs and HMIs. These networks would be routed via a public demilitarized zone (DMZ) over the internet to a remote bridge site. Also, all of these networks would have their own subnets and feature a router that allows adequate routing between the networks and a firewall that specifies individual rules for incoming and outgoing traffic (with a DENY ALL default rule). We decided that virtualizing these machines and networks would be a good compromise between the resources demanded to implement them and the physical space they would take up.

Presumed Local Network Infrastructure of a Bridge Operator

In addition to the IT infrastructure, we also designed the OT part. We intended the diagram below to somewhat represent the lower levels of the Purdue model: There are three substations that represent individual cells for traffic lights, gates and leaf lifting operation. They contain sensors and drives (our level 0 devices, e.g. limit switches and motors) which are controlled by individual PLCs per cell. These PLCs are instructed by one central PLC that is connected to the SCADA network.

Presumed OT Environment of our Bridge Site Scenario

In addition to these rather traditional OT components, our client requested us to include CCTV functionality in the lab. For this we planned to use Raspberry Pis with PiCams.
This network design represented a sufficiently realistic ICS network and allowed for future additions. Time to move on!

3. Figuring Out Which OT Hardware to Use

Now that we knew what things we wanted to interact with physically (those being mainly motors and LEDs) and how to connect them to our lab networks, we started doing our research on suitable OT hardware.

Naturally, we were soon overwhelmed by the sheer amount of devices to choose from: there were plenty of manufacturers that offered loads of different devices for a variety of different use-cases, requirements and budgets with an equally wide variety of different features, dependencies and compatibilities.

Confronted with this challenge (and severely lacking expertise in building OT environments), we decided to make assumptions that helped us trimming down the selection of manufacturers and devices and making educated decisions:

  • We would assume that, for a single operation site, one would stick to devices of one single manufacturer. This allowed us to largely ignore cross-manufacturer-compatibility. We chose SIEMENS for their significant European market-share in ICS hardware.
  • In order to reduce the complextity of building and interconnecting the OT devices, we decided to implement communication via ethernet exclusively and ignore other communication media and interfaces.
  • To represent a realistic and “historically grown” (e.g. occasionally updated and maybe upgraded across decades) operation site, we would use devices of varying EOL (end of life). We decided to include legacy PLCs (S7-300), all-rounder “standard” PLCs (S7-1200), modern high-end PLCs (S7-1500) and standard HMIs (TP700).
Us (left) when we faced dozens datasheets of SIEMENS, ABB and Mitsubishi devices.

At this point, all that was left to do now was to figure out which PLC to use for which task. This required digging through quite some datasheets of the abovementioned PLCs, mainly to find out how many and what digital inputs and outputs the PLCs feature. For example we learned that, to control stepper motors, we needed to create pulse-signals (in our case Pulse-Train-Outputs, PTOs) of up to 100kHz. During our research, a rather cheap signal-board for the S7-1200 turned up that would generate PTOs of up to 200kHz. We ended up using the S7-1200 PLCs to drive the leaves and barriers, the S7-300 to control LEDs and the buzzer and the S7-1500 for orchestration and outbound communication to the virtualized IT environment.

4. Our Vision

With all this information we worked out there, we came up with a vision of what we wanted our lab to look like:

3D concept of the mobile lab

It’s essentially an aluminium frame on wheels, featuring a 3D printed bridge on-top and a steelplate put inside it vertically. The OT components are mounted onto the front-facing side of the steel-plate and the virtualization server running the IT systems and networks is located in the back. The black panels are made of wood and hide the power distribution and the server. It may be hard to pick up visually, but there are acryllic glass panels on the sides and the front to provide a look inside.

With this vision in mind, we set out to build it!

We are going to cover this in the next blog post about our ICS firing range – Stay tuned!

MITRE ATT&CK turned purple – Part 1: Hijack execution flow

6 October 2020 at 10:42

The MITRE ATT&CK framework is probably the most well-known framework in terms of adversary emulation and by extent, red teaming.
It features numerous TTPs (Tactics, Techniques, and Procedures) and maps them to threat actors. Being familiar with this framework is not only benefiting the red team operations but the blue team operations as well! To create the most secure environment for your enterprise, it is imperative that you know what threat actors are using and how to defend against it.

Having a 100% coverage of MITRE ATT&CK is probably not feasible, by choosing which TTPs are most relevant for your environment however, you can start setting up baseline defenses and expand from there. This will help you mature your enterprise’s security posture significantly. We at NVISO are using the framework in our daily operations and have therefore decided it was time to combine the knowledge we have in-house from both our blue and red teams to provide insight into how these techniques can be leveraged from an offensive point of view AND how to prevent (or at least detect) the technique from a defensive point of view. In our first blogpost of the series, we decided to cover T1574 – Hijack execution flow.

Offensive point of view: Leveraging execution flow hijacking in red team engagements and threat emulations

Execution flow hijacking usually boils down to the following: identifying a binary present on the system that is missing dependencies (typically a DLL) and providing said missing dependency. Luckily for us, the good people at Microsoft have gifted us with a tool suite called sysinternals, which we will happily leverage to identify missing dependencies.

It should be noted that casually dropping sysinternals tools on a target environment is very poor operational security and probably won’t do you much good anyway. For most of the tooling (if not all), you will need to have administrative privilege on the machine you are running it from. Therefore it is much more interesting to either have some “educated” knowledge beforehand on what tools are living on your targeted environment. Alternatively (and simpler), you can hijack a program you know will most likely be installed. Some fine examples of this would be Teams, Chrome, Firefox, …

We can identify missing dependencies using a tool that was created by our friends over at SpectreOps called “DLLHijackTest”. This tool needs an extract from sysinternals’ Process Monitor and will attempt to verify if the processes identified are indeed hijackable, as not all missing DLLs are getting loaded in the same way (calling DLLMain) at execution time.

Let’s identify some nice missing dependencies on our trusted Internet Explorer using the following Process Monitor filter:

After this filter is applied, let’s open Internet Explorer and check our process monitor light up like a Christmas tree:

Now we can export this as a CSV file by going to file -> save and choosing CSV as an output format.

Everything we need now is a valid hijack, which we can test using the aforementioned PowerShell script from SpectreOps:

Get-PotentialDLLHijack -CSVPath "G:\testzone\DLLHijackTest-master\InternetExplorer\IE.CSV" -MaliciousDLLPath "G:\testzone\DLLHijackTest-master\x64\Release\DLLHijackTest.dll" -ProcessPath "C:\Program Files\Internet Explorer\iexplore.exe"

What happens now is the following chain of steps:

  • A DLL gets dropped in the location of the application and is named after a missing dependency
  • The process gets launched
  • If the DLLMain method is called, the DLL will write its own path into an arbitrary location that you need to replace in the source code of the SpectreOps project.
  • The process terminates

This repeats until the entire CSV is parsed. If the application has a vulnerable Hijack, an output file will be created at the location you hardcoded.

In the case of Internet Explorer this is indeed the case:

We have successfully fuzzed Internet Explorer and identified four missing DLLs that are in fact loaded and their DLLMain is executed.

Note: for this blogpost, IE was chosen as a PoC. You will need admin rights to write in C:\Program Files\ so for red team ops, this is a pretty weak candidate, unless you will abuse this for persistence reasons.

Now all that is left to do is create a DLL that executes your payload, name it one of the missing dependencies identified in the results file and drop it on disk.
Every time Internet Explorer will be opened, your DLL payload will fire.

Defensive point of view: Preventing and detecting execution flow Hijacks

When looking through the public Sigma repository, it is noticeable how only a few rules to detect this technique exist:
Some 20 exist, of which two are authored by NVISO: Maxime Thiebaut’s “Windows Registry Persistence COM Search Order Hijacking”, and Bart Parys and yours truly’s “Fax Service DLL Search Order Hijack”. All of these only cover specific instances of this technique. The reason for this is very simply that it is next to impossible to write a rule that covers the many options the red team/adversary has to exploit this technique. Proper detection is achievable however, by getting a baseline of your environment and alerting on any DLLs/EXEs loaded from unexpected locations.

While Sysmon can be configured to log ImageLoaded events as event ID 7, this is disabled by default because of the massive amount of logs it would generate.
To help with triaging you can use a PowerShell script to semi-automatically generate a Sysmon config that excludes all known-good DLLs that are loaded.
See the example below for one such (basic) PowerShell script:

# Run this script repeatedly to automatically add the newly used DLLs to the exclusions.
# Do a reboot after installing the "base" Sysmon config to log all the DLLs loaded in the Windows boot process.

# Modify to point to the Sysmon executable.
$SYSMON_EXECUTABLE = "C:\Sysmon\Sysmon64.exe"
# Modify to point to the new config. (Will be overwritten by a run of the script!)
$CONFIG_FILE = "C:\Sysmon\config.xml"

Function Get-DLLs {
    # Using a HashSet to avoid having to filter for duplicates
	$dlls = New-Object System.Collections.Generic.HashSet[String]
    try {
        # Retrieve all Sysmon ImageLoaded events
	    $events = Get-WinEvent -LogName "Microsoft-Windows-Sysmon/Operational" -FilterXPath "Event[System[(EventID=7)]]"
        # Extract the ImageLoaded from the events' Message fields
		$events.Message | ForEach-Object -Process {
			$loaded = (Select-String -InputObject $_ -Pattern "ImageLoaded: (.*)").Matches.Groups[1]
			$dlls.add($loaded) | Out-Null
	} catch {}
    # Sort before returning for consistent & managable output
	$dlls | Sort-Object

Function Export-SysmonConfig {
	$XMLHeader = @"
<Sysmon schemaversion=`"4.22`">
        <RuleGroup name="" groupRelation=`"or`">
            <ImageLoad onmatch=`"exclude`">

	$XMLTrailer = @"
    # To indent <ImageLoaded> for readability.
    $Offset = "                "
	Function Format-Exclusion {
		$dll = $dll.trim()
		$Offset + "<ImageLoaded condition=`"is`">$dll</ImageLoaded>`n"
	$XMLConfig = $XMLHeader
	$XMLConfig += $Offset + "<ImageLoaded condition=`"is`">$SYSMON_EXECUTABLE</ImageLoaded>`n"
	$XMLConfig += $Offset + "<ImageLoaded condition=`"begin with`">C:\Windows\System32\</ImageLoaded>`n"
	$XMLConfig += $Offset + "<ImageLoaded condition=`"begin with`">C:\Windows\SysWOW64\</ImageLoaded>`n"
	foreach ($dll in $dlls) {
		$XMLConfig += Format-Exclusion $dll
	$XMLConfig += $XMLTrailer

$dlls = Get-DLLs
Export-SysmonConfig $dlls | Tee-Object -FilePath $CONFIG_FILE
# Install the new config to lower the amount of logs generated.
Start-Process -FilePath $SYSMON_EXECUTABLE -ArgumentList @('-c', $CONFIG_FILE)

Be sure to only execute this on a known-good device, such as a freshly imaged laptop or a new VM:
If you use a potentially compromised device to generate this, there is a chance of excluding a malicious DLL that can then remain completely undetected in your environment.
You will need to run this every time a piece of software gets updated, as the loaded DLLs may change (new DLLs added, older DLLs no longer relevant) depending on the version of the software.

Note that to limit the amount of exclusions the config needs, the C:\Windows\System32\ and C:\Windows\SysWOW64\ directories are excluded in their entirety by the script.
You should set up a SIEM alert for Sysmon event ID 11 (FileCreate) if the TargetFileName starts with either of these directories.
A Sigma rule to detect this looks as follows:

title: DLL Created In Windows System Folder
id: ddc5624d-4127-4787-8cd9-e0943ebb10e8
status: experimental
description: |
  Detects new DLLs written to the Windows system folders.
  Can be used to gain persistence on a system by exploiting DLL hijacking vulnerabilities.
  - https://blog.nviso.eu/2020/10/06/mitre-attack-turned-purple-part-1-hijack-execution-flow
  - attack.t1574.001
  - attack.t1574.002
author: NVISO
date: 2020/10/05
  product: windows
  service: sysmon
    EventID: 11
      - 'C:\Windows\System32\'
      - 'C:\Windows\SysWOW64\'
    TargetFilename|endswith: '.dll'
  condition: selection
  - Driver installations
  - Some other software installations 
level: high

If your configuration is correct, you should not generate any Sysmon event ID 7 for legitimate DLLs and you can simply alert on any occurrence of the event as potentially malicious.
Any DLLs dropped in the excluded directories get flagged by the Sigma rule for proper coverage.
Even if your Sysmon config is not covering 100% of the legitimately loaded DLLs, the volume of generated events should be low enough to be able to be workable, and additional filtering can also be done using a SIEM or automated in a SOAR solution, for example.
With sufficient time, your detection capabilities for this technique should be tuned finely enough as to not generate many false positives.

Detection for this technique is obviously not cut-and-dry but it is possible to have very good coverage, provided your blue team gets a proper testing environment to improve their detection capabilities.

Prevention of this technique works very similar to detection:
One can write AppLocker policies to only allow known DLLs to load.
You can create a list of loaded DLLs by setting the policy to audit for several weeks and appending DLLs that were missed by the initial testing to the list of known-good ones before enforcing your policies.

The script and rule in this blogpost are available on our GitHub.


We hope that this blogpost has provided you with actionable information and has given you more insight into leveraging this technique and defending against it.
This was the first blogpost of a recurring series, we hope to see you again when we cover another ATT&CK technique in the near future!
From all of us at NVISO, stay safe!

About the author(s)

  • Jean-François Maes is a red teaming and social engineering expert working in the NVISO Cyber Resilience team. When he is not working, you can probably find Jean-François in the Gym or conducting research. Apart from his work with NVISO, he is also the creator of redteamer.tips, a website dedicated to help red teamers.
    He was also ranked #1 on the Belgian leaderboard of Hack The Box (a popular penetration testing platform).
    You can find Jean-François on LinkedIn and on Hack The Box.
  • Remco Hofman is an intrusion analyst in NVISO’s MDR team, always looking at improving the detection capabilities of the service. A few cups of properly brewed tea help him unwind after a long day’s work.
    You can find him on Twitter or LinkedIn.

Epic Manchego – atypical maldoc delivery brings flurry of infostealers

1 September 2020 at 11:33

In July 2020, NVISO detected a set of malicious Excel documents, also known as “maldocs”, that deliver malware through VBA-activated spreadsheets. While the malicious VBA code and the dropped payloads were something we had seen before, it was the specific way in which the Excel documents themselves were created that caught our attention.

The creators of the malicious Excel documents used a technique that allows them to create macro-laden Excel workbooks, without actually using Microsoft Office. As a side effect of this particular way of working, the detection rate for these documents is typically lower than for standard maldocs.

This blog post provides an overview of how these malicious documents came to be. In addition, it briefly describes the observed payloads and finally closes with recommendations as well as indicators of compromise to help defend your organization from such attacks.

Key Findings (TL;DR)

  • The malicious Microsoft Office documents are created using the EPPlus software rather than Microsoft Office Excel, these documents may fly under the radar as it differs from a typical Excel document;
  • NVISO assesses with medium confidence that this campaign is delivered by a single threat actor based on the limited number of documents uploaded to services such as VirusTotal, and the similarities in payloads delivery throughout this campaign;
  • The payloads that have been observed up to the date of the release of this post, have been, for the most part, so called information stealers with the intention of harvesting passwords from browsers, email clients, etc.;
  • The payloads stemming from these documents have evolved only slightly in terms of obfuscation and masquerading. This is another indication of a single actor who is slowly evolving their technical prowess.


The analysis section below is divided in two parts and refers to a specific link in the infection chain.

Malicious document analysis

In an earlier blog post, we wrote about “VBA Purging”[1], which is a technique to remove compiled VBA code from VBA projects. We were interested to see if any malicious documents found in-the-wild were adopting this technique (it lowers the initial detection rate of antivirus products). This is how we stumbled upon a set of peculiar malicious documents.

At first, we thought they were created with Excel, and were then VBA purged. But closer examination leads us to believe that these documents are created with a .NET library that creates Office Open XML (OOXML) spreadsheets. As stated in our VBA Purging blog post, Office documents can also lack compiled VBA code when they are created with tools that are totally independent from Microsoft Office. EPPlus is such a tool. We are familiar with this .NET library, as we have been using it since a couple of years to create malicious documents (“maldocs”) for our red team and penetration testers.

When we noticed that the maldocs had no compiled code, and were also missing Office metadata, we quickly thought about EPPlus. This library also creates OOXML files without compiled VBA code and without Office metadata.

The OOXML file format is an Open Packaging Conventions (OPC) format: a ZIP container with mainly XML files, and possibly binary files (like pictures). It was first introduced by Microsoft with the release of Office 2007. OOXML spreadsheets use extension .xlsx and .xlsm (for spreadsheets with macros).

When a VBA project is created with EPPlus, it does not contain compiled VBA code. EPPlus has no methods to create compiled code: the algorithms to create compiled VBA code are proprietary to Microsoft.

The very first malicious document we detected was created on 22nd of June 2020, and since then 200+ malicious documents were found over a period of 2 months. The actor has increased their activity in the last weeks, as now we see more than 10 new malicious documents on some days.

Figure 1 – Unique maldocs observed per day

The maldocs discovered over the course of two months have many properties that are quite different from the properties of documents created with Microsoft Office. We believe this is the case because they are created with a tool independent from Microsoft Excel. Although we don’t have a copy of the exact tool used by the threat actor to create these malicious documents, the malicious documents created by this tool have many properties that convince us that they were created with the aforementioned EPPlus software.

Some of EPPlus’ properties include, but are not limited to:

  • Powerful and versatile library: not only can it create spreadsheets containing a VBA project, but that project can also be password protected and/or digitally signed. It does not rely on Microsoft Office. It can also run on Mono (cross platform, open-source .NET).
  • OOXML files created with EPPlus have some properties that distinguish them from OOXML files created with Excel. Here is an overview:
    • ZIP Date: every file included in a ZIP file has a timestamp (DOSDATE and DOSTIME field in the ZIPFILE record). For documents created (or edited) with Microsoft Office, this timestamp is always 1980-01-01 00:00:00 (0x0021 for DOSDATE and 0x0000 for DOSTIME). OOXML files created with EPPlus have a timestamp that corresponds to the creation time of the document. Usually, that timestamp is the same for all files inside the OOXML files, but due to execution delays, there can be a difference of 2 seconds between timestamp. 2 seconds is the resolution of the DOSTIME format.

Figure 2 – DOSTIME difference (left: EPPlus created file)

  • Extra ZIP records: a typical ZIP file is composed of ZIP file records (magic 50 4B 03 04) with metadata for the file, and the (compressed) file content. Then there are ZIP directory entries (magic 50 4B 01 02) followed by a ZIP end-of-directory record (magic 50 4B 05 06). Microsoft Office creates OOXML files containing these 3 ZIP record types. EPPlus creates OOXML files containing 4 ZIP records: it also includes a ZIP data description record (magic 50 4B 07 08) after each ZIP file record.

Figure 3 – Extra ZIP records (left: EPPlus created file)

  • Missing Office document metadata: an OOXML document created with Microsoft Office contains metadata (author, title, …). This metadata is stored inside XML files found inside the docProps folder. By default, documents created with EPPlus don’t have metadata: there is no docProps folder inside the ZIP container.

Figure 4 – Missing metadata (left: EPPlus created file)

  • VBA Purged: OOXML files with a VBA project created with Microsoft Office contain an OLE file (vbaProject.bin) with streams containing the compiled VBA code and the compressed VBA source code. Documents created with EPPlus do not contain compiled VBA code, only compressed VBA source code. This means that:
    • The module streams only contain compressed VBA code
    • There are no SRP streams (SRP streams contain implementation-specific and version-dependent compile code, theire name starts with __SRP_)
    • The _VBA_PROJECT stream does not contain compiled VBA code. In fact, the content of the _VBA_PROJECT stream is hardcoded in the EPPlus source code: it’s always CC 61 FF FF 00 00 00.

Figure 5 – Hardcoded stream content (left: EPPlus created file)

In addition to the above, we have also observed some properties of the VBA source code that hints at the use of a creation tool based on a library like EPPlus.

There are a couple of variants to the VBA source code used by the actor (some variants use PowerShell to download the payload, others use pure VBA code). But all these variants contain a call to a loader function with one argument, a string with the URL (either BASE64 or hexadecimal encoded). Like this (hexadecimal example):

Loader”68 74 74 70 …”

Do note that there is no space character between the function name and the argument: there is no space between Loader and ”68 74 74 70 …”.

This is an indication that the VBA code was not entered through the VBA EDI in Office: when you type a statement like this, without space character, the VBA EDI will automatically add a space character for you (even if you copy/paste the code). The absence of this space character divulges that this code was not entered through the VBA EDI, but likely via a library such as EPPlus.

To illustrate these differences in properties, we show examples with one of our internal tools (ExcelVBA) using the EPPlus library. We create a vba.xlsm file with the vba code in text file vba.txt using our tool ExcelVBA, and show some of its properties.:

Figure 6 – NVISO created XLSM file using the EPPlus library

Figure 7 – Running oledump.py reveals this document was created using the EPPlus library

Some of the malicious documents contain objects that clearly have been created with EPPlus, using some of the example code found on the EPPlus Wiki. We illustrate this with the following example (the first document in this campaign):

Filename: Scan Order List.xlsm
MD5: 8857fae198acd87f7581c7ef7227c34d
SHA256: 8a863b5f154e1ddba695453fdd0f5b83d9d555bae6cf377963c9009c9fa6c9be
File Size: 5.77 KB (5911 bytes)
Earliest Contents Modification: 2020-06-22 14:01:46

This document contains a drawing1.xml object (a rounded rectangle) with this name: name=”VBASampleRect”.

Figure 8 – zipdump of maldoc

Figure 9 – Selecting the drawing1.xml object reveals the name

This was created with sample code found on the EPPlus Wiki[2]:

Figure 10 – EPPlus sample code, clearly showing the similarities

Noteworthy is that all maldocs we observed have their VBA project protected with a password. It is interesting to note that the VBA code itself is not encoded/encrypted, it is stored in cleartext (although compressed) [3]. When a document with a password protected VBA project is opened, the VBA macros will execute without the password: the user does not need to provide the password. The password is only required to view the VBA project inside the VBA IDE (Integrated Development Environment):

Figure 11 – Password prompt for viewing the VBA project

We were not able to recover these passwords. We used John the Ripper with the rockyou.txt password list[4], and Hashcat with a small ASCII brute-force attack.

Although each malicious document is unique with its own VBA code, with more than 200 samples analyzed to date, we can generalize and abstract all this VBA code to just a handful of templates. The VBA code will either use PowerShell or ActiveX objects to download the payload. The different strings are encoded using either hexadecimal, BASE64 or XOR-encoding; or a combination of these encodings. A Yara rule to detect these maldocs is provided at the end of this blog post for identification and detection purposes.

Payload analysis

As mentioned in the previous section, via the malicious VBA code, a second-stage payload is downloaded from various websites. Each second-stage executable created by its respective malicious document acts as dropper for the final payload. In order to thwart detection mechanisms such as antivirus solutions, a variety of obfuscation techniques are leveraged which are however not advanced enough to hide the malicious intent.  The infrastructure used by the threat actor appears to mainly comprise compromised websites.

Popular antivirus solutions such as those listed on VirusTotal, shown in Figure 12, commonly identify the second-stage executables as “AgentTesla”. While leveraging VirusTotal for malware identification is not an ideal method, it does display how simple obfuscation can result in an incorrect classification. Throughout this analysis, we’ll explain how only few of these popular detections turned out to be accurate.

Figure 12: VirusTotal “AgentTesla” mis-identification.

The different obfuscation techniques we observed outline a pattern common to all second-stage executables of operation Epic Manchego. As can be observed in Figure 13, the second stage will dynamically load a decryption DLL. This DLL component then proceeds to extract additional settings and a third-stage payload before transferring the execution to the final payload, typically an information stealer.

Figure 13: Operation Epic Manchego final stage delivery mechanism.

Although the above obfuscation pattern is common to all samples, we have observed an evolution in its complexity as well as a wide variation in perhaps more opportunistic techniques.

  Early Variants Recent Variants
DLL Component Obfuscation Obfuscated base64 encoding Empty fixed-size structures
Final Payload Obfuscation Single-PNG encoding Multi-BMP dictionary encoding
Opportunistic Obfuscation Name randomisation Run-time method resolving, Goto flow-control, …

Table 1 – Variant comparison

A common factor of the operation’s second-stage samples is the usage of steganography to obfuscate their malicious intent. Figure 14 identifies a partial configuration used in recent variants where a dictionary of settings, including the final payload, is encoded into hundreds of images as part of the second-stage’s embedded resources.

Figure 14: Partial dictionary encoded in a BMP image

The image itself is part of the following second-stage sample which has the following properties:

Filename: crefgyu.exe
MD5: 7D71F885128A27C00C4D72BF488CD7CC
SHA256: C40FA887BE0159016F3AFD43A3BDEC6D11078E19974B60028B93DEF1C2F95726
File Size: 761 KB (779.776 bytes)
Compilation Timestamp: 2020-03-09 16:39:33

Noteworthy is the likelihood that the obfuscation process is not built by the threat actors themselves. A careful review of the second-stage steganography decoding routine uncovers how most samples mistakenly contain the final payload twice. In the following representation (Figure 15) of the loader’s configuration we can see that its payload is indeed duplicated. The complexity of the second- and third-stage payloads furthermore tend to suggest the operation involves different actors as the initial documents reflect a less experienced actor.

Throughout the multiple dictionary-based variants analyzed we furthermore noticed that, regardless of the final payload, similar keys were used as part of the settings. All dictionaries contained the final payload as “EpkVBztLXeSpKwe” while some, as seen in Figure 15, also contained the same value as “PXcli.0.XdHg”. This suggests a possible builder for payload delivery, which may be used by multiple actors.

Figure 15: Stage 2 decoded dictionary

Within the manually analyzed dataset of 30 distinct dictionary-based second stages, 19 unique final payloads were observed. From these, the “Azorult” stealer accounts for 50% of the variant’s delivery (Figure 16). Other payloads include “AgentTesla”, “Formbook”, “Matiex” and “njRat”, which are all well-documented already. Both “Azurult” and “njRAT” have a noticeable reusage rate.

Figure 16: Dictionary-based payload classification and (re-)usage of samples with trimmed hashes

Our analysis of droppers and respective payloads uncovered a common pattern in obfuscation routines. While opportunistic obfuscation methods may evolve, the delivered payloads remain part of a rather limited set of malware families.


A small number of the malicious documents we retrieved from VirusTotal were uploaded together with the phishing email itself. Analysis of these emails can shed some light on the potential targets of this actor. Due to the limited number of source emails retrieved, it was not possible to identify a clear pattern based on the victims. In the 6 emails we were able to retrieve, recipients were in the medical equipment sector, aluminium sector, facility management and a vendor for custom made press machines.

When looking into the sender domains, it appears most emails are sent from legitimate companies. Having used the “Have I Been Pwned”[5] service to confirm if any of the email addresses were known to be compromised, turned up with no results. This leaves us to wonder whether the threat actor was able to leverage these accounts during an earlier infection or whether a different party supplied them. Regardless of who compromised the accounts, it appears the threat actor primarily uses legitimate corporate email accounts to initiate the phishing campaign.

Looking at both sender and recipient, there doesn’t appear to be a pattern we can deduce to identify potential new targets. There does not seem to be a specific sector targeted nor are the sending domains affiliated with each other.

Both body (content) and subject of the emails relate to a more classic phishing scheme, for example, a request to initiate business for which the attachment provides the ‘details’. An overview of subjects observed can be seen below, note some subjects have been altered by the respective mail gateways:

  • Re: Quotation required/
  • Quote volume and weight for preferred
  • *****SPAM***** FW:Offer_10044885_[companyname]_2_09_2020.xlsx*
  • [SUSPECTED SPAM] Alternatives for Request*
  • Purchase Order Details
  • Quotation Request

Figure 17 – Sample phishing email

This method of enticing users to open the attachments is nothing new and does not provide a lot of additional information to pinpoint the campaign targeting any specific organisation or verticals.

However, leveraging public submissions of the maldocs through VirusTotal, we clustered over 200 documents, which allowed us to rank 27 countries by submission count without differentiating between uploads possibly performed through VPNs. As shown in Figure 18, areas such as the United States, Czech Republic, France, Germany, as well as China, account for the majority of targeted regions.

Figure 18 – Geographical distribution of VT submissions

When analysing the initial documents for targeted regions, we primarily identified English, Spanish, Chinese and Turkish language-based images.

Figure 19 – Maldoc content in Chinese, Turkish, Spanish and English respectively

Some images however contained an interesting detail: some of the document properties are in Cyrillic, and this regardless of the image’s primary language.

Although the Cyrillic Word settings were observed in multiple images, a new maldoc detected at time of writing this blog post piqued our interest, as it appears to be the first one to explicitly impersonate a healthcare sector member (“Ohiohealth Hardin Memorial Hospital”), as can be observed in Figure 20. Note also the settings as described above: СТРАНИЦА 1 ИЗ 1; which means page 1 of 1.

Figure 20 – Maldoc content impersonating “Ohiohealth Hardin Memorial Hospital” with Cyrillic Word settings

This Microsoft Excel document has the following details:

Filename: 새로운 주문 _2608.xlsm (Korean: New order _2608.xlsm)
MD5: 551b5dd7aff4ee07f98d11aac910e174
SHA256: 45cab564386a568a4569d66f6781c6d0b06a9561ae4ac362f0e76a8abfede7bb
File Size: 5.77 KB (5911 bytes)
Earliest Contents Modification: 2020-06-22 14:01:46

While the template from said hospital may have been simply discovered on the web and consequently used by the threat actor, this surprising change in modus operandi does appear to align with the actor’s constant evolution observed since the start of tracking.



Based on the analysis, NVISO assesses the following:

  • The threat actor observed has worked out a new method to create malicious Office documents with a way to at least slightly reduce detection mechanisms;
  • The actor is likely experimenting and evolving its methodology in which malicious Office documents are created, potentially automating the workflow;
  • While the targeting seems rather limited for now, it’s possible these first runs were intended for testing rather than a full-fledged campaign;
  • Recent uptick in detections submitted to VirusTotal confirms the actor may be ramping up their operations;
  • While the approach to create malicious documents is unique, the methodologies for payload delivery as well as actual payloads are not, and should be stopped or detected by modern technologies;
  • Of interest is a recent blog post published by Xavier Mertens on the SANS diary Tracking A Malware Campaign Through VT[6]. It appears another security researcher has also been tracking these documents, however, they have extracted the VBA code from the maldocs and uploaded that portion. These templates relate to the PowerShell way of downloading the next stage.

In conclusion, NVISO assesses this specific malicious Excel document creation technique is likely to be observed more in the wild, albeit missed by email gateways or analysts, as payload analysis is often considered more interesting. However, blocking and detection of these types of novelties, such as the maldoc creation described in this blog, enables organizations to detect and respond quicker in case an uptick or similar campaign occurs. The recommendations section provides ruling and indicators as a means of detection.


  • Filter email attachments and emails sent from outside your organization;
  • Implement robust endpoint detect and respond defenses;
  • Create phishing awareness trainings and perform a phishing exercise.



We provide the following rule to implement in your detection mechanisms for use in further hunting missions.

rule xlsm_without_metadata_and_with_date {
        description = "Identifies .xlsm files created with EPPlus"
        author = "NVISO (Didier Stevens)"
        date = "2020-07-12"
        reference = "http://blog.nviso.eu/2020/09/01/epic-manchego-atypical-maldoc-delivery-brings-flurry-of-infostealers"
        tlp = "White"
        $opc = "[Content_Types].xml"
        $ooxml = "xl/workbook.xml"
        $vba = "xl/vbaProject.bin"
        $meta1 = "docProps/core.xml"
        $meta2 = "docProps/app.xml"
        $timestamp = {50 4B 03 04 ?? ?? ?? ?? ?? ?? 00 00 21 00}
        uint32be(0) == 0x504B0304 and ($opc and $ooxml and $vba)
        and not (any of ($meta*) and $timestamp)

This rule will match documents with VBA code created with EPPlus, even if they are not malicious. We had only a couple of false positives with this rule (documents created with other benign software), and quite some corrupt samples (incomplete ZIP files).



Indicators of compromise can be found on our Github page here.


  • Initial Access:
    • T1566.001 Phishing: Spearphishing Attachment
  • Execution:
    • T1204.002 User Execution: Malicious File
  • Defense Evasion:
    • T1140 Deobfuscate/Decode Files or Information
    • T1036.005 Masquerading: Match Legitimate Name or Location
    • T1027.001 Obfuscate Files or Information: Binary Padding
    • T1027.002 Obfuscate Files or Information: Software Packing
    • T1027.003 Obfuscate Files or Information: Steganography
    • T1055.001 Process Injection: DLL Injection
    • T1055.002 Process Injection: PE Injection
    • T1497.001 Virtualization/Sandbox Evasion: System Checks



This blog post was created based on the collaborative effort of :

  • There are no more articles