Threat Bulletin: Exploring the Differences and Similarities of Agent Tesla v2 & v3

May 11th 2021


Agent Tesla is a spyware that has been around since 2014. It’s in active development, constantly being updated and improved with new features, obfuscation, and encryption methods. The malware is sold as a service with a relatively cheap licensing model, which makes it particularly easy to use and can explain its distribution on such a wide scale. At the time of writing two versions of Agent Tesla can still be found in the wild – version 2 and 3. Version 3 comes with some updates and additional features and is currently the most prevalent.

Agent Tesla’s most common and successful delivery method is through email, either in the form of spam or more targeted campaigns (OPEC+, COVID-19, ISPS), where the malware is bundled as an attachment, usually in the form of a document or a compressed archive (Figure 1).


Figure 1: VMRay Analyzer – Email delivering Agent Tesla (left) and the email displayed in an email client (right).


In the following Threat Bulletin, we’ll explore the delivery process of an Agent Tesla sample and some of the differences and similarities between different versions of Agent Tesla. With that in mind, we begin by looking into a fairly recent sample of Agent Tesla (v3) delivered as an email attachment (Figure 1).


Agent Tesla – Initial Stages

The email arrives with an attachment posing as an invoice with the .doc extension but is actually an RTF document. When it’s opened, it exploits CVE-2017-11882 to execute further stages. The shellcode used in the exploitation of the Equation Editor (eqnedt32.exe) is responsible for downloading and executing the next stage (Figure 2).

View the VMRay Analyzer Report for Agent Tesla v3 (INVOICE-6754.doc.rtf)


Figure 2: VMRay function log of the Equation Editor process downloading the next stage (top) and a VTI depicting document creating other processes (bottom).


Interestingly, with this delivery, the threat actors leverage the CMSTP.exe to launch further stages (Figure 3).


Figure 3: Abusing CMSTP to launch further stages.


CMSTP is usually used to install Connection Manager service profiles. It takes an .INF file’s path as argument. It describes the profile’s characteristics and the steps to be taken when installing it. This can be abused to start another executable by a legitimate, signed binary or used as a UAC bypass. It’s one of the Living Off The Land techniques. In this case, the .INF file itself seems to have been taken from a public example (by Tyler Applebaum) (Figure 4). It extends the installation with a RunPreSetupCommandsSection which allows one to run commands before the profile is installed. The malicious actor leverages this to run the malware.


Figure 4: .INF file passed to CMSTP.exe as an argument.


During the following steps of the execution, we observe how Agent Tesla makes sure that it’s not easily discovered by adding its image path as an exclusion for Windows Defender (Figure 5). Additionally, it also disables the UAC dialog by overwriting the corresponding settings in the registry. Doing this, the user won’t be notified or prompted for permission if an elevated (requiring administrator access token) action is taken. Thus, Agent Tesla is silently installed.


Figure 5: Defense evasion methods of the loader.


Finally, the actual Agent Tesla payload is extracted and injected using the process hollowing method (Figure 6). We have observed many samples using this approach however there were also cases using .NET in-memory reflective loading or a similar method. The process of delivering and loading Agent Tesla varies greatly but the actual payload has many similarities even between versions.


Figure 6: Agent Tesla’s loader using process hollowing.


Agent Tesla – Execution Flow

Even though Agent Tesla has been in development for at least 7 years, the overall execution flow hasn’t changed much. Some new features were added to the newer versions of Agent Tesla, but the behavior has remained fairly similar. The following section summarizes the high-level execution steps it usually performs. In some cases, we have observed that the order changes slightly but it doesn’t impact the behavior. It also highlights additions made in the newer version of Agent Tesla (v3).

At the beginning of its execution, Agent Tesla often uses certain methods to evade automatic analyses. Some of the common evasion techniques include the introduction of an execution delay, which can evade sandboxes that have a limited monitoring duration, and checking the user and computer name for certain hard-coded values that could indicate it’s being analyzed (Figure 7). The spyware also makes sure that no other processes with the same name are currently running. It iterates over all processes with the same name and kills any which aren’t the current process.

Each infected system is identified by a unique ID generated from different hardware information. There are different ways Agent Tesla can achieve this. It applies the MD5 hashing algorithm on a string created by concatenating different hardware properties:

  • System Serial Number,
  • CPU identification value retrieved from the processorID property of the Win32_Processor WMI management class,
  • The MAC address is taken from the MACAddress property of the Win32_NetworkAdapterConfiguration WMI class. It takes the MAC address of a network adapter that is currently connected.

The hardware ID is generated at the beginning of the execution but appears to be only used during the HTTP communication.

Another common “evasion” between versions, that Agent Tesla uses at the beginning of its execution, is the GetLastInputInfo function. If no input event was detected in the last 10 minutes a configuration variable is set (Figure 7).


Figure 7: Agent Tesla’s last input detection (top) and user/computer name detection (bottom).


Its next step is usually to copy itself to a less obvious location (an installation folder) like %appdata% which is also configurable and might not be used at all. The config file also indicates if the file should have the hidden and system attributes set. Persistence is achieved by installing itself as a startup application in the registry. In this case, Agent Tesla also enables the corresponding startup entry via \Software\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\Run by setting the value 02 00 00 00 00 00 (Figure 8).


Figure 8: Agent Tesla’s persistence via Registry.


Furthermore, it also deletes the ZoneIdentifier from the base image. A ZoneIdentifier is an Alternate Data Stream created (when a file is downloaded and saved from the internet). This information is used by Windows and various security products. Deleting it makes the malware look as if it wasn’t downloaded from the internet. Depending on the configuration Agent Tesla is able to take screenshots periodically. It uses a timer that will invoke the registered callback function according to a specified interval which is also configurable. One difference between versions is in the choice of protocols the malware can use to exfiltrate the collected information. Version 2 and 3 are both capable of using HTTP, SMTP, and FTP. On top of that, v3 comes with another possibility which is sending a document to a Telegram channel (Figure 9).


Figure 9: Example configuration of Agent Tesla using Telegram as C2 (left) and screenshot functionality of a v3 that can use Telegram (right).


A new addition that came with Agent Tesla v3 is the ability to collect clipboard data and the external IP of the infected host (Figure 10).

View the VMRay Analyzer Report for Agent Tesla v3 (External IP Check)


Figure 10: Agent Tesla v3 checking external IP.


Furthermore, v3 comes with the option to use the Tor proxy for its HTTP communication. This is a newer addition which isn’t found in the previous versions (Figure 11). If the corresponding configuration is set, Agent Tesla first tries to kill all currently running Tor instances and then download and set up the Tor client.


Figure 11: Agent Tesla with the Tor proxy option (v3) (left) and Agent Tesla without Tor proxy v2 (right).


With HTTP communication set-up, Agent Tesla starts one of its main tasks – credential-stealing (Figure 12). Agent Tesla v3 has some additions to the application list that it targets.


Figure 12: Agent Tesla’s Stealing attempts.


Both versions are also able to function as a keylogger. The keylogging functionality is again implemented with the help of timers. The set interval specifies how often the logs are collected and exfiltrated (Figure 13). The hook itself is installed using the native SetWindowsHookExA function with idHook WH_KEYBOARD_LL which takes an application-defined hook.


Figure 13: Keyboard log exfiltration (left) and hook installation (right).


String and Config Decryption

All strings that are used by Agent Tesla are encrypted by default and mostly used on demand. The ability to decrypt Agent Tesla’s strings, allows one to extract parts of the configuration information like the c2 server, the passwords used, or other data related to network connections. Appendix B contains a small list of extracted network information from different Agent Tesla samples.

Version 2
Agent Tesla v2’s encrypted strings are usually located in the .text segment of the PE file. To be exact, they start 0x50 bytes past the beginning of the section. The strings are encrypted using AES in CBC mode (Figure 14). Each string is encrypted with its own Key and IV. Strings are stored in an array of objects, where each object is an array of units. The decryption routine takes an encoded offset into the array which is then decoded at runtime to extract the corresponding string.


Figure 14: Agent Tesla v2 string decryption routine.


Investigating the object in dnSpy shows that the static object array corresponds to the token 0x04000001 (Figure 15 left). It describes the Field table (0x4) and its first row (0x000001). Each element in the array is described by its own token (Figure 15 right). dnSpy already provides us with the corresponding RVA and file offset. However, this information can also be extracted manually from the FieldRVA table in the metadata stream of the PE file by looking up the corresponding row number. This information would allow to statically parse the file and its metadata, extract the RVAs and decrypt the strings without assuming any offsets.


Figure 15: Encrypted strings as shown in dnSpy (left) and the metadata of each element (right).


Version 3
Agent Tesla v3 changes how the strings are encrypted. AES is no longer used for decryption. Instead, the encrypted strings are stored in a byte array which is decrypted by XORing the value with the current array offset and a hard-coded key. This decryption takes place when the class is constructed, i.e., the array and the decryption loop (Figure 16 left) are implemented inside a class constructor. The decrypted strings are stored without any separators as a single blob of characters. When a particular string is required, a function that takes the offset and length of the string as parameters is used (Figure 16 right). This also means that it’s harder to statically extract information from the strings and requires, e.g., parsing of the actual decoding function wherever it’s used and extracting its arguments.


Figure 16: String decryption in a class constructor (top) and example decoding function (bottom).



Understanding a malware family, its usual delivery methods, and the techniques used can be very beneficial from an incident response standpoint. The research of a family can give the blue team enough information to start an internal investigation if a breach is suspected. They can better assess the initial impact of such a breach, can look for indicators and start their initial analysis from there and expand outwards.




Appendix A

Agent Tesla Payloads – Hashes












Loaders – Hashes













Documents – Hashes



Appendix B

Some of the extracted configurations presented in the MWCP format.


{'version': [3], 'other': {'xor_key': 170, 'smtp': ''}, 'email_address': [''], 'password': ['fP******']}
{'version': [3], 'other': {'xor_key': 170, 'smtp': ''}, 'email_address': [''], 'password': ['sg**********']}
{'version': [3], 'other': {'xor_key': 170, 'smtp': ''}, 'email_address': [''], 'password': ['ma*******']}
{'version': [3], 'other': {'xor_key': 170, 'smtp': '', 'toemail': ''}, 'email_address': [''], 'password': ['an*********']}
{'version': [3], 'other': {'xor_key': 170, 'chat_id': '1063661839', 'token': 'bot16********:AAF2v81NoI*************************', 'method': 'sendDocument'}, 'c2_address': ['']}
{'version': [3], 'other': {'xor_key': 170, 'smtp': ''}, 'email_address': [''], 'password': ['fo*****']}
{'version': [2], 'email_address': [''], 'password': ['721*************'], 'other': {'smtp': '', 'toemail': ''}}
{'version': [3], 'other': {'xor_key': 170, 'smtp': ''}, 'email_address': [''], 'password': ['bd***************']}
{'version': [3], 'other': {'xor_key': 170, 'smtp': '', 'toemail': ''}, 'email_address': [''], 'password': ['4r**********']}
{'version': [3], 'other': {'xor_key': 170, 'smtp': ''}, 'email_address': [''], 'password': ['Chi*****']}
{'version': [2], 'email_address': [''], 'password': ['stl*****'], 'other': {'smtp': ''}}
{'version': [3], 'other': {'xor_key': 170, 'smtp': ''}, 'email_address': [''], 'password': ['m*****']}
{'version': [3], 'other': {'xor_key': 170, 'smtp': ''}, 'email_address': [''], 'password': ['Jes*****']}
{'version': [3], 'other': {'xor_key': 170, 'smtp': '', 'toemail': ''}, 'email_address': [''], 'password': ['D***************']}
{'version': [3], 'other': {'xor_key': 170, 'smtp': '', 'toemail': ''}, 'email_address': [''], 'password': ['721*************']}
{'version': [3], 'other': {'xor_key': 170, 'chat_id': '1464755657', 'token': 'bot14********:AAHvvJmG-W*************************', 'method': 'sendDocument'}, 'c2_address': ['']}
{'version': [3], 'other': {'xor_key': 170, 'smtp': ''}, 'email_address': [''], 'password': ['sta*******']}
{'version': [3], 'other': {'xor_key': 170, 'smtp': '', 'toemail': ''}, 'email_address': [''], 'password': ['ZA**********']}
{'version': [2], 'email_address': [''], 'password': ['B**********'], 'other': {'smtp': '', 'toemail': ''}}
{'version': [3], 'other': {'xor_key': 170}, 'ftp': ['', 'travelsplan', '3p**********']}
{'version': [3], 'other': {'xor_key': 170, 'smtp': ''}, 'email_address': [''], 'password': ['Reb**********']}
{'version': [3], 'other': {'xor_key': 170, 'smtp': ''}, 'email_address': [''], 'password': ['@@**********']}
{'version': [3], 'other': {'xor_key': 170, 'smtp': ''}, 'email_address': [''], 'password': ['Ak************']}
{'version': [3], 'other': {'xor_key': 170, 'smtp': ''}, 'email_address': [''], 'password': ['{D**********']}
{'version': [3], 'other': {'xor_key': 170, 'smtp': ''}, 'email_address': [''], 'password': ['@M********']}
{'version': [3], 'other': {'xor_key': 170, 'smtp': ''}, 'email_address': [''], 'password': ['S1**********']}
{'version': [3], 'other': {'xor_key': 170, 'smtp': ''}, 'email_address': [''], 'password': ['Q*******']}
{'version': [3], 'other': {'xor_key': 170, 'smtp': ''}, 'email_address': [''], 'password': ['dg**********']}
Calculate how much malware false positives are costing your organization:
Malware False Positive Cost Calculator