_Overview

DarkVision is a malware classified as a Remote Access Trojan (RAT), incorporating various techniques associated with other types of malware focused on stealing information. Unlike other malware in the same category, it is developed in C++ and ASM and contains a plugin subsystem within its payload, providing operational capabilities at runtime. DarkVision first appeared between late 2019 and early 2020 on underground forums, where its developer introduced it as a RAT “which makes it standalone and free from any third party dependencies”. It was offered for around $40, with support and a sales website featuring information, screenshots, and explanatory videos, clearly targeting the MaaS (Malware-as-a-Service) market.

Over the years, it has continued to evolve and has been sold in different ways, appearing in various campaigns operated by different Threat Actors, as well as in unattributed mass campaigns that have gained access to thousands of devices worldwide. This well-known RAT could establish communication with the C2 configured by the malware purchaser, inject itself into the browser for credential stealing, escalate privileges, and establish persistence on compromised victims, strengthening its position for remote access, gathering information about the device or user, and potentially conducting lateral movement later on. It is a tool that has enabled different adversaries with different motivations to operate, providing access to sensitive information that can be sold or used to gain further control over infrastructure, with a clear point of compromise at patient zero, which acts as the entry point.

Throughout the more than four years that DarkVision has been active, as mentioned above, it has appeared in several relevant operations and campaigns, where it has played a fundamental role in collecting victims or operating alongside other malware. Some relevant examples include:

• [☢️Campaign] SmokeLoader: Distribution through malvertising and/or apparently legitimate software to load SmokeLoader and deploy DarkVision.
• [☢️Campaign] PureCrypter + Donut: An attack using .NET + SC Donut to execute PureCrypter and deploy DarkVisionRAT.
• [☢️Campaign] Scripts abuse: Mass campaigns using scripts as initial loaders to download or load other stealers that deploy the RAT, or deploy DarkVision directly.
• [☢️Campaign] GraftLoader: Use of .NET to load multiple bitmaps and launch different malware, with DarkVision identified in later stages.



_Modus Operandi

This RAT has been part of the MaaS ecosystem for the past few years, sharing the landscape with dozens of different malware families and campaigns running simultaneously. As a result, there is no single infection chain that can be considered representative. Since this tool has been and remains available for purchase on underground markets, different versions and campaigns can be found operating simultaneously, each with its own modus operandi.

Despite this variation, the patterns observed over recent months have been fairly consistent. Phishing, Malvertising, and deceptive software installation techniques have been used to introduce loaders or early stages of DarkVision. The primary objective in all cases is to remain undetected long enough to deploy the RAT and maintain stable communication with the victim. Through this connection, the operator can receive sensitive information and access a range of capabilities once the malware has been implanted in the system.

For a better understanding of the most common DarkVision campaigns, we can refer to the following graph:

DarkVision Graph

As we can see, initial access and the development of the stages preceding DarkVision execution vary considerably depending on the purchaser and the campaign creator. However, as is usually the case, execution becomes more standardized once the infection reaches the stages immediately preceding DarkVision’s execution. The purchaser can change how the RAT is launched, but does not necessarily modify or alter its execution flow. Despite this, DarkVision offers a certain degree of flexibility, as its builder, which we will explore in later sections, allows some modifications that affect the capabilities available in the payload.

Before examining how DarkVision works, it is worth understanding how different adversaries have used various techniques to deploy it, as detecting the threat as early as possible is essential.


_Phishing and/or Malvertising

The first stage, and the most widespread one, involves the use of Phishing or other techniques to gain initial access for DarkVision. Adversaries do not usually focus on deploying it directly at this early stage, instead relying on preceding stages, loaders, or other malware to facilitate deployment.

In the Phishing category, we can find different lures targeting various companies and attempting to direct victims towards a supposedly legitimate document, whether PDF, DOCX, or XLS. In these cases, as shown in the example, victims are led to download the file to proceed to the next stage.

0

Here, we may encounter genuine office documents or simply loaders whose icons or file extensions have been changed to make them appear legitimate, a common technique in mass campaigns.

0
0

We may also find ZIP/RAR archives at this stage, containing office documents or directly including scripts or binaries that act as loaders or droppers.

Regarding malvertising and fake software, several samples and campaigns have attempted to disguise themselves as ADs on movie websites, leading to ClickFix, of course, followed by the download of a loader or dropper, much like the techniques described above. As seen in similar campaigns, the classic “Download Adobe for Free”, “Crack”, or similar lures are also present in DarkVision campaigns. Innovation cannot happen at every level, can it?

0


_Scripts

Another vector that often overlaps with the previous one is the extensive use of scripts I have observed throughout my investigation of DarkVisionRAT. They often arrive through the same channels, including Phishing, Malvertising, or the abuse of fake cracks and software, but they can also be downloaded as RAR/ZIP archives or originate from other malware or loaders. The range of variants is quite extensive, as I have encountered almost the entire catalogue: VBS, JS, BAT, HTA, and LNK, all to varying degrees, with VBS and JS being the most common.

To avoid boring you too much and making this unnecessarily long, I think it is worth highlighting the most representative examples. One of them is undoubtedly JavaScript, where we can see how it is combined with PowerShell execution. These scripts are often heavily obfuscated and can follow different approaches:

  • A script whose deobfuscation leads to the download and execution of a loader that subsequently invokes the RAT.
  • A script with two stages, one acting as an injector and the other serving as the RAT loader sample.

0

In the example, we can see how GitHub and other intermediary sites are used to host different components of this initial stage. One acts as the injector, while the other contains the malware, which is often a preliminary version or another loader associated with the RAT itself. This modus operandi is also quite common with AsyncRAT and other RATs in the same category. In some cases, the same operator has been observed serving two different scripts to different targets, but written in different languages, such as JS and HTA running simultaneously.

As for VBS, these scripts are not particularly original either. We can observe different scripts obfuscated in various ways, where a variable contains a chunk of data that is subsequently processed using XOR or Base64. Nothing particularly sophisticated and, essentially, the same approach as in the previous examples: a binary acting as a loader or another piece of malware doing the job under some fancy name.

0

Essentially, the purpose is clear: these scripts delay analysis and provide an easy component to replace. Operators can move their infrastructure, change the script, and restart the campaign, making this one of the cheapest and least maintenance-intensive modus operandi for an inexperienced adversary or one unwilling to invest much effort in it.


_Summary of Active Campaigns

Over the past few months, I have encountered all kinds of different campaigns, as mentioned above, with operators attempting to introduce DarkVision by any means necessary. For this reason, I have tried to showcase the most widespread techniques to cover as much ground as possible. However, it is important to keep in mind that other campaigns have also been active and could reappear using different patterns, including:

  • Other malware acting as loaders or additional components: Amadey, Vidar, StealC, Raccoon, SmokeLoader, etc.
  • Inno Setup: Used to initiate the loading of other malware or DarkVision itself.
  • Cleaning utilities (e.g. GCCleaner) that install other malware.
  • Other scripts, as mentioned above.

The use of other malware or techniques to deploy the RAT is the spark that initiates the connection from the victim’s device. However, it can also be combined with other stealers, creating a joint operation that amplifies both the strengths and weaknesses of each component. One gathers all the available information, while DarkVision provides communication and additional remote control and execution capabilities. Together, this makes for an explosive combination for the targets involved.


_Technical analysis

Now that we have covered how DarkVision reaches its initial stages, all that remains are minor loader variants leading up to the RAT payload. In this case, there are two clearly differentiated types, C++ and .NET. Essentially, they boil down to the same thing: loading modules into memory and working with different threads to progressively expand their capabilities while hindering analysis and preventing anyone from reaching the malware’s core code.

_Prev phase

Before going through these stages, it is worth mentioning that previous stages have sometimes been found in samples featuring obfuscated/Crypted layers or even packers that delay analysis. However, they essentially end up doing the same thing, only making static analysis more difficult, as they expose fewer imports or contain virtually no strings. Naturally, when examining them in IDA, we encounter the initial STUB rather than the actual code of DarkVision’s early stages.

0

Essentially, the most important elements we will find in this case are memory allocation stages using VirtualAlloc, which, in this instance, fill the allocated memory with 0x23 (# in ASCII). This filling pattern is visible in the memory dump, where we can see consecutive rows of # characters.

0

It then passes through several functions to process the payload and reconstructs the IAT (Import Address Table), allowing us to retrieve all the libraries and imports it will actually use, which were not previously visible during static analysis.

0

Ultimately, this is what it does:

  • Locates kernel32.dll and ntdll.dll in memory.
  • Resolves GetProcAddress and LoadLibrary through the PEB/LDR.
  • Iterates through the payload’s import table and invokes GetProcAddress for each function.
  • Writes the resolved pointers into the payload’s IAT, now located in memory.

Once it finishes, we can see, as shown in the previous image and the following one, how it extracts all the functions, such as ZwSetVol, ZwShutdown, ZwSuspendThread, ZwTerminateJob, ZwTerminateProcess, ZwTerminateThread, etc.

0

Eventually, it performs a long jump to the OEP (Original Entry Point) of the unpacked payload, and from this point onward, we have a binary corresponding to the early stages of DarkVision.


_Phase 1: Initial Setup

After reaching the beginning of the stages common to most DarkVision binaries, we encounter a first layer that behaves differently depending on the version. Essentially, in the case of .NET samples, it attempts to load modules or process strings that lead to intermediate DLLs or directly to the payload.

Among the most interesting .NET samples, I have found numerous examples that rely on bitmaps to load subsequent modules. These are usually protected by ConfuserEx, Eazfuscator, or similar tools. Their names naturally vary, and ultimately, they contain libraries that employ techniques such as pixel steganography, also found in other malware such as VIP or Snake.

0

The first library is retrieved in the same way as the subsequent ones, so we will use it as a representative example of the process, which is repeated in .NET samples when it comes to loading libraries. The malware allocates an array, loads the resource, retrieves the bitmap’s contents, and processes them using another function to eventually obtain the MZ header in another array and finally load it into memory.

0

Furthermore, what is interesting is that many of these loaded libraries contain additional bitmaps themselves, meaning the malware weaves an impressive network of image processing operations during runtime.

The result is what we mentioned earlier: a library with an obfuscator or crypter layered on top. Nothing new.

0

This stage serves solely as a launcher and performs the binary’s initial setup. Therefore, although it contains fewer technical details, it is actually the most important stage, as it is the spark that sets everything in motion.


_Phase 2: First Module and Execution

Following the previous initialization, we can reach the execution of the first loaded module, in this case OptiMax, although its name varies between campaigns. This stage focuses on further developing its capabilities while hindering analysis, with the ultimate goal of loading additional modules.

This first DLL applies control-flow flattening, string encryption, and identifier names containing invisible Unicode characters, all of which remain present throughout the analysis.

From the very beginning, we can see how it allocates memory and works with strings that it processes during execution.

0
0

As execution progresses, we reach the loading of a NUIv, another bitmap image embedded in the assembly that acts as a steganographic container. The payload is stored in the ARGB values of each pixel.

0

Essentially, the image includes deliberate padding that inflates its actual dimensions: (W + 177) × (H + 225) pixels. The RestoreOriginalBitmap function removes this padding before extraction, restoring the image to the container’s original dimensions. It then iterates over each pixel to extract the color bytes as data.

0
0
0

Essentially, what we see is how it works with multiple arrays containing the bitmap’s contents.

Additionally, we find one of the most relevant functions in this stage, where decryption is performed using parameters with names such as fog (the encrypted blob), kite (the key), or yek, which in this case means key written backwards.

kite = "yek"  →  UTF-16LE: {00 79 00 65 00 6B}  
seed = fog[-1] ^ 0x70                          

fog[-1] = 0x97  →  seed = 0x97 ^ 0x70 = 0xE7


Blob:        AA  C4  77  E7
Keystream:   E7  9E  E7  E7
Plaintext:   4D  5A  90  00  →  MZ 

0

The final result is, once again, another MZ header.

0
0

By extracting the bitmap before it is processed and comparing it with the extracted result, we can see that both occupy the same amount of space. Naturally, all the processing takes place in memory, and the library is never dropped to disk.

0

After decryption, what we obtain is the second DLL being loaded into memory, named Edge Optimizer.

0

To nobody’s surprise, this brings the second stage to an end. However, I found it interesting that these types of names had already been used repeatedly in similar campaigns in the past.


_Phase 3: Second Module, Installation and Persistence

This stage performs most of the operations preceding the payload, as it contains the necessary components to drop similar binaries, implement persistence mechanisms, install the payload, and so on. The library responsible for these actions generally follows the same pattern as the previous one, either being large in size or having been processed by obfuscators/crypters.

The first layer of this stage focuses on functions that copy the currently executing binary. Its purpose is simple: locate %AppData% and create a randomly named file in the Roaming folder, following the same pattern, with the Read-Only and Hidden flags set through its ACLs and file attributes. This makes the file harder to locate, open, and delete unless you have SYSTEM privileges. As we can see, the path is constructed using an array containing the ASCII characters that translate into the complete path where the malware will operate.

0

The created binary is, in every case, a copy of the original. The filename is generated from the system’s GUID, making it unique per victim. Although it follows certain patterns, the resulting string can be used to identify the victim.

0

Subsequently, another interesting technique, and undoubtedly one of the most important ones, is persistence. This can be implemented in two locations: within the payload itself, if this feature is enabled in the builder, and during this stage in these particular versions.

First, it retrieves the executable created earlier to create a registry key.

0
0

As shown in the previous image, it uses PowerShell to extract values from memory and transform them during execution to construct a string containing the PS1 script code. In summary, this includes both the PowerShell flags and the file path and name we saw earlier:

$yzzyf = [char]78+[char]111+...       → "NoProfile"
$uittk = [char]69+[char]120+...       → "ExecutionPolicy"
$t0soe = [char]66+[char]121+...       → "Bypass"
$lchad = [char]87+[char]105+...       → "WindowStyle"
$cswj3 = [char]72+[char]105+...       → "Hidden"
$5gbmo = [char]83+[char]116+...       → "Start-Process"

$r1its = @(67,58,92,85,115,...,101,120,101)
$iwfa4 = ($r1its | ForEach-Object { [char]$_ }) -join '' # → "C:\Users\<VictimUser>\AppData\Roaming\<\w{13}\.exe>"

0

What happens next is that it creates an entry under the CurrentVersion\Run registry key using the elements it has already obtained. It creates a value whose name follows the same pattern described earlier and directly inserts the command to be executed. This ensures that the PS1 command runs at every system startup, using the previously mentioned flags and ultimately launching the executable.

powershell.exe -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -Command "<Script>"

0

As we can infer from the command, -ExecutionPolicy Bypass bypasses corporate execution policy restrictions.

After this stage, it falls back on the old reliable technique: retrieving another resource. As mentioned earlier, both the imported DLLs and the initial stage, before loading modules, contain bitmaps, which the malware uses as it sees fit throughout all stages.

0
0

To avoid boring you again, the module reads the bitmap from ResourceManager, decrypts it using XOR (xorshift32), and decompresses it with RtlDecompressBuffer. The final result is the extraction of a resource that is then processed to obtain an MZ header. This resource is subsequently invoked to load the code into the memory of the executable we previously observed in Roaming, rather than the executable currently being debugged.

0

What happens next is that execution is transferred to the executable dropped earlier. Remember that it is hidden and has read-only permissions, with the payload injected into the process memory.

Other interesting features include the self-destruction or escape mechanism. If the file TITANIC.TXT exists in the installation directory, the RAT detects it and executes ExitProcess. The filename can be changed in the builder, sorry for another spoiler. This can be used as a detection indicator for those who have not configured it differently. Otherwise, the presence of a TXT file in this path may also be suspicious, particularly when found alongside the executable.

0

As mentioned earlier, the most relevant aspect is the duplication of persistence mechanisms. In some cases, DarkVision can be observed persisting through registry entries, as seen in this stage, scheduled tasks, and/or BAT scripts in the Startup folder. This depends heavily on the campaign and the preceding layers present before payload injection. However, the builder itself already provides registry-based persistence. In some cases, samples have been found implementing persistence through two or more different methods, which is not particularly common.

Once the payload is in memory, we have reached the final stage and can begin to understand how DarkVision actually works.


_Payload

Moving execution and analysis to the RAT’s core, we find C++ code that is generally not packed. However, after extracting several samples through to their final stage, one recurring characteristic becomes apparent: a mismatch between the actual capabilities available and the libraries imported. We will resolve this shortly.

0
0

As mentioned, the payload commonly lacks the libraries and imports declared in the IAT. Therefore, unsurprisingly, the first stage of the payload generally focuses on obtaining additional capabilities at runtime. The first function uses LoadLibrary and GetProcAddress to perform the entire operation and retrieve the following libraries:

DLL Functions Main purpose
NTDLL.DLL 9 Native APIs (injection, anti-debugging)
KERNEL32.DLL ~110 Process, memory, and file management
USER32.DLL ~72 Graphical interface, keyboard hooks
GDI32.DLL 6 Screenshot capture (BitBlt)
ADVAPI32.DLL ~55 Registry, cryptography (SystemFunction036)
SHLWAPI.DLL 7 Path and string utilities
SHELL32.DLL 7 Application execution
OLE32.DLL 11 COM (UAC bypass, injection)
WINHTTP.DLL 14 HTTP communication (stealer channel)
WTSAPI32.DLL 1 Terminal Services sessions
WS2_32.DLL 20 TCP/IP communication (C2 channel)
GDIPLUS.DLL 14 Image capture (GDI+)
MSI.DLL 3 Installed software information
WINMM.DLL 10 Audio capture (waveInOpen)
DBGHELP.DLL 1 Debugging helpers
SECUR32.DLL 1 Network security
CRYPT32.DLL 1 Cryptography (CryptUnprotectData)

0

Among the libraries loaded, we can see that WS2_32.DLL is separate from WINHTTP.DLL. As another spoiler, the former is used for C2 communication, while the latter handles HTTP exfiltration.

Subsequently, the most common mechanism is mutex-based control, where the malware checks whether a mutex already exists and creates one if it does not. As another spoiler, these mutexes, which resemble HWIDs, can be modified directly in the builder, as we saw earlier. This means they are unique, at least theoretically. They also prevent duplicate execution and coordinate between instances.

0

These HWIDs are simply identifiers used to track different conditions during execution, such as whether the malware is installed or has the appropriate permissions. They are also used as a kind of checkpoint. For example:

{4A3426FC-C099-4018-817D-09893BA6B2F0}  >  Mode A (main installation)
{90575A5E-87EC-4BFB-BEAE-7CAC5AD73878}  >  Mode B (elevated execution)
{BAC5FF3F-A556-450B-96FD-4E546B2B4641}  >  Mode C (copy in ProgramData)
{3E33A834-DAFE-4555-814F-15E6533A0713}  >  Mode D (process relaunched by command)

0

Unlike other malware, this RAT does not rely on a single mutex. Instead, it can have up to three or four active mutexes, depending on the context, using different identifiers that may change between versions and/or campaigns. Nevertheless, repeated identifiers have been found across many samples. These mutexes can also be found at different stages of the payload, where they are checked or used for other purposes.

Essentially, this step allows the malware to prevent the sample from being executed again and maintain control over other events. It also acts as a safeguard against errors and future issues if another instance is already running, while providing a situational checkpoint. Additionally, the malware subsequently uses these IDs in connection with security descriptors.

0

We can also see that the malware uses registry entries to store information under the same identifiers.

HKCU\SOFTWARE\{36140C73-F5D3-486D-A06E-74B97C3D1B50}
    {297B1BF3-A9A9-4FCE-A043-80F440D55B4D}  >  Installation FileTime timestamp
    {34C40EE3-C7DD-4BA0-907A-6006301EF11A}  >  Original executable path

0

Subsequently, it performs an operation that is extremely important when the malware lacks the required privileges. Again relying on the HWIDs, it performs a UAC bypass + COM elevation technique, provided it detects that the current process does not have administrator privileges. It injects shellcode (SC) into explorer.exe, which can load OLE32.DLL and execute the second elevation stage.

0

Another important aspect is injection into LOLBins, where it uses Process Hollowing and takes advantage of different threads. Generally, it maintains threads for its most important functions, which are executed when necessary.

0

The process involves injection into one of three possible target processes using nine NTDLL functions that we saw being loaded in the initial stage. These include:

NtCreateSection          > Creates a shared memory section
NtMapViewOfSection       > Maps the section into the target process
RtlCreateUserThread      > Creates the remote thread without going through kernel32
NtUnmapViewOfSection     > Unmaps the process's original sections
NtClose                  > Closes handles
NtGetCurrentProcess      > References the current process
+ 3 additional functions (NtQueryInformationProcess, NtAllocateVirtualMemory,
                          NtProtectVirtualMemory)

Regarding the processes shown in the image, I am also listing them here:

explorer.exe   >  %WINDIR%\explorer.exe          (Primary target)
svchost.exe    >  %WINDIR%\System32\svchost.exe  (Fallback)
cmd.exe        >  %WINDIR%\System32\cmd.exe      (Fallback)

0

To perform the injection, it uses a typical multithreading coordination mechanism involving an event, again associated with an HWID, together with WaitForSingleObject, OpenEvent, and SetEvent.

hEvent = CreateEventW(NULL, TRUE, FALSE,
                       L"{D8ED75C4-0599-483F-AC1C-6892DBD9C037}");
// Injects into explorer.exe
WaitForSingleObject(hEvent, INFINITE);  // Waits for the child signal
// When the signal arrives → ExitProcess(0)

// Injected process (child, inside explorer.exe)
hEvent = OpenEventW(SYNCHRONIZE|EVENT_MODIFY_STATE, FALSE,
                     L"{D8ED75C4-0599-483F-AC1C-6892DBD9C037}");

SetEvent(hEvent);  // Signals the parent
// The parent receives the signal and exits

The final result is that the original process, which was previously running under an apparently random name, disappears, and activity continues inside explorer.exe. In reality, the code remains the same. It has simply taken another step and is no longer visible inside a process with a suspicious name, but rather inside a LOLBin that does not attract attention at first glance.

0

Continuing with the list of spoilers, one more won’t hurt, the builder itself also allows us to modify this behavior, letting us choose different LOLBins or run the malware within the current process.

0

As malware, it does not want to be detected or analyzed, so an anti-analysis routine was also needed. The payload includes events associated with these techniques, using a dedicated thread to monitor potential analysis activity.

For detection, it uses the typical CreateToolhelp32Snapshot, Process32First, and Process32Next sequence to capture running processes and compare them against an internal list of applications commonly used for malware analysis.

The list includes:

  • IDA
  • IDA Pro
  • Ghidra
  • Binary Ninja
  • Radare2
  • Objdump
  • x64dbg
  • OllyDbg
  • WinDbg
  • FlareVM
  • Retoolkit
  • Malcat
  • CAPE Sandbox

0

In addition to this, it implements other common sandbox timing checks (anti-sandbox techniques), sleeps for the same purpose, and standard NTDLL functions such as ProcessDebugPort.

Regarding communication, as mentioned earlier, we can identify two distinct channels: the C2 channel and HTTP exfiltration, although the latter will be discussed in the plugins section. As for C2 communication, DarkVision uses TCP. This activity is also visible in a separate thread, where it performs the initial checks. If it cannot establish a connection, it enters an infinite loop.

0
0

The RAT can use several options to establish a connection, either through hardcoded values visible in plaintext during analysis or through another plugin. In the first case, we can see how it establishes communication via SOCKS5.

0

In the Client Hello packet (640 bytes), it sends the client/victim identification. The string 477474 is a protocol version identifier that can be used as an indicator. The packet also contains:

offset  +0:   0x1000F (65583)  >  Magic / Protocol version
offset  +4:   "477474" (UTF-16LE)  >  DarkVisionRAT protocol version
offset  +84:  1/0  >  Administrator flag (IsAdmin)
offset  +88:  "%s [%d]" % (folder_name, PID)  >  Process identification
offset  +616: System data (OS version, local IP)

0

Once the connection attempt has been established, the RAT attempts to receive data every 10 seconds. If nothing is received, it attempts to restart the connection, causing the same function to execute again and, consequently, the same packets to be captured in an infinite loop.

If communication is successfully established, an entire plugin system begins executing to carry out the next stage. This stage is also related to the payload, but deserves an honorary mention due to its complexity and capabilities.


_Plugins

As we were discussing, the RAT’s actual operational capabilities do not reside solely in the main binary, but also in a network of plugins loaded into memory. This makes it difficult to trace all the execution paths during a forensic investigation due to the design implemented by DarkVision.

Within the builder itself, we can see that there is a Plugin Manager where we can load whichever plugins we want. This is technically quite interesting and sets it apart from many other RATs.

0

As you can probably imagine, and as we mentioned earlier, it relies on descriptors to handle plugins. Each descriptor contains an encrypted and compressed plugin and follows a loading process. Some of these plugins are embedded in the payload itself, and we will analyze one of them later (briefly, don’t panic). The steps involved are:

  1. Reads the plugin descriptor from the internal table.
  2. Decrypts it using block-based XOR with an incremental counter.
  3. Decompresses it using RtlDecompressBuffer (LZMA, without external libraries).
  4. Loads it as a PE into memory.
  5. Looks for exports (Initialize / UnInitialize / UnInstall).
  6. Calls Initialize(config, configSize, data, dataSize).
  7. Registers it in a global table.

0

Additionally, as you might have guessed from the previous image of the builder, it supports a dispatcher for loading additional plugins. Including every plugin in the binary would make it excessively large and difficult to manage, and could also trigger security systems.

This dispatcher can load plugins by performing three main functions:

  1. Check whether the plugin is already loaded in memory.
  2. Attempt to load it from ProgramData\*.DLL.
  3. Download it from the C2 in real time.

0

This functionality allows the RAT operator or buyer to add or update its existing capabilities whenever they want. Furthermore, all plugins have three key exports, which we have already seen:

Initialize()   > 1 for success, 0 for error
UnInitialize() > Stops the plugin
UnInstall()    > Removes the plugin and its artifacts

0

Like other RATs in its category, this one supports command codes that allow the operator to execute specific parts of the malware, such as performing a reinstallation, executing commands through ShellExecute, reinstalling persistence, and so on. While looking for these functions, I also found something interesting: the ability to establish reverse shells across multiple sessions, with up to 100 concurrent sessions.

0


_Credential Stealer Plugin

To focus on a more interesting component, it is worth taking a closer look at the module dedicated to stealing information. It shares clear similarities with other Stealer-type malware, which is less common for a RAT. RATs typically focus on exfiltrating basic information, registering the victim, and providing capabilities such as remote command execution and persistence. DarkVision goes much further.

When the malware installs a plugin, we can observe it in memory. In this case, the plugin provides capabilities to steal information from the system and the user.

0

This module injects itself into the browser and accesses information directly from memory. From there, it can retrieve information from the default browsers installed on the system, including Chrome, Brave, Opera, and others.

0

The main targets I identified are:

Target Path
Chrome \Google\Chrome\User Data\Default\Login Data
Brave \BraveSoftware\Brave-Browser\User Data...
Opera \Opera Software\Opera Stable\Login Data
Vivaldi \Vivaldi\User Data\Default\Login Data
Edge \Microsoft\Edge\User Data\Default\Login Data
Firefox %APPDATA%\Mozilla\Firefox\profiles.ini / logins.json
ThunderBird profiles.ini / logins.json
FoxMail 7.2 HKCU\SOFTWARE\Aerofox\FoxmailPreview
Wi-Fi WlanGetProfileList + WlanGetProfile

0

Once operational, we can expect to see access to the different paths and files associated with each of the applications mentioned above. Its scope is not limited to browsers, as it also targets email clients, network information, and more.

0

The fact that the plugin operates within the process gives it access to the correct user context for DPAPI, addressing everything related to app-bound encryption without needing to know the AES key.

We can also find the use of SQL, which is also common in Stealers when accessing the Login Data files used by each browser.

0

The information obtained by this plugin is parsed into a .txt file using a format that is quite recognizable in the binary, containing fields such as Website, Username, Password, and so on.

<Browser>-YYYY-MM-DD-HH-MM-SS-(00001).TXT

0
0

Regarding exfiltration, as mentioned at the beginning, it does not use the same channel as the C2, which relies on TCP. Instead, it uses WinHTTP.

0

The independence of the exfiltration channel from the TCP control channel is important, as blocking the C2 port does not prevent the plugin from independently stealing credentials. The Stealer can exfiltrate data over standard HTTPS even if the firewall blocks the TCP port configured by the operator.

To sum up, without making this section any longer, the RAT’s existing capabilities, combined with those it can gain through plugins, are extensive. I have tried to break down most of them, or at least the ones I considered most important, in a straightforward way. However, the plugins and their overall capabilities could easily warrant a separate investigation. The combination of standard RAT features with components borrowed from other types of malware is genuinely concerning and unusual.


_The RAT from the Other Side & Capabilities

If you thought this was over, you were wrong. Whenever possible, it is important to match the actual tool with the extracted malware to understand its expected behavior in as much detail as possible.

The malware usually comes with several libraries and an executable that acts as both the builder and the server, allowing us to configure whatever we want. The main panel primarily lets us configure the port on which we want to accept requests and create the builder.

0

As for the builder, to provide a quick summary, it offers the configuration options we have seen throughout the analysis. Virtually everything is configurable, including paths, names, mutexes, whether the malware should inject itself and into which processes, persistence mechanisms, and much more.

0

Once everything is configured as desired, it generates a binary containing the installation message, the information about the C2 it will contact, the mutexes we configured, and so on. Essentially, this is our customized RAT, as it would appear to a DarkVision operator or buyer.

0

As you might imagine, its behavior and capabilities are virtually identical across different payloads. The main difference is that the strings clearly reveal the new information we have added.

0

Speaking of capabilities, and to wrap up this section for the geeks (always welcome on my team), I think it is worth reviewing the capabilities I identified after analyzing different versions, along with those documented by the developer. Keep in mind that, as mentioned earlier, I have not covered everything. This comparison is the best way to get a quick overview of the RAT’s entire arsenal.

Declared capability Observed Evidence
Process Injection (Explorer, SvcHost, Cmd) Confirmed Section-based hollowing + RtlCreateUserThread
UAC Bypass Confirmed COM Elevation Moniker
Batch update of bots Confirmed Commands from the payload
Persistence (Registry / Autostart / Scheduled Task) Confirmed HKCU\Run + obfuscated PowerShell + ProgramData
Six installation locations Partial ProgramData and %APPDATA% observed
Melting of executables Confirmed Dropper self-deletion behavior
Custom Windows Defender Exclusions Confirmed Similar to what was observed in the July 2024 Zscaler campaign
Self-destruct when named executables detected Confirmed Watchdog thread with action flags A/B/C
HTTP/S-Based File Logger (new in March 2026) Not observed N/A
Remote Speaker Capture / Local Playback Inferred WINMM.DLL (10 functions loaded)
Remote Connection Monitor (TCP/UDP) Inferred WS2_32 + WINHTTP imports
Extension Manager (custom 64-bit features) Not observed Compatible plugin architecture
Instant Downloader (payloads at bot start) Confirmed On-demand download from the C2
Access Control (block input / hide icons) Inferred USER32.DLL (72 functions loaded)
Instant Password Recovery via HTTP/S Confirmed Stealer plugin with WinHTTP channel
Password Recovery (Chrome, Opera, Brave, FoxMail7+ IMAP, Firefox, Vivaldi, Wi-Fi) Confirmed Full analysis of the Stealer plugin
File Explorer (upload, download, thumbnail) Confirmed FindFirstFileW + file transfer commands
Screen Capture Confirmed GDI32 (6 functions) + GDIPLUS (14 functions) + BitBlt
Remote Shell Confirmed Handler with 100 concurrent sessions
Download & Execute (batch execution) Confirmed Payload function with commands
Drop Files (from URL) Confirmed WinHTTP downloader
Reverse Proxy Confirmed SOCKS5 with and without authentication
Remote Browsers (Chrome, Edge, Brave) Confirmed USER32.DLL + GDIPLUS context
Remote Desktop (keyboard + mouse) Confirmed WTSAPI32 + USER32
Webcam Capture Inferred GDIPLUS + CoCreateInstance context
Send Message (wait for response) Inferred USER32 MessageBoxW
Live Keylogger (hook-based, x64) Confirmed Dedicated thread + SetWindowsHookEx
Kill Switch (AFK protection) Confirmed TITANIC.TXT + watchdog thread
Play Sound (WAV) Inferred WINMM.DLL + waveOutOpen
Web Browser History Viewer (Chrome, Edge, Opera) Confirmed SQLite accessible from the browser process
Microphone Capture (with logging) Confirmed WINMM.DLL + waveInOpen / waveInRead
Service Manager (create/delete/start/stop) Not observed N/A
Program Manager (list/uninstall MSI) Inferred MSI.DLL (3 functions loaded)
Clipboard Editor (get/set + logging) Confirmed ENCMARK strings in the Stealer
System Control (lock/reboot/shutdown) Confirmed USER32 + shutdown APIs
Wallpaper (get/set) Inferred USER32.SystemParametersInfoW
Window List (visibility, caption, state) Inferred USER32 EnumWindows
Memory Dump (MDMP format) Inferred DBGHELP.DLL (1 function loaded)
Offline Keylogger Not observed N/A
Process Manager (list/terminate) Confirmed CreateToolhelp32Snapshot + Process32First/Next
Registry Editor (remote registry) Confirmed RegCreateKeyExW / RegSetValueExW
Text To Speech (remote voice) Not observed N/A

As you can see, we were able to identify most of these capabilities by analyzing the different payloads. However, some depend on external plugins, while others are functions I simply did not investigate in depth (you’re welcome for saving you another ten pages). In essence, this demonstrates that DarkVision is not just another RAT, as its capabilities combine features from different types of malware, as mentioned earlier.


_Intel

DarkVision began offering its services between late 2019 and early 2020, primarily through HackForums, which is essentially one of the forums with the highest traffic. Its price was around $40 USD, with promises of lifetime support and updates included in the price. This price has increased over time, along with its features, as the TA continues to post regular updates. It is now sold for around $60 USD, payable in crypto, of course.

0

As before, the developer continues to share videos, images, and demonstrations of how DarkVision works with its audience. The developer has remained active to this day, with interactions observed in October 2026.

0

The developer has used different email addresses, such as tooldev@tutamail.com and toolforge@proton.me, to communicate with customers. An analysis of these addresses reveals that the developer has, or has had, accounts on Russian platforms, as well as connections to CTF and cybersecurity platforms and Telegram, which we will discuss later. Some of the most relevant platforms are:

Platform Relevance
247CTF Security CTF platform
CodeChef Competitive programming
Kwork.ru Russian freelance platform
RuTracker.org Russian content tracker
getmonero.org Monero forum
Ko-Fi Payment platform
Telegram Registered account

The platforms associated with these accounts suggest that the developer is not simply a script kiddie, as both accounts have been associated with cybersecurity-related activities for many years, often with a focus on Russia. However, this is not enough to support a plausible attribution.

Using the older email address, the first one the developer used, we can also find accounts on platforms unrelated to DarkVision that have been active since February or March 2026, along with parallel projects associated with the same email address previously used for DarkVision.

0

Regarding Telegram, which we mentioned earlier, several bots have been identified that follow the same pattern. These are later linked to the model used by other resellers with the same format. Based on the RAT’s style and comparisons with other malware, we understand that after making a payment, customers may receive real-time access to privileged information and support through Telegram. This is a fairly common MaaS model, similar to the one used by Snake.

0


_Sales

When it comes to sales, the scope is clear: the developer uses specialized forums to advertise services and sell the product. However, the developer historically also operated a website that remained active for years before becoming unavailable in the summer of 2025.

0

In addition to sales by the main developer, resellers and other portals have also been identified offering DarkVision alongside other tools, such as Razor and Stage One, which clearly complement or accompany our RAT.

0

The GraySec website was active during 2024 and 2025. It used a similar architecture, relying on Telegram and other channels such as Twitter. DarkVision has therefore operated not only through an independent developer and seller, but also through partnerships with other portals to increase the tool’s visibility. This is fairly common in the MaaS ecosystem, where sellers leverage the wider Dark Web and Telegram markets.

0

Similarly, Telegram groups have been observed offering DarkVision alongside other hacking tools and malware, demonstrating its strong position in the market.

0

DarkVision has also appeared in cross-promotional mentions within markets selling FUD tools, where it has been used as an example to promote or improve the evasion capabilities of RATs and Stealers. Our subject is among the tools listed in these discussions.

0


_Outro

Another interesting topic is the market for cracks and leaked software. This type of malware often suffers code leaks, or researchers create cracks to distribute it, whether for academic purposes or resale.

The sale of DarkVision v2.35 is well documented, and several resellers took advantage of this window of opportunity. There were also some GitHub repositories offering fully functional older versions of the RAT.

0

To conclude our analysis of DarkVision, we should highlight its high degree of modularity and the resulting capabilities discussed in the previous section. From a security perspective, this is alarming, while from an analyst’s perspective, it is interesting. The RAT can inject itself, drop files, establish persistence, load modules, detect sandboxes and analysis tools, and create multiple communication channels in addition to its exfiltration channel, among other capabilities.

It offers a platform for around $60 in an already crowded market. However, Threat Actors have incorporated it into their operations over the past six years, and it continues to receive updates several times a year. It is gaining users while attracting less attention than some competitors, yet it remains just as lethal, if not more so.

Finally, I would like to thank you for reading this analysis and for supporting me :)


_Detection Opportunities

The rules are written in pseudocode so that they can be adapted to different security systems

• [TA0002][T1059.005] Execution of VBS with payload download

(Process) wscript.exe (Command) *\.vbs > (Child-Network) *WinHttpRequest* | *XMLHttpRequest* >  (Child-File) *.exe | *.dll (written in %TEMP% | %APPDATA%)

• [TA0002][T1059.007] Execution of JS with payload download
(Process) wscript.exe (Command) *\.js | *\.jse > (Child-Network) outbound connection > (Child-File) *.exe | *.hta (written in %TEMP%)

• [TA0002][T1059.001] PowerShell with path reconstructed from an ASCII array (ClickFix / persistence)
(Process) powershell.exe (Command) *-NoProfile*-ExecutionPolicy*Bypass*-WindowStyle*Hidden*ForEach-Object*[char]*

• [TA0005][T1055.002] Injection via NtCreateSection + RtlCreateUserThread in lolbin
(Source-Process) <RandName>.exe (Non-Common Path) > (API-Call) NtCreateSection + NtMapViewOfSection + RtlCreateUserThread > (Target-Process) explorer.exe | svchost.exe | cmd.exe

• [TA0011][T1071.001] Outbound network connection from explorer.exe to a non-standard port
(Process) explorer.exe > (Outbound-Connection) Destination-Port NOT 80 | NOT 443 | NOT 8080 > (Destination-Port) 1783 | 8120 | <Non-Standard port>

• [TA0005][T1036.005] Process injected into explorer initiating unusual activity
(Parent-Process) NOT winlogon.exe | NOT userinit.exe > (Process) explorer.exe

• [TA0003][T1547.001] Writing to the Run key with an obfuscated PowerShell command
(Registry-Write) *\Software\Microsoft\Windows\CurrentVersion\Run > (Value-Data) *powershell*-ExecutionPolicy*Bypass*[char]*

• [TA0003][T1547.001] Creation of a tracking key with a hardcoded GUID
(Registry-Write) *\SOFTWARE\( +Regex {[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}}  )

• [TA0005][T1562.001] Adding an exclusion to Windows Defender for the RAT executable
(Process) powershell.exe | MpCmdRun.exe > (Command) *Add-MpPreference*-ExclusionPath*%APPDATA%*|*%ProgramData%*

• [TA0006][T1555.003] Access to Chrome/Chromium browser login data from an external process
(Process) NOT chrome.exe | NOT brave.exe | NOT msedge.exe > (File-Access-Read) *\Google\Chrome\User Data\Default\Login Data |  *\BraveSoftware\Brave-Browser\User Data\Default\Login Data | *\Microsoft\Edge\User Data\Default\Login Data

• [TA0006][T1555.003] Writing a credentials file to %TEMP%
(File-Create) %TEMP%\KEYFILE.TXT (File-Create) %TEMP%\Chrome-*.TXT | %TEMP%\Firefox-*.TXT | %TEMP%\Brave-*.TXT

Regex for credential files by browser:
(File-Create) Path-Regex: %TEMP%\\(Chrome|Brave|Firefox|Opera|Vivaldi|Edge|FireFox)-\d{4}-\d{2}-\d{2}-\d{2}-\d{2}-\d{2}-\(\d{5}\)\.TXT

_TTP

[TA0001][T1566.001] Spearphishing Attachment
[TA0001][T1566.002] Spearphishing Link
[TA0002][T1204.002] User Execution: Malicious File 
[TA0002][T1059.001] PS persistence script with ASCII array path reconstruction
[TA0002][T1059.003] Shell with cmd.exe as injection target 
[TA0002][T1059.005] VBS first-stage loaders 
[TA0002][T1059.007] JS/JSE first-stage loaders 
[TA0003][T1547.001] Registry Run Keys with obfuscated PowerShell command 
[TA0004][T1548.002] COM Elevation Moniker via CMSTPLUA
[TA0005][T1027] Obfuscated Files or Information
[TA0005][T1027.002] Software Packing
[TA0005][T1027.010] PowerShell path reconstruction from [char] ASCII arrays 
[TA0005][T1140] Deobfuscate/Decode Files or Information 
[TA0005][T1055.002] Process Injection: Portable Executable Injection
[TA0005][T1562.001] Impair Defenses: Disable or Modify Tools with custom Windows Defender exclusions for installed path 
[TA0005][T1222.001] DENY Delete/Write/ChangePermissions/TakeOwnership on installed executable 
[TA0005][T1564.001] Hidden + System + ReadOnly attributes on installed executable
[TA0006][T1555.003] DLL injection into browser process
[TA0007][T1497] CreateToolhelp32Snapshot in anti-Debug/Analysis thread 
[TA0007][T1082] OS version, local IP, admin status, PID collected in C2 client hello 
[TA0007][T1012] HWID derived from volume serial number, registry read for installation state
[TA0010][T1041] WinHTTP POST with hwid/logfoldername/uploaded_file fields
[TA0011][T1095] TCP protocol with proprietary framing and handshake 
[TA0011][T1573] AES-128 session key negotiated during handshake via CryptGenRandom
[TA0011][T1090.001] SOCKS5 with and without authentication

_IOC

2a67ec9b4db3954e30b1fa26fe87dea4f89ce4d011415e00d48f3200c9fe1f88
6700075bf252fbc09453df6f543d36bbd7f7a011ed2b5bf7fc86df1c4b634c8d
B1c7d89f04a4a9a2729f6030b581e5a7cfb2afe766b36c80cfad5ece7ecccfed
Fb76ed9669c3c728806fa4d349e46bcec2e51f474ac829269e3713f3909c051b
70aacb6ae4c62d3913af232c5f67f17f532c8379adfa0d1ab0185620fb62627f
9a0369f05cd24b818b5885b3866643d168f6f4216724641ca540613972e9e682
8edac9f53baffdb318253b4874a7776339c322e46ca88f32c169199556109550
92ad02bd0ce9160a8ad87ffd7fba019a366b4e70056b3e8bd35c706abdb4a2ff
Ac24f6d0da9372825d16e75a76ec2f43d185a3ab6ecbb1df6d7be482e4ea0412
6977899b07c0c789fd516de82f436698fde6b53060404905dca561a41cd59290
95a67324a3b360de5e1012587af185aa511e37a347c45ff0ca0a897ca95d25a8
9f29563ca323046c2ff4f7ee64c298221dd03a4cd54fc1b56c875b293cfe03d6
7e52b86d3a300523af18b87223dd50d104d76b1e32a664910cda4d90917e495d
12b3d39284068b43a531f79489480aa1d966b3b57fadde97306fde9ad498fc17
c158a126ea5e8a9cd99d1109c43ee7b7d18cb2dbf7aa7d0dee841a18f68d39a9
E834413cb99b1a3e847717d41691802feae9b9234004eba542c8e244ac8d6674
cb1492326724d3083f2796607dc881ff5bdb8ee4723b02849c94cd4d482c1c31
ac24f6d0da9372825d16e75a76ec2f43d185a3ab6ecbb1df6d7be482e4ea0412
92a4270557ad29e087495c1ffc93bea0e03cc16943e8836ea708d4e428eae088
71fcb77dc307104eb0c9365b86f690c64d48dba6f23057e2fdfb9e31f9b6a11a
7d300eb1d4889aa70e74b2be67a76d6494c3840ffc2fda597b3dac711f57a999

103.20.235.24
23.95.222.239
107.172.13.211
77.83.39.177
62.60.226.140
158.94.211.222
91.92.240.254
104.37.175.235
196.251.115.178
⬆︎TOP