Monday, January 30, 2017

EyePyramid: An Archaeological Journey

This post authored by Mariano Graziano and Paul Rascagneres


The last few days a malware sample named EyePyramid has received considerable attention, especially in Italy. The Italian police have arrested two suspects and also published a preliminary report of the investigation. This malware is notable due to the targeting of Italian celebrities and politicians.

We conducted our analysis on one of the first public samples attributed to EyePyramid. Sources in the security community have described this malware campaign as unsophisticated, and the malware samples involved as uninteresting. However Talos was intrigued to determine just how EyePyramid managed to stay hidden under-the-radar for years.

Preliminary Analysis

The sample is written in .Net and it is heavily obfuscated. Although at first sight we can also extract some interesting strings which are useful for possible ClamAV or Yara signatures. The author paid attention to hide the core functionalities by using either known .Net obfuscators or cryptography to hide crucial information such as URLs, email addresses and credentials.

Generally speaking, reversing .Net applications is not a difficult task because it is possible to decompile the binary. There are many tools do it such as ILSpy, dotPeek, etc. We first tried decompiling the sample with ILSpy but the obfuscation was heavy and all over the place. As a result the ILSpy output was not very useful and we had problems identifying the entry point of the application. The sample cannot be debugged, and it does not run inside virtual machines due to several and sometimes trivial (but effective) anti-debugging and anti-vm checks.


To effectively analyze EyePyramid we needed to defeat the obfuscation. We first tried to use de4dot for the deobfuscation and it detected two different known obfuscators namely 'Dotfuscator' and and 'Skater .NET'. From this point on, we refer to a 'cleaner' version of the sample. Keep in mind, however, that the malware is still obfuscated and the decompiler still fails for some routines.

The sample starts with some initialization code for the license keys and the certificates. Then, there is some code to achieve persistence using the CurrentVersion\Run and CurrentVersion\RunOnce registry keys. Moreover, there are checks to ensure the malware has Administrator privileges, and for the system uptime via a Windows Management Instrumentation (WMI) query to LastBootUpTime.

Regarding the persistence, we can observe the operation in which the registry key is set below:

The next step is to check and 'fix' the security descriptors of many folders via 'cacls.exe'. Specifically, this code is interested in the Windows Firewall and a long list of possible antivirus software (among them also 'ClamAV for Windows'). To find these programs the malware looks in typical locations such as ProgramFiles, ProgramFiles (x86), etc. You can see from the picture below 'cacls.exe' and part of the security products list:

In the next picture we can see how the malware creates an exception rule for itself, adding several new entries to the firewall policy ruleset:

The program also spawns threads and executes commands and executables (e.g., via ProcessStart or InteractionShell functions). For instance, it creates a registry key named 'default.reg' and it is added to the registry by directly invoking the regedit command. Regarding executables, we have instead 'ghk.exe' and 'stkr.exe' that are executed and other resources downloaded from the web.

Another interesting spawned thread is the one for checking the User Account Control (UAC) via the registry key 'EnableLUA' and disabling it through the control panel. UAC is an additional layer of security introduced by Microsoft from Windows Vista to notify the users about changes in the computer. In case of this and other changes, the system needs a reboot so all the modifications are effective and this is the goal of the function containing the 'shutdown' command. See below:

It is worth also a mention the programs added to 'DisallowRun', and here we noticed a particular interest for Avast antivirus. This key contains a list of applications that cannot run on the system.

When programs are executed by the agent, often they are launched with a command line parameter ('-w'). Generally speaking, this sample really pays attention to disable all possible security software and security checks. Additionally, it creates rules to make its execution smoother whenever it is possible.


As we already said the sample is still obfuscated and it massively adopts cryptography. As reported by other sources, the strings are encrypted with 3DES. Here we report how the key is generated and the overall structure for the encryption phase. The key is an array of 16 booleans at the beginning all set to false. The key is initialized in the the steps listed in the table below. The result of every step is a boolean value (true/false).

(*) These checks are more complex. Please refer to the decompiled version of the binary for a more exhaustive description.      

As a consequence, the key is dependent on the environment in which the sample is run. This sample was configured to run in three different environments. In order to allow this, the decryption function is called with three string arguments, which correspond to the same string encrypted with three different keys (one for each possible environment). The function will first try to decrypt the first string with the 16-bit based environment key, with the 14th and 15th bytes set to false. If this decryption process does not return a valid string, it will try to decrypt the second string with the same key, and finally, if this does not work either, it will try to decrypt the last string with the whole 16 bit key, including the last two checks.

The encryption is performed according to the pseudocode below:

array = init_key()
sarray = serializekey(array)
key = md5(sarray)
iv = sha256(sarray)
3des(data, key, iv)

where init_key() are the the checks from 0 to 13 or from 0 to 15. Given the low entropy of the possible keys, we could bruteforce the encryption keys for the three different running environments. In all the cases the decryption produced the same exact set of strings:

Throughout the code, the checks are also used as anti-vm in combination with others.

Among the others, it is worth mentioning a check for the 'Totalsize' of the drive. If this is less than 46.5 GB and the operating system is Windows XP, this is not a valid environment. This is a clever way to detect sandbox environments because generally they use a small hard drive and an old version of the Windows operating system.

Network Behavior

By running the sample on a VM and sniffing the network traffic we noticed some requests to known websites. At a first sight, this looks like a method to check if the connection is available but in this case the goal is different as you can see below:

The code randomly picks one domain and contacts it. Then it checks the header for the field 'Date'. This field is used to compute the difference the with current date and see if the delta is less than 60 min.

Another interesting point is related to the way in which the domains are rotated. This is not a real a domain generation algorithm (DGA), because the domains are not generated on the fly. This is simply how the agent gets the required information. This works in the following way:

switch((DateAndTime.Now.Month - 1) % 3):
0: geturl[0]
1: geturl[1]
2: geturl[2]

where geturl looks like:

return new string{

In this image you can observe the behavior described above. Interestingly, the same approach is used for URLs and other critical information such as email addresses, passwords etc. Throughout the code there are three different implementations to get a different kind of information. We stress the point that the domains are not generated on the fly but are chosen among a list of candidates.


The exfiltration is done mainly via email and partially via WebDAV and HTTP. Regarding emails, they are sent via SMTP protocol and the data is exfiltrated as attachment. The message is then uploaded to the IMAP server in a specific folder ("inbox" on the third picture).The protocol choice depends on a flag passed as a parameter to the function dealing with the email messages. These attachments can be either encrypted or in clear. The encryption is once again based on 3DES. For instance, this is part of the code related to the SMTP protocol, the second image contains IMAP servers while the third picture contains IMAP code:

WebDAV support is present in the code and it is used for uploading data and to fetch files. We also decrypted WebDAV credentials used during this operation. The code invokes different WebDav methods. In the picture below we can observe the code for 'SEARCH':

The sample interacts with Command and Control servers and can download additional files. This C&C communication is authenticated with a username and password. After authentication, the agent downloads the resource and writes it to the disk in encrypted form. Next, the file is read and decrypted, with the decryption key being used as the temporary filename. Finally, the file is deleted.

It is also interesting how the sample retrieves the IP address of '', a well-known italian webportal:

As you can see from the snippets of code above, the IP address is extracted directly from the cookie. This IP is added to a list of possible IP addresses to use and it is also used to generated an index later to pick a value from an array.The purpose of obtaining this IP is not completely clear from analyzing the code. Unfortunately some of the functions involved do not have any reference, so it appears as if they are never invoked.

Other Supports

Additionally in the code there is also support for Active Directory and LDAP. The code concerning Active Directory lists the administrative members of the domains and it checks if the current user is in this list. Another method adds the current user to the domain administrators. Regarding LDAP, the code is not referenced by any function, and it is probably used in more recent versions of this agent, however, logically it is similar to the Active Directory one.

Related Samples

There are other executables that appear to be executed, such as 'stkr.exe', but the analysis of that malware in beyond the scope of this post. For the reader interested in a further analysis, the sha256 for 'stkr.exe' is: 0af665d7d81871474039f08d96ba067d5a0bd5a95088009ea7344d23a27ca824.

During our analysis we have isolated another sample which was not publically related to this campaign. This sample and possibly one other are on ''. Unfortunately, at the time of publication is down for maintenance and google did not cache either of the two analyses. See:


Although it is true the authors made some trivial mistakes, throughout this post we have observed efforts to cover the vital information of this operation and an agent able to subvert the entire operating system security. Additionally, this sample is not stealthy for all the operations it performs but it has been undetected for years and is reported to have exfiltrated vast amounts of data. In this post, Talos dissected some interesting parts of this agent and provided detailed information on how it bypasses dynamic analysis environments and disarms the operating system security.

The authors would like to thank the research community for sharing the hashes and 'hackbunny' for the support and information sharing.


Additional ways our customers can detect and block this threat are listed below.

Advanced Malware Protection (AMP) is ideally suited to prevent the execution of the malware used by these threat actors.

CWS or WSA web scanning prevents access to malicious websites and detects malware used in these attacks.

Email Security can block malicious emails sent by threat actors as part of their campaign.

The Network Security protection of IPS and NGFW have up-to-date signatures to detect malicious network activity by threat actors.

AMP Threat Grid helps identify malicious binaries and build protection into all Cisco Security products.

Umbrella prevents DNS resolution of the domains associated with malicious activity.


No comments:

Post a Comment