Turla PNG Dropper is back

This is a short blog post on the PNG Dropper malware that has been developed and used by the Turla Group [1]. The PNG Dropper was first discovered back in August 2017 by Carbon Black researchers. Back in 2017 it was being used to distribute Snake, but recently NCC Group researchers have uncovered samples with a new payload that we have internally named RegRunnerSvc.

It’s worth noting at this point that there are other components to this infection that we have not managed to obtain. There will be a first stage dropper that will drop and install the PNG Dropper/RegRunnerSvc. Nevertheless, we think that this it is worth documenting this new use of the PNG Dropper.

PNG Dropper

The PNG Dropper component has already been well documented by the research team at Carbon Black [1], but for the purpose of clarity we will now give a quick summary of what it is and how it works.

Figure 1

The purpose of the dropper is to load and run a PE file that is hidden in a number of PNG files. Figure 1 shows the resources of the dropper. Here you can see a number binary data resource entries under the name “PNG”. Each of these resources is a valid PNG file which can be viewed with any image viewer, but upon opening one you will only see a few coloured pixels (see an enlarged version in Figure 2).

Figure 2

The PNG is loaded using Microsoft’s GDI+ library. In Figure 3 we see a call to LockBits which is used to read the pixel data from the PNG file. Each byte in the pixel data represents an RGB value for a pixel. Encoded in each of the the RGB values is a byte from a PE file. It doesn’t make for a very meaningful image, but it is a novel way to hide data in seemingly innocent resources.

Figure 3

Each PNG resource is enumerated and the pixel data is extracted and then concatenated together. The result is an entire PE file contained in memory. The dropper will then manually load the PE file. The imports are processed, as are the relocations. Finally the PE file’s entry point is executed (as shown in Figure 4).

Figure 4


The PNG dropper will decode and run RegRunnerSvc from its PNG resources. The purpose of RegRunnerSvc is to extract an encrypted payload from the registry, load it into memory, and then run it. A first stage dropper (which we have not managed to obtain) will have already installed it as a service and performed a few additional setup operations.

Figure 5 shows the entry point for RegRunnerSvc. Here we can see the call to StartServiceCtrlDispatcher. In this case the name of the service is WerFaultSvc, obviously chosen in an attempt to seem like a legitimate part of the Windows Error Reporting service. The service also serves as a persistence mechanism for the malware.

Figure 5

After the service setup functions has been executed, it is time to find the data in the registry. Generally the path to the registry value would be stored as a (possibly encrypted/obfuscated) string within the binary, but interestingly this is not the case here. The registry keys and values are enumerated using the RegEnumKeyExA and RegEnumValueA functions. The enumeration starts at the root of the HKEY_LOCAL_MACHINE key and continues using a depth first search until either the data is found or the enumeration is exhausted. Another interesting implementation detail (shown in Figure 6), is that the only requirement for decryption function to be called is that the size of the value data is 0x200 (512) bytes in size. This is not as inefficient as it may first seem as the decryption function will exit relatively quickly if the first stage dropper has not performed its setup operations. Nevertheless it’s clear that for the malware authors, obfuscation is more important than efficiency.

Figure 6

The data in the registry contains the encrypted payload and the data required to decrypt it. It doesn’t contain the decryption key, but it does contain data that is used to generate the key. This data, however, is itself partially encrypted using the Microsoft CNG library functions (NCrypt*). The first stage dropper will have generated a decryption key and stored it in the one of the system default key storage providers, in this case the “Microsoft Software Key Storage Provider”. If the first stage dropper has not run, then the key will not be in the storage provider, and the decryption function will exit. Provided that the storage provider actually contains a key, the first 0x200 (512) bytes of the data will be decrypted. This decrypted data contains a header that contains the information needed to locate the rest of the data in the binary blob (full description of the header can be found in Table 1).

0x00Offset to secret data - used in call to the BCryptGenerateSymmetricKey() function
0x08Size of secret data
0x10Offset to IV
0x18IV size
0x20Offset to AES encrypted data
0x28Encrypted data size
Table 1

Now the header has been decrypted, the second part of the decryption can take place. The main payload is encrypted using the AES algorithm. First a chunk of data from the registry is passed to the BCryptGenerateSymmetricKey function, which results in the AES decryption key being created. Once the key has been generated and the decryption properties have been set, the payload will be decrypted. The decrypted payload is then checked to ensure that it’s a valid PE file (it checks for the MZ & PE magic bytes, and also checks for the machine architecture entry in the PE header). If the checks pass, the file is manually loaded (imports and relocations) and the entry point is called (as shown in Figure 7).

Figure 7


In this blog post we have had a quick look at a new use of the PNG Dropper by the Turla Group. The group is now using it with a new component: RegRunnerSvc, which extracts and encrypted PE file from the registry, decrypts it and runs it. It seems that the group is taking ideas from fileless malware, such as Poweliks or Kovter. The group is ensuring that it is leaving as little information as possible in the binary files, i.e. not hardcoding the name of the registry key containing the encrypted data. This means that that it is not possible to extract useful IOCs for threat hunting.

Thankfully all is not lost and we can at least detect the usage of the PNG dropper using the Yara rules below.

As part of our research we created a tool that will extract the payload from the PNG Dropper. We have decided to release this tool just in case others find it useful. It can be found here: https://github.com/nccgroup/Cyber-Defence/tree/master/Scripts/turla_image_decoder.

Yara Rules

rule turla_png_dropper {
author = "Ben Humphrey"
description = "Detects the PNG Dropper used by the Turla group"
sha256 =

$api0 = "GdiplusStartup"
$api1 = "GdipAlloc"
$api2 = "GdipCreateBitmapFromStreamICM"
$api3 = "GdipBitmapLockBits"
$api4 = "GdipGetImageWidth"
$api5 = "GdipGetImageHeight"
$api6 = "GdiplusShutdown"

$code32 = {
8B 46 3C // mov eax, [esi+3Ch]
B9 0B 01 00 00 // mov ecx, 10Bh
66 39 4C 30 18 // cmp [eax+esi+18h], cx
8B 44 30 28 // mov eax, [eax+esi+28h]
6A 00 // push 0
B9 AF BE AD DE // mov ecx, 0DEADBEAFh
51 // push ecx
51 // push ecx
03 C6 // add eax, esi
56 // push esi
FF D0 // call eax

$code64 = {
48 63 43 3C // movsxd rax, dword ptr [rbx+3Ch]
B9 0B 01 00 00 // mov ecx, 10Bh
BA AF BE AD DE // mov edx, 0DEADBEAFh
66 39 4C 18 18 // cmp [rax+rbx+18h], cx
8B 44 18 28 // mov eax, [rax+rbx+28h]
45 33 C9 // xor r9d, r9d
44 8B C2 // mov r8d, edx
48 8B CB // mov rcx, rbx
48 03 C3 // add rax, rbx
FF D0 // call rax

(uint16(0) == 0x5A4D and uint16(uint32(0x3c)) == 0x4550) and
all of ($api*) and
1 of ($code*)
rule turla_png_reg_enum_payload {
                author = "Ben Humphrey"
                description = "Payload that has most recently been dropped by the
Turla PNG Dropper"
               shas256 =

$crypt00 = "Microsoft Software Key Storage Provider" wide
$crypt01 = "ChainingModeCBC" wide
$crypt02 = "AES" wide

(uint16(0) == 0x5A4D and uint16(uint32(0x3c)) == 0x4550) and
pe.imports("advapi32.dll", "StartServiceCtrlDispatcherA") and
pe.imports("advapi32.dll", "RegEnumValueA") and
pe.imports("advapi32.dll", "RegEnumKeyExA") and
pe.imports("ncrypt.dll", "NCryptOpenStorageProvider") and
pe.imports("ncrypt.dll", "NCryptEnumKeys") and
pe.imports("ncrypt.dll", "NCryptOpenKey") and
pe.imports("ncrypt.dll", "NCryptDecrypt") and
pe.imports("ncrypt.dll", "BCryptGenerateSymmetricKey") and
pe.imports("ncrypt.dll", "BCryptGetProperty") and
pe.imports("ncrypt.dll", "BCryptDecrypt") and
pe.imports("ncrypt.dll", "BCryptEncrypt") and
all of them


Sample Analysed

  1. 6ed939f59476fd31dc4d99e96136e928fbd88aec0d9c59846092c0e93a3c0e27 (PNG Dropper)
  2. fea27eb2e939e930c8617dcf64366d1649988f30555f6ee9cd09fe54e4bc22b3 (Payload contained in the PNG dropper)


  1. WerFaultSvc


[1] https://www.carbonblack.com/2017/08/18/threat-analysis-carbon-black-threat-research-dissects-png-dropper/

Published date:  22 November 2018

Written by:  Ben Humphrey

Call us before you need us.

Our experts will help you.

Get in touch