Origin Story
Vect is a newly observed RaaS operation that emerged in December of 2025, with affiliate recruitment and victim postings following shortly after in January 2026. Following the 19th of March 2026 Trivy/LiteLLM supply chain attack conducted by TeamPCP, in which ~340 GB uncompressed data was stolen, Vect announced on the dark web forum “Breached” that they would be partnering with TeamPCP.
Vect recently issued access keys for all users that are on their forum on April 18th 2026, allowing anyone and everyone to pick up ransomware, and start doing some cybercrime. Unfortunately for the affiliates they hoped to attract, Vect has failed to build ransomware that works. In fact, it completely fails at its core purpose.
This post is a technical breakdown of how we got here, including the odd DEVMAN 3.0 branding, the encryption bugs, the lateral movement code, and what this actually tells us about where Vect and TeamPCP operations may be headed.
The dashboard of Vect Ransomware’s Data leak Site (DLS) shows 2 victims that were labelled as compromised from the Trivy supply chain attack.
We know with a high degree of confidence that TeamPCP and Vect’s partnership is actually legit (xpl0itrs-affiliated account confirmation, Unit42/Palo Alto’s analysis, and victim data on Vect’s DLS traced to the TeamPCP Trivy breach). And so, the BreachForum chat and subsequent keys weren’t someone opportunistically trying to leverage TeamPCP’s recent clout.
Vect announces partnership with TeamPCP 6 days after the Trivy compromise
The Vect administrator stated “every single BreachForums member will receive their own personal Vect Affiliation Key”, this means that anyone with a BreachForums account can start being a ransomware affiliate, without the need for any proof of skill, money from previous ransomware success, or track record, unlike other RaaS platforms.
Following this announcement, on April 16th Vect began DMing users with their own affiliate keys that they can use to sign up and create an account on the Vect dashboard.
Announcement saying that affiliate keys are being released to all users
I received a key in my accounts private messages and subsequently created an account on the Dashboard in order to obtain a sample.
After creating an account with the key, we can login to the dashboard and get a view of what a real affiliate would see.
Vect Ransomware Affiliate Panel
Moving to the “Builder” tab, affiliates are required to add the victim’s name that they have compromised before generating the ransomware binary itself. We created a fake business name and built a Windows locker. The Linux and ESXI lockers threw HTTP Error code 500 when I tried to generate them.
Victim folders list
Builder Panel
The Vect 2.0 Ransomware – Malware Analysis
The generated executable is 1.39MB in size, compiled with GNU ld / MinGW-w64 and not packed. The .text entropy is flat and both libstdc++ / libsodium source path strings are intact in .rdata, making static analysis straightforward.
DetectItEasy Report
After loading the malware into IDA and viewing the “Imports” area, we can see multiple imported libraries that are used for a wide variety of different functionalities.
Imports list
As seen in the image above, the malware imports multiple Windows libraries which already give us a decent view of its features, for example the “MPR” library and “NETAPI32” libraries are used to discover network shares that can also be encrypted, alongside other computers on the network that the malware could spread to.
Interestingly, there is no Windows CryptoAPI or CNG functions like BCrypt, CryptEncrypt, or CryptImportKey. The malware instead links “libsodium” for all cryptographic operations, which is a portable crypto library designed for encryption, decryption, signatures, and password hashing.
Does the DEVMAN 3.0 reference tell us anything?
Looking at the strings in the malware, we can see a reference to a “DEVMAN 3.0” string, a different RaaS malware which is a derivative of the “DragonForce” ransomware, it is referenced by the operator-facing `–verbose` console banner. The lateral movement code also generates scheduled tasks and services with names prefixed with “DM” followed by four ransom uppercase characters (DMABCD for example).
This naming pattern has not been previously documented in DEVMAN 1.0 or DEVMAN 2.0 reporting, while these artifacts suggest continuity with the DEVMAN operator, they are trivially plantable and cannot be used to link Vect to prior DEVMAN operations.
This kind of naming reuse could project a false maturity by using the identity of a more established strain and potentially mislead analysts during attribution or deliberately introduce noise into threat intelligence reporting.
Strings list showing “DEVMAN 3.0” appearance
Anyways, the “DEVMAN 3.0” string leads to a console banner that is shown if the “–help” argument is passed, displaying different options and features that the affiliate can use when deploying the ransomware.
Operator commands list
A description of each of the flags can be found below:
| Flag | What it does |
| -h, –help | Allocates a console and prints the “DEVMAN 3.0” banner with all flags, then exits cleanly |
| -v, –verbose | Allocates a console with CONOUT$ and enables real-time logging: thread counts, drive queuing, per-file paths, encryption stats, and the “!!!_READ_ME_!!!.txt” completion banner |
| -p, –path <dir> | Restricts encryption to a single directory instead of enumerating all drives and mounted shares |
| -c, –creds <base64> | Accepts base64-encoded Active Directory credentials, which are injected into the PowerShell lateral movement template for remote CIM sessions, WMI, scheduled tasks, and sc.exe calls |
| –gpo | Enables Group Policy Object-based spreading to domain joined machines, enabled by default |
| –no-gpo | Disables GPO spreading |
| –mount | Enumerates all network shares via WNetOpenEnum/NetShareEnum/NetServerEnum, mounts them with WNetAddConnection2A, then queues them for encryption alongside local drives, enabled by default |
| –no-mount | Skips share enumeration and mounting, only encrypts local drives |
| –stealth | After encryption completes, XOR decrypt a command string, builds a cmd command with the malware’s own path, which deletes the malware from disk, enabled by default |
| –no-stealth | Malware remains on disk after execution |
| –force-safemode | Runs `bcdedit /set {default} safeboot minimal` to reboot the machine into Safe Mode, where most AV/EDR agents are not loaded, allowing encryption to proceed. Only fires if the malware detects it is NOT already in Safe Mode and has admin privileges |
After finding the console help banner and viewing cross references that reference this function, we find the `main()` function, which is the orchestrator for all of the ransomware’s major capability.
main() Function graph
Capabilities
Prior to the encryption, the ransomware disables Windows Defenders real-time protection via PowerShell. The command is stored as a 163 byte XOR encrypted string.
PowerShell command, XOR encrypted
The XOR decryption loop uses a rotating 8 byte XOR key (`0x497DF58F9D6D63CD`) to decrypt the command, which it then passes to `CreateProcessA` with the `CREATE_NO_WINDOW` flag.
The XOR Decryption loop and CreateProcessA execution
The decrypted command is a simple PowerShell command that as mentioned, disables Windows Defender real-time detection:
`powershell -Command “Set-MpPreference -DisableRealtimeMonitoring $true -DisableBehaviorMonitoring $true -DisableIOAVProtection $true -DisableScriptScanning $true`
Alongside that, it should be mentioned that the malware also disables Windows Task Manager to prevent victims from opening Task Manager to kill the encryption process
Following this, the malware also uses `vssadmin` to delete shadow copies with another XOR encrypted string. It also does a 30 second timeout to ensure shadow copies are fully deleted before the encryption begins.
Same XOR encryption/decryption logic
Executing the `vssadmin` command via CreateProcessA and delaying by 30 seconds (0x7530 in decimal is 30,000 milliseconds, 30 seconds)
The key used in the decryption is `0xCB7BFF79F115AB07`, and the resulting command that is executed is:
`vssadmin delete shadows /all /quiet`
The malware also modifies the registry to register itself in the Safe Mode whitelist, and the `CurrentVersion\Run\` key. When a machine reboots into Safe Mode, Windows only loads services/drivers listed under `SafeBoot\Minimal\`. By creating its own entry with the value `Service` the malware essentially tells Windows “I’m an allowed service in Safe Mode”. Then the `CurrentVersion\Run\` entry ensures it actually starts up.
The XOR encryption for the strings is the same process we have mentioned twice already, so we won’t go over it again, the only difference after all is the key used for decryption and the XOR encrypted string data itself.
Graph showing the registry modifications
| Registry path | Value | Data |
| HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\Minimal\<name> | (Default) | Service |
| HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\Network\<name> | (Default) | Service |
| HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run | Binary name | Binary location |
The Encryption Mechanism (and a funny bug!)
Regarding the actual encryption, the malware uses libsodium’s ChaCha20-IETF stream cipher for file encryption. Each chunk is encrypted with a 32-byte key derived when the malware starts and a 12-byte random nonce generated via libsodium’s `randombytes_buf` function. No authentication tag (Poly1305 or other) is appended, meaning encrypted files have no integrity protection.
Files are renamed to <original>.vect via `MoveFileExW` before encryption begins. For files under 128 KB, the entire contents are encrypted. For files over 128 KB, the malware utilises intermittent encryption, and only four 32 KB chunks are encrypted at offsets 0%, 25%, 50%, and 75% throughout the file. This is for speed optimisation common in modern ransomware, allowing fast encryption of large files while still rendering them unusable. The 12-byte random nonce is also appended to the end of each encrypted file.
The first function to look at is a function which we have renamed to `pre_encrypt_kill_and_disable()`, this is a simple function which just stops targeted services, kills processes, and as mentioned before, disables task manager.
Pre-encrypt function that kills targeted services and processes
The following table is a list of the stopped services and killed processes from those two functions:
| XOR Decrypted name | Description |
| svc$ | Generic service marker (likely prefix matched) |
| sophos | Sophos AV |
| backup | Backup services |
| ccEvtMgr | Symantec/Norton Event Manager |
| SavRoam | Sophos Anti-Virus roaming |
| QBCFMonitorService | QuickBooks company file monitor |
| YooIT | YooIT Remote Management |
| mepocs | MailEnable POP connector |
| MySQL57 | MySQL 5.7 database |
| memtas | MailEnable |
| veeam | Veeam Backup |
| GxVss | Commvault VSS provider |
| GxBlr | Commvault Baseline Reporter |
| GxFWD | Commvault Firewall Daemon |
| GxCVD | Commvault Communications |
| GxCIMgr | Commvault Client Interface Manager |
| DefWatch | Symantec DefWatch |
| ccSetMgr | Symantec Settings Manager |
| RTVscan | Symantec Realtime Virus Scanner |
| QBFCService | QuickBooks File Copy |
| QBIDPService | QuickBooks IDP |
| YooBackup | YooBackup |
| MSSQLSERVER | Microsoft SQL Server |
| MySQL80 | MySQL 8.0 |
| wbengine | Windows Backup Engine |
| sql.exe | SQL Server |
| oracle.exe | Oracle Database |
| outlook.exe | Microsoft Outlook |
| winword.exe | Microsoft Word |
| firefox.exe | Firefox Browser |
| thunderbird.exe | Thunderbird Mail Client |
The next interesting function is used to launch the encryption threads. This is a lengthy function that calculates thread counts, creates the scanner and encryptor threads, then waits on them to finish with `WaitForMultipleObjects`.
The scanner itself is just a simple function that walks directories with `FindFirstFileW / FindNextFileW` and pushes these paths into a queue.
Seen below is the function for the scanner and encryption threads.
The function then uses `WaitForMultipleObjects` to wait for the scanner threads and encryptor threads to finish.
Looking at the actual encryption thread function, we can see the call to the actual `encrypt_single_file` (this has been renamed to make it easier to read).
Encryption thread function, calling the encrypt_single_file function
Why you definitely shouldn’t pay Vect for their decryption keys!
Moving into the `encrypt_single_file` function, which we have renamed in IDA, we see a clear two-path encryption mechanism. The function first renames the target file by appending the “.vect” extension via MoveFileExW as mentioned previously.
File rename prior to encryption. Appended with “.vect”
The function then check whether the file is bigger or smaller than 128 KB and, as mentioned, any files below this threshold are entirely encrypted. Conversely, files above this threshold are encrypted in four 32 KB chunks at offsets 0%, 25%, 50%, and 75%.
Check: Is filesize less than 128 KB? If yes, encrypt entire contents
However, there is a critical bug. Each of the four chunks is encrypted with a unique randomly generated nonce, but all four calls write their nonce to the same local variable, `Buffer` (seen in blue just after the WriteFile).
However, there is a critical bug. Each of the four chunks is encrypted with a unique randomly generated nonce, but all four calls write their nonce to the same local variable, `Buffer` (seen in blue just after the WriteFile).
Check: Is filesize more than 128 KB? If yes, encrypt in four 32 KB chunks
After the encryption loop completes only a single 12-byte footer is appended to the file, which contains ONLY the last nonce. Therefore, the nonces for chunks 1-3 are permanently lost, and even with the correct decryption key, three of the four encrypted regions can NOT be recovered.
Overall, this means that for any file larger than 128 KB, paying the ransom and receiving a working decryptor from a Vect affiliate would still only recover 25% of the data, the remaining 75% is destroyed and irrecoverable.
Alongside this bug, a second critical bug exists in the same function. The I/O buffer used for file encryption is allocated with VirualAlloc at a size of 32 KB (same size as the chunks). When files are over 128 KB, the ransomware correctly caps each read at 32 KB. However, when files are smaller than 128 KB, the ransomware passes the file size directly to ReadFile with no bounds check. Therefore, for any file that is between 32 KB and 128 KB, a buffer overflow is caused, which makes the read operation fail silently.
Second bug, no file size cap
Bug fixed in the “larger than 128 KB” encryption routine
Overall, this means that the file is renamed to .vect and a 12-byte footer of uninitialized stack garbage is appended (which can be easily removed), but the contents themselves are never actually encrypted. The original data remains plaintext.
To prove this, I created multiple random text files with “ABCDEDFGH” inside them:
| File Name | File Size |
| “test_tiny.txt” | 18 KB (will be fully encrypted) |
| “test_small.txt” | 64 KB (will NOT be encrypted at all) |
| “test_large.txt” | 256 KB (will be encrypted in four 32 KB chunks) |
| “test_large2.txt” | 1 MB (will be encrypted in four 32 KB chunks) |
After running the ransomware, we can see Vect “encrypted” all the files (see .vect).
4 different size test files, all “encrypted”
And here you can see the difference between Vect Ransomware “encrypting” a 64 KB file, and encrypting a 18 KB file. On the right, the Vect Ransomware running, and on the left, our 64 KB test file being untouched.
However, our 18KB file, was fully encrypted
The encryption itself is skipped entirely due to this bug.
Following this, I thought while I was inside my VM I would also show what the 128 KB+ files look like when they are encrypted.
The 256 KB test file, encrypted in four 32 KB chunks – 75% of this data is completely unrecoverable due to the nonce overwrite bug, only the last chunk at the 75% offset is recoverable
And I also wanted to check to see if there actually was a Poly1305 MAC tag in the encrypted files, as mentioned originally by the Vect developer/operator.
Vect developer claims Poly1305 AEAD
No 16-byte MAC tag found.
Well… ¯\_(ツ)_/¯
In a nutshell, the only files that Vect can actually decrypt and restore, are files under 32 KB. Any files between 32 KB and 128 KB are never encrypted, just renamed to .vect with a 12-byte footer of uninitialized stack data, that can easily be removed. Files over 128 KB are encrypted in four chunks, but three of the four nonces are overwritten by a single local variable, rendering only the final chunk at the 75% offset decryptable. The remaining 75% of encrypted data is permanently destroyed.
Lateral Movement Techniques
The ransomware also utilizes a toolkit of lateral movement commands via PowerShell; they are all viewable in plaintext and include the following:
| Method | Protocol | Execution |
| WinRM CIM ScheduledTask | WinRM (TCP 5985 / 5986) | Register + Start scheduled task as SYSTEM |
| DCOM CIM Win32_Process | DCOM (TCP 135 + dynamic) | CIM session over DCOM, create process |
| WMI Win32_Process | WMI (TCP 135 + dynamic) | Invoke-WmiMethod process creation |
| MMC20.Application DCOM | DCOM (TCP 135 + dynamic) | ExecuteShellCommand via MMC COM object |
| Remote schtasks.exe | SMB + RPC | schtasks /create /run /delete as SYSTEM |
| WinRM Invoke-Command | WinRM (TCP 5985 / 5986) | Remote PowerShell scriptblock |
| Remote sc.exe service | SMB + RPC | sc.exe create + start + delete service |
All task/service names use the “DM” prefix as mentioned before with 4 random uppercase letters, credentials come from the `-c/–creds [base64]` CLI flag as mentioned, and all methods run with `-EA Stop / 2>$null` flags, they fail silently and try the next method.
Detonating the Ransomware
After all this, I decided to run the ransomware on my FlareVM to see what it looks like, and I noted a few things:
- Vect Ransomware is very slow, it took multiple minutes while I was testing it to encrypt 18,000 files, in comparison, Lockbit’s benchmark is around 25,000 files every minute
- The ID does not seem to be generated based off the ID that is given when you create a new victim folder, it is the same every time, and the .onion/chat/[ID] endpoint to go to the “chat” for negotiations, throws a 404…
- The only other “backup” contact is a hardcoded qTox address, which is not possible to change in the panel’s configuration.
And here’s where the betrayal comes in. Considering that after deploying the ransomware, the “!!!_READ_ME_!!!.txt” note includes a link to the chat to negotiate that just throws a 404 error, this could mean Vect are trying to use their affiliates to do their dirty work for them, while simultaneously cutting them out of the deal.
Why did they adopt this strategy?
When we consider where Vect came from, how they partnered with TeamPCP, and how this “open RaaS” model came to be, at first, something doesn’t add up. Why would arguably one the most prolific financially motivated threat actors in 2026 pivot away from doing what they’ve done best to partner with what looks to be a novice ransomware operator that fundamentally doesn’t work?
One explanation is that TeamPCP, while riding the momentum of the Trivy/LiteLLM supply chain campaign, saw a window to pivot from access brokering to ransomware operations, and therefore moved faster than their infrastructure could support. The open affiliate model and handing builder access to every BreachForums member regardless of skill mirrors the playbook of more prominent actors like Lockbit, but without any of their technical maturity. Lockbit spent years working on their encryptor before opening the gate to affiliates, whereas Vect have gone straight to opening the gate to anyone.
The DEVMAN 3.0 branding is also somewhat telling. Since the code or functionality shows no overlaps, this doesn’t seem like iteration, it seems like someone adopting a name to imply lineage that they don’t have, or a developer on their third rewrite who still hasn’t learned to bounds-check a buffer. The result is a ransomware operation where the access is real but the monetisation is broken. TeamPCP can get the ransomware through the door, but after that, they’re essentially conducting a wiper attack and calling it extortion.
What’s next?
For defenders, the irony with these bugs is that Vect’s incompetence makes it more dangerous. A functional ransomware operation at least would offer the theoretical possibility that the victim data can be recovered through payment. Vect’s operation removes that option entirely. Organisations hit by Vect face data destruction with no recovery path, while also being delivered by operators who may not even understand that the ransomware itself is broken.
Overall, the supply chain attacks were real, the access they gathered from those attacks was real, and the victims on Vect’s leak site are traced to those campaigns. But the tooling itself just isn’t ready for what the operation is trying to be. Whether it eventually gets there will be interesting to see. It will certainly be worth tracking whether Vect will clean up their act, privatise the affiliate access, rewrite the code, and actually come back with something better. Because if their 2026 success in gathering initial access credentials via major supply chain attacks can be replicated, and they collaborate with or develop even a mildly competent ransomware operation, that would be quite a prolific combined operation.
References
- https://www.dataminr.com/resources/intel-brief/vect-breachforums-teampcp-converge-in-unprecedented-affiliate-mobilizatio/
- https://buymeacoffee.com/insidedarknet/box-turtle-xploitrs-interview
- https://www.paloaltonetworks.com/blog/cloud-security/bitwardencli-supply-chain-attack/
- https://isc.sans.edu/diary/32846
- https://www.halcyon.ai/ransomware-alerts/trivy-supply-chain-compromise-enters-extortion-phase-as-vect-ransomware-publishes-first-victim
- https://unit42.paloaltonetworks.com/teampcp-supply-chain-attacks/
See also:
Jack Lewis
Jack is a security researcher with a strong focus on malware analysis, tracking new threat actors and campaigns, reverse engineering, patch diffing, and proactive threat hunting.
