Commodity .NET Packers use Embedded Images to Hide Payloads

Most malware is distributed in "packed" form: typically an executable containing code to evade antivirus detection and sandboxes before extracting and executing the intended payload. 

There are many commodity packers written in Microsoft .NET, usually but not always containing malware also written in .NET. 

We discuss two prevalent such packers used to distribute a wide variety of malware but hiding the intended payload in images. 


Steganography is the technique of sending hidden messages in apparently innocent forms. For hiding data in images, the main techniques are: 

  • Store the hidden data at the end of an image file 
  • Store the hidden data within the image metadata (e.g., EXIF) 
  • Store the hidden data within the actual pixel data 

To be truly "hidden" the latter would arguably mean using only the least significant bits of the data so that the image appears "normal" when rendered. 

The packers discussed here generally use the entire image pixel data so aren't truly "hidden"; if they were displayed, the images would appear random. 

 "CyaX" packer 

In this packer, the .NET executable contains a square PNG image in a .NET resource, which is typically a large proportion of the whole file size. 

The image can be decoded to an intermediate executable, which contains a .NET resource which in turn can be decoded to the payload. Sometimes the intermediate executable uses an additional commodity packer such as ConfuserEx or .NET Reactor.  


The first stage payload is decoded from the Blue, Green, Red, and Alpha (BGRA) channels taking pixels in columns. Some versions use Red, Green, and Blue (RGB) channels instead. 

For example, in sample SHA256 - 026b38e8eb0e4f505dc5601246143e7e77bbd2630b91df50622e7a14e0728675: 

Figure 1: Image taken from sample SHA256: 026b38e8eb0e4f505dc5601246143e7e77bbd2630b91df50622e7a14e0728675 

Using channels BGRA from the image we get data starting: 


In general, the extracted data is then XORed with a short XOR key or the first 16 bytes of the data and possibly decompressed with gzip, yielding an intermediate stage .NET executable.    

For the above sample, the XOR key is (in hex) "74 43 74 17 74 02 74 23 74", which gives the executable: 


This intermediate stage is often itself packed with ConfuserEx, but after unpacking that, it contains a .NET resource which contains the payload, typically XORed with two keys:, a short (often truncated Unicode) one, followed by a 16-byte key stored at the start of the resulting file. 

In the above sample, the intermediate executable is packed with .NET Reactor. After deobfuscation with a tool such as de4dot, the deobfuscated executable contains a resource "2EJp1.resources" which starts: 


XORing with key "00 77 00 55 00 6c 00 59 00 71 00 79 00 4e" ("wUlYqyNZJIbjVN" in Unicode, truncated to half the length): 


  and then XORing with the first 16 bytes of the result gives the payload, Agent Tesla (a prevalent information stealer) in this case: 


In some early versions of this packer, this .NET resource was named "CyaX_Sharp.Properties.Resources.resources" hence the name we have given to this packer family. 

Gzip variant 

As mentioned above, some samples use the Red, Green, and Blue (RGB) channels, and some compress the intermediate executable with gzip. 

For example, in sample SHA256 - 083521fa4522245adc968b1b7dd18da29b193fd41572114c9d7dd927918234ea: