TL;DR
- A consumer NAS (WD My Cloud, EOL firmware) was attacked via SMB port 445 exposed to the internet through UPnP. Guest access was enabled with no authentication required.
- 239,285 files across four shares were replaced with sparse null-filled files (1 MiB / 2 MiB, 100%
0x00,Blocks: 0). This was a wiper, not ransomware. No encryption occurred. - Two ransom notes were deployed: a basic
RECOVERY.txtand a sophisticatedRECOVERY.htaposing as a corporate IT decryptor. The HTA contains Russian developer comments, ActiveX-based file downloading, and aCN1:encoded URL scheme using XOR keyCorpKey2025. - Recovery succeeded: PhotoRec carved ~480,000 files (~318 GB) from the raw disk. A surviving WD media database (
wdmc.db) with 500,000+ entries enabled partial restoration of original filenames and directory structure.
How the Case Came In
We spotted a LinkedIn post from someone in distress. His NAS, full of years of family memories, had been hit by what appeared to be ransomware. The comments were full of people calling it a new variant, nobody had seen the extension before, and the general sentiment was that the data was gone.
We enjoy reverse engineering, and we've broken a few ransomware encryption implementations in the past. So we thought: let's give it a go. We reached out, asked him to send us a couple of the affected files and the ransom note by email. That's where the investigation started. (For a non-technical overview of this attack class, see our analysis of fake NAS ransomware and recovery options.)
The samples had a .eeYai2po extension appended to their original .jpg filenames. The ransom note instructed the victim to install the Tox encrypted messenger and contact the attacker via a Tox ID. Our first instinct was to check what we were actually dealing with before assuming encryption. Within minutes of opening the files in a hex editor, the assumption of ransomware started to fall apart.
Initial Triage: The Files Aren't Encrypted
We ran both sample files through hex analysis and byte composition counting. The result was unambiguous.
227166023_0ea67487bf.jpg.eeYai2po:
Size: 1,048,576 bytes (exactly 1 MiB)
Null bytes: 1,048,576 (100.00%)
Non-null bytes: 0
227166278_dc152a2e3a.jpg.eeYai2po:
Size: 1,048,576 bytes (exactly 1 MiB)
Null bytes: 1,048,576 (100.00%)
Non-null bytes: 0
SHA-256 (both files): 30e14955ebf1352266dc2ff8067e68104607e750abb9d3b36582b8af909fcb58
MD5 (both files): b6d81b360a5672d80c27430f39153e2c
Both files are byte-for-byte identical. They contain nothing but null bytes. Here's how that compares to what encrypted files actually look like:
| Property | Encrypted File (expected) | These Files (actual) |
|---|---|---|
| Byte distribution | High entropy, pseudo-random | Zero entropy, all 0x00 |
| File size | Varies (often padded to block size) | Exactly 1 MiB, suspiciously round |
| Content | Indistinguishable from random data | Uniform null bytes |
| Uniqueness | Each file encrypted differently | Both files are byte-for-byte identical |
These files were not encrypted. They were replaced with fixed-size null-filled placeholders. No decryption key can recover data from a file that contains no data. We assess with high confidence that this was a deliberate wiper operation, not ransomware. The null-byte sparse-file pattern is inconsistent with any known ransomware implementation. While a catastrophically malfunctioning ransomware tool cannot be entirely excluded, the deliberate creation of fixed-size sparse files points to intentional destruction rather than failed encryption.
Based on these findings, we decided to pick up the NAS on March 27 for full forensic analysis. The initial triage on the emailed samples told us enough: this wasn't a case where we needed to negotiate with an attacker or evaluate a decryption payment. The files were gone, and the only question was whether the original data could be recovered from the disk itself.
The Ransom Note (RECOVERY.txt)
YOUR FILES ARE ENCRYPTED !!!
TO DECRYPT, FOLLOW THE INSTRUCTIONS:
To recover data you need decrypt tool.
To get the decrypt tool you should:
After we send you instruction how to pay for decrypt tool and after payment
you will receive a decryption tool!
We can decrypt few files in quality the evidence that we have the decoder.
DO NOT TRY TO DO SOMETHING WITH YOUR FILES BY YOURSELF YOU WILL BRAKE
YOUR DATA !!! ONLY WE ARE CAN HELP YOU! CONTACT US:
Install a chat program https://tox.chat/clients.html
https://github.com/uTox/uTox/releases/
https://github.com/uTox/uTox/releases/download/v0.18.1/utox_x86_64.exe
add us to the list and wait for a response
59440C6E...BECB204088D7
Several things stand out.
Language errors consistent with a Russian-speaking author: "YOU WILL BRAKE YOUR DATA" (brake/break), "ONLY WE ARE CAN HELP YOU", "few files in quality the evidence." These are not typos. These structural errors are consistent with a Slavic-language speaker, most likely Russian, based on the error patterns and the corroborating Russian code comments in the HTA.
What's missing compared to professional ransomware operations:
- No ransom amount
- No payment deadline
- No unique victim ID
- No proof-of-decryption portal
- No Bitcoin or Monero wallet address
The note defers everything to Tox chat: "After we send you instruction how to pay." Professional ransomware gangs (Conti, LockBit, BlackCat) include payment details directly. This note reads like a template inconsistent with professional ransomware operations.
The Tox ID 59440C6E...BECB204088D7 (full value in IOC table below) returned no matches in public threat intelligence databases.
The HTA: A Fake Decryptor Built for Deception (RECOVERY.hta)
This is where the operation gets interesting. The second ransom note, RECOVERY.hta (16,961 bytes, SHA-256: 16a80dd19517d38e7ce7ab1849f228df6d3adeb1fc31d4629b5c4fe89a7d5e93), was found in 334 copies across every subdirectory of the affected shares. It was created 8 seconds before RECOVERY.txt.
Corporate IT Impersonation
The HTA presents itself as a "Corp IT" security portal. It tells the victim their files were encrypted "due to a security problem with your PC" and lists fabricated policy violations as the supposed cause:
| Policy Code | Fabricated Violation |
|---|---|
SEC-1.3 | "Violation: Darknet — Third-party tunneling (proxy/VPN) detected" |
AUP-2.6 | "Unlicensed software — Unapproved apps found" |
ID-4.2 | "Adault find — Prohibited content" (note misspelling: "Adault") |
NET-5.1 | "P2P-net — Open service ports" |
This is shame-based extortion. The victim is told their own behaviour caused the "encryption." The goal: discourage them from reporting the incident or seeking help.
The corporate branding is significant. This attacker is scanning SMB port 445 across the internet. That net catches home NAS devices, but it also catches corporate file servers and NAS appliances sitting on company networks with misconfigured firewalls or UPnP-forwarded ports. This is an opportunistic compromise: the attacker likely does not know whether the target is a home device or a corporate asset.
The "Corp IT" impersonation is designed for the corporate scenario. An employee who sees a security portal claiming their VPN usage or "prohibited content" triggered the encryption may be less likely to report it to their actual IT department. They might try to resolve it quietly, or even pay, rather than risk the embarrassment of an internal investigation. On a corporate network, this social engineering layer turns a simple wiper into something that buys the attacker time and silence.
The "Decrypt" Mechanism Is a File Downloader
The HTA includes a "DECRYPT Files" interface that asks for a "received code." It supports two input formats: a standard URL or a custom CN1: encoded format. Here's how the encoding works:
- Strip the
CN1:prefix - Base64-decode the remaining string
- XOR each byte with key
CorpKey2025(repeating) - The result is a URL pointing to the attacker's file server
Here's the actual decode function from the HTA source:
function decodeCN1orURL(input) {
if (!input.startsWith('CN1:')) return input; // обычный URL
var b64 = input.substring(4);
var decoded = atob(b64);
var key = 'CorpKey2025';
var result = '';
for (var i = 0; i < decoded.length; i++) {
result += String.fromCharCode(
decoded.charCodeAt(i) ^ key.charCodeAt(i % key.length)
);
}
return result;
}
Trivial obfuscation. Repeating-key XOR with a hardcoded key that's sitting right there in the source. Anyone with a Base64 decoder and the key can reverse any CN1-encoded URL the attacker distributes.
The "decryption" process then uses Windows-only ActiveX objects to download files from that URL:
MSXML2.XMLHTTPfor HTTP requestsADODB.Streamfor binary stream handlingScripting.FileSystemObjectfor writing files to disk
It scans the remote URL for a manifest.json or directory listing, then downloads files to C:\testDECRYPT or the user's Desktop. No cryptographic operations are performed on the local "encrypted" files. The tool does not decrypt anything. It downloads pre-selected files from the attacker's infrastructure and presents this as "decryption."
If the mechanism works as designed, the victim would be paying for files served from attacker infrastructure, wrapped in a UI that makes it look like cryptographic recovery. No direct evidence of data exfiltration from this specific device was identified during our investigation.
Russian Developer Comments in Source
The JavaScript source code contains Russian-language strings that were never localised:
| String in source | Translation | Location |
|---|---|---|
// Общий прогресс | "General progress" | CSS comment (line 41) |
showToast("Список пуст") | "List is empty" | downloadAll() function |
'ошибок: ' | "errors:" | Download progress counter |
return input; // обычный URL | "regular URL" | decodeCN1orURL() function |
These are internal developer comments and debug messages, not translated UI strings. The tool was very likely developed in a Russian-language environment, based on native developer comments and debug strings left in the source code. Whether the individual developer is a native Russian speaker, or working within a Russian-language codebase, cannot be determined from this evidence alone.
RECOVERY.txt vs RECOVERY.hta
| Aspect | RECOVERY.txt | RECOVERY.hta |
|---|---|---|
| Format | Plain text | HTML Application (Windows executable) |
| Size | 758 bytes | 16,961 bytes |
| Sophistication | Low (template text) | High (styled UI, JavaScript, ActiveX) |
| Created | 21:11:43 CET | 21:11:35 CET (8 seconds earlier) |
| Count on NAS | 4 (one per share root) | 334 (one per subdirectory) |
| Tox ID | Same | Same |
| Language clues | English grammar errors | Russian code comments |
| "Decryption" | Claims tool will be sent via chat | Contains fake "decryptor" (actually a downloader) |
| Social engineering | None | Fabricated policy violations, shame-based extortion |
Getting Inside the NAS
The target device was a Western Digital My Cloud 4TB (model WDBCTL0040HWT), running WD My Cloud OS 3, firmware version 04.06.00-111. My Cloud OS 3 reached end-of-life on April 15, 2022. No security updates have been available since.
| Component | Detail |
|---|---|
| Kernel | Linux 3.2.26 (armv7l) |
| OS | Debian 7 "Wheezy" |
| Data partition | /dev/sda4, EXT4, 3.6 TB (454 GB used) |
| Logging | ramlog-tmpfs (40 MB RAM disk at /var/log) |
We mounted the forensic disk image read-only via a hardware write blocker. Standard procedure, no surprises.
Critical: volatile logging
This NAS uses ramlog-tmpfs, storing all logs in a 40 MB RAM disk at /var/log. Every reboot wipes everything. If the owner had rebooted the NAS before we got to it, most of the attacker's traces would have been permanently gone. On consumer NAS devices, speed is everything. The clock starts ticking the moment the device is powered on after an incident.
We performed the live analysis on March 27-28, four days after the attack on March 23. Because the NAS had not been rebooted in the meantime, the rotated Samba logs (log.smbd.old) and a rotated user log (user.log.1) were still present in RAM. These contained the attacker's connection records, SMB probing signatures, and disk wake events.
Had the device been rebooted at any point between the attack and our investigation, these logs would have been permanently lost. This is a recurring problem with consumer NAS devices and a strong argument for enabling remote syslog forwarding on any network storage that matters.
The Configuration That Made This Possible
We assess with high confidence that the root cause was the combination of guest-writable SMB shares and internet exposure. No exploit was required for SMB access. We found no evidence of exploitation of other services, though the limited logging capability means exploitation cannot be fully excluded. The attacker connected to an open, writable SMB share over the internet.
SMB: Accept Any Connection
From /etc/samba/smb-global.conf:
null passwords = yes
map to guest = bad user
guest account = nobody
security = user
smb encrypt = disabled
browseable = yes
The combination of null passwords = yes and map to guest = bad user means the NAS accepts literally any connection attempt. Invalid username? Mapped to guest. No password? Accepted. The security = user setting is meaningless when every failed auth silently succeeds as guest.
Shares: Guest-Writable by Default
[Public] guest ok = yes, writable = yes
[User_1] guest ok = yes, writable = yes
[User_2] guest ok = yes, writable = yes
[User_3] guest ok = yes, writable = yes
[Victim] public = no, valid users = "victim", invalid users = "nobody"
Four of seven active shares allowed unauthenticated read/write access. Only the Victim share was properly locked down with explicit user validation and guest denial. This distinction becomes important later.
NFS: Second Unauthenticated Attack Vector
From /etc/exports:
/nfs *(rw,all_squash,sync,no_subtree_check,insecure,crossmnt,anonuid=65534,anongid=1000)
The entire /nfs directory tree (containing all shares) was exported read-write to any IP address (*), with all users squashed to nobody (UID 65534), accepting connections from unprivileged ports (insecure). If SMB had been locked down, NFS would have provided the same level of access.
Firewall: Non-Existent
Chain INPUT (policy ACCEPT)
DROP tcp 0.0.0.0/0 0.0.0.0/0 tcpflags: 0x02/0x02 tcpmss match 1:500
Chain FORWARD (policy ACCEPT)
Chain OUTPUT (policy ACCEPT)
On the device itself: default ACCEPT on all chains. The single rule drops malformed TCP SYN packets with small MSS values. No port filtering, no IP restrictions, no rate limiting. Of course, there is a home router in front of the NAS, and we did not have access to that configuration. But the presence of external IPs in the Samba logs confirms that SMB traffic was reaching the device from the internet, whether through UPnP port forwarding, manual port mapping, or another mechanism on the router.
UPnP: Automatic Internet Exposure
A UPnP daemon was running:
/usr/local/bin/upnp_nas_device -webdir /var/local/upnp_nas_device
We assess it is likely that UPnP automatically configured port forwarding on the home router, making port 445 internet-accessible. We did not have access to the router configuration to confirm this. If this was the mechanism, the NAS owner did not need to manually forward any ports. The device did it for them.
Software: Everything End-of-Life
| Component | Version | Status |
|---|---|---|
| Debian | 7 "Wheezy" | EOL June 2016 (almost 10 years out of support) |
| Linux Kernel | 3.2.26 (Debian Wheezy era, circa 2012) | No security patches in over a decade |
| OpenSSL | 1.0.1t (May 2016) | EOL December 2016 |
| Samba | 4.3.11 | EOL, multiple critical CVEs |
| WD My Cloud OS | 3 (fw 04.06.00-111) | EOL April 15, 2022 |
The configuration set max protocol = SMB3, but this only sets the upper limit for negotiation. Without min protocol = SMB2, Samba still accepts SMBv1 connections if the client requests them. The probing patterns in the Samba logs confirm SMBv1 connections were accepted.
Reconstructing the Timeline
All timestamps are CET (Central European Time, UTC+1). The timeline was reconstructed from three sources: rotated Samba logs (log.smbd.old), a rotated user log (user.log.1) containing disk standby events, and filesystem timestamps (mtime) on wiped files and ransom notes.
March 22: SMBv1 Probing
[2026/03/22 14:04:18] reply_trans: invalid trans parameters
[2026/03/22 14:04:18] read_fd_with_timeout failed for client 123.58.207.127
[2026/03/22 20:37:02] reply_trans: invalid trans parameters
[2026/03/22 23:24:09] reply_trans: invalid trans parameters
[2026/03/22 23:44:59] reply_trans: invalid trans parameters
reply_trans: invalid trans parameters is Samba's response to malformed SMBv1 transaction requests. This is the signature of automated SMB vulnerability scanning. The Chinese IP 123.58.207.127 connected and failed with NT_STATUS_END_OF_FILE. Multiple probes continued from 14:04 through 23:44.
March 23: Continued Probing, Cloud IPs Connect
[2026/03/23 04:21:48] reply_trans: invalid trans parameters
[2026/03/23 04:21:48] read_fd_with_timeout failed for client 3.131.220.121 (AWS us-east-2, Ohio)
[2026/03/23 04:21:48] read_fd_with_timeout failed for client 40.124.173.234 (Azure Texas)
[2026/03/23 05:42-06:00] lpcfg_service_ok entries — Samba validating share configurations
[2026/03/23 17:20:57] reply_trans: invalid trans parameters
[2026/03/23 19:43:00] reply_trans: invalid trans parameters (last probe before attack)
At 04:21, two US cloud IPs joined the probing: AWS Ohio (3.131.220.121) and Azure Texas (40.124.173.234). Both failed initially but the burst of lpcfg_service_ok entries between 05:42 and 06:00 shows Samba validating share configurations as clients connected to multiple shares.
20:08: First Disk Wake
2026-03-23 20:08:44 exit standby after 7
The NAS disk woke from standby after only 7 seconds of sleep. A remote connection triggered the wake. Brief activity, then the disk returned to standby by 20:18:55.
20:29: Sustained Connection, Share Enumeration
2026-03-23 20:29:12 exit standby after 617
The disk had been in standby for 617 seconds (10 min 17 sec). This wake marked the beginning of the sustained attack session. From 20:29 to 21:11, the Samba logs show repeated lpcfg_service_ok entries as Samba validated share configurations for incoming connections — indicating the attacker was connecting to multiple shares. At 20:54:48, a burst of 5 entries in under 1 second suggests rapid enumeration across all available shares.
This was a 42-minute reconnaissance phase. The attacker was connected and browsing the share structure but had not yet modified any files.
21:11: Ransom Notes Deployed (338 Files in ~10 Seconds)
| Time (CET) | Event |
|---|---|
| 21:11:35 | First RECOVERY.hta created (User_1 share) |
| 21:11:35-21:11:42 | 334 RECOVERY.hta files deployed to all subdirectories across 4 shares |
| 21:11:40 | RECOVERY.txt created in User_3 share root |
| 21:11:41 | RECOVERY.txt created in Public and User_2 share roots |
| 21:11:43 | RECOVERY.txt created in User_1 share root |
334 HTA files + 4 TXT files in approximately 10 seconds. This is scripted. No human is placing 338 files across a directory tree that fast.
21:14: Oplock Storm Begins (Wiper Active)
[2026/03/23 21:14:04] smbd/oplock.c:downgrade_file_oplock
[2026/03/23 21:17:52] smbd/oplock.c:downgrade_file_oplock
[2026/03/23 21:18:34] smbd/oplock.c:downgrade_file_oplock
[2026/03/23 21:18:36] smbd/oplock.c:downgrade_file_oplock
[2026/03/23 21:19-21:22] multiple per minute, accelerating
[2026/03/23 21:25-21:30] sustained storm — files wiped continuously
[2026/03/23 22:00-22:01] peak intensity — 10+ events per minute
A downgrade_file_oplock entry appears when Samba breaks an opportunistic lock on a file because another process is modifying it. Under normal NAS operation, you might see one occasionally. Hundreds in rapid succession means an automated process is systematically opening, truncating, and replacing files.
The wiper started at 21:14:04, only 2.5 minutes after the last ransom note was dropped.
21:55-23:08: Sustained Wiping
Filesystem timestamps confirm the destruction window:
| Time (CET) | Event |
|---|---|
| 21:55:05 | Earliest wiped file mtime observed in our examination: User_3/.DS_Store.eeYai2po (1 MiB). Note: this is the earliest mtime we found in the files examined, not necessarily the absolute earliest across all 239,285 wiped files. |
| 21:55:23 | User_1/IMG_7698.JPG.eeYai2po wiped (2 MiB) |
| 22:04:35 | User_1/IMG_5720.JPG.eeYai2po wiped (1 MiB) |
| ~23:08 | Last observed activity (User_2 share last modified) |
The oplock log shows file modification starting at 21:14, but mtime values start at 21:55. This gap suggests a multi-pass approach: the wiper first renamed files (appending .eeYai2po), then made a second pass to truncate and zero-fill them. The mtime we observed reflects the final write, not the first touch.
Phase Summary
| Phase | Time Window | Duration | Activity |
|---|---|---|---|
| Reconnaissance | Mar 22 14:04 - 23:44 | ~10 hours | SMBv1 probing from 3 external IPs |
| Continued probing | Mar 23 03:09 - 19:43 | ~16 hours | Ongoing SMB probes, AWS + Azure IPs connect |
| First disk wake | 20:08:44 | Brief | Probe triggers disk wake, returns to standby |
| Attacker connects | 20:29:12 | - | Sustained SMB session begins |
| Share enumeration | 20:29 - 21:11 | ~42 min | Attacker enumerates shares, no file modifications |
| Note deployment | 21:11:35 - 21:11:45 | ~10 sec | 338 ransom notes dropped (scripted) |
| Wiper starts | 21:14:04 | - | First downgrade_file_oplock |
| File wiping | 21:14 - 23:08+ | ~2 hours | 239,285 files wiped across 4 shares |
| Total operation | 20:29 - 23:08+ | ~2.5 hours | Connection to last observed activity |
| Total recon + attack | Mar 22 14:04 - Mar 24 01:22 | ~35 hours | Full adversary engagement |
Impact Assessment
239,285 files were wiped across the four guest-accessible shares: Public, User_1, User_2, and User_3.
The Victim share, the date-named shares, and the NewYork share were untouched. All of these required authentication and explicitly denied the nobody (guest) user. Authentication worked exactly as intended. The attack boundary was defined entirely by the guest ok = yes configuration.
File ownership analysis: Every wiped file and every ransom note was owned by UID 65534 (nobody), GID 1000 (share). This is the SMB guest account. No authenticated account was used at any point during the attack.
Files that survived: Some files in the affected shares were not wiped. These included .mp3, .mp4, and .sfk files (audio/video) in the User_3 share; several .JPG files with spaces or (2) in filenames in the User_1 share; and various app data files, .nomedia markers, and cache files in the User_2 share. Two patterns explain the survivors. First, the stronger signal: media files (.mp3, .mp4, .sfk) survived systematically, suggesting the wiper used file type filters that excluded audio and video formats. Second, a weaker but notable pattern: some .JPG files with spaces or (2) in their filenames were skipped, which may indicate the wiper's filename handling failed on special characters and parentheses common in Dutch filenames.
The Wiped Files: Sparse, Not Overwritten
The wiped files are 1 MiB or 2 MiB, contain 100% null bytes, and have a .eeYai2po extension appended. That much we established early. But one detail changed the entire recovery outlook.
$ stat User_1/IMG_7698.JPG.eeYai2po
Size: 2097152 Blocks: 0 IO Block: 4096 regular file
Blocks: 0. The file is 2 MiB in size but occupies zero disk blocks. It's a sparse file.
When you create a sparse file, the filesystem records the file's size in metadata but doesn't allocate any physical disk blocks for the content. A read from any offset returns null bytes, but those null bytes don't exist on disk. The filesystem generates them on the fly.
This means the wiper did not overwrite the original data blocks. It truncated each file (releasing the original block allocations), appended the extension, and set the file size to 1 or 2 MiB without writing any actual data. The original blocks were marked as free but their contents remained physically present on the disk.
For recovery, this was the best possible outcome. The original data was still there, sitting in unallocated space, waiting to be carved.
Data Recovery: PhotoRec + wdmc.db
Traditional undelete tools like extundelete rely on inode-to-block mappings. Since the wiper truncated the files, the block pointers within the inodes were zeroed out, destroying the mappings to the original data blocks. extundelete was ineffective.
We turned to file carving. PhotoRec scans raw disk blocks for known file signatures (JPEG SOI markers, PNG headers, etc.) and reconstructs files without relying on filesystem metadata. Running PhotoRec against the raw /dev/sda4 partition:
| Metric | Value |
|---|---|
| Files recovered | ~480,000 |
| Data recovered | ~318 GB |
| Method | PhotoRec file carving on raw /dev/sda4 |
The ~480,000 recovered files exceed the 239,285 wiped files because PhotoRec also recovered previously-deleted data still present in unallocated disk space, not just files destroyed in this attack.
File carving recovers content but not context. The 480,000 recovered files had no filenames and no directory structure. They came out as f0000001.jpg, f0000002.png, etc.
The wdmc.db Goldmine
The WD My Cloud media indexing service maintains a SQLite database at /DataVolume/shares/.wdmc/wdmc.db. This 500+ MB database survived the attack because the attacker targeted user files, not system/hidden directories. It contained:
- Metadata for over 500,000 files indexed by the NAS
- Original file paths and complete directory structure
- File sizes at time of indexing
- Creation and modification timestamps
- EXIF data for images (camera model, GPS coordinates, date taken)
- ID3 tags for audio files (artist, album, track information)
We built a custom mapping tool to cross-reference carved files against wdmc.db entries using file size, MIME type, EXIF metadata, and ID3 tags. A carved JPEG with matching byte length, camera model, and capture timestamp could be confidently mapped to its original filename and path in the database.
The result: partial reconstruction of the original directory structure with meaningful filenames restored to a significant portion of the 480,000 recovered files.
Threat Actor Analysis
We assess with moderate confidence that this was an opportunistic attack using Russian-developed tooling, deployed from Chinese and US cloud infrastructure.
Russian-language development environment: The RECOVERY.hta contains native Russian developer comments and debug strings. These are internal code artefacts, not translated UI. The RECOVERY.txt uses broken English with error patterns consistent with a Slavic-language speaker.
Geographically diverse infrastructure:
| IP Address | Location | Provider |
|---|---|---|
123.58.207.127 | China | Chinese ISP (residential or hosting) |
3.131.220.121 | United States (Ohio) | Amazon AWS (us-east-2) |
40.124.173.234 | United States (Texas) | Microsoft Azure |
Most likely scenario: tool reuse from a crimeware marketplace. The RECOVERY.hta is a purpose-built tool with CN1-encoded URLs, ActiveX downloading, and corporate IT social engineering. This level of development suggests a tooling author who is separate from the operator. Russian-language ransomware/wiper toolkits are widely sold and traded on underground forums. The operator who deployed this against a Dutch consumer NAS may not be Russian at all.
The reconnaissance phase (Chinese IP, March 22) and the attack execution (March 23) could involve different actors. Automated scanning infrastructure discovers exposed SMB services and catalogues targets. Target lists are sold or shared with operators who carry out the attack. This model is common in NAS-targeting campaigns.
Modus operandi: Scan for internet-exposed SMB. Connect via guest access. Deploy ransom notes. Wipe files. Demand payment for data that can't be "decrypted" because it was never encrypted.
Detection Opportunities
If you're running Samba or managing NAS devices, here's what to watch for:
reply_trans: invalid trans parametersin Samba logs = SMBv1 probing. Someone is testing your device for known SMB vulnerabilities. If your NAS should not be internet-accessible, this means it is.downgrade_file_oplockstorms in Samba logs = rapid automated file modification. A handful of these in normal operation is fine. Hundreds per minute means something is systematically processing your files.- Sparse files with
Blocks: 0and null content = wiper, not ransomware. Runstaton any "encrypted" file. If the block count is zero, the file was never written to disk. No decryption key exists. - Files owned by
nobody(UID 65534) in user shares = unauthenticated access. If legitimate users have named accounts, files owned bynobodywere created via guest SMB sessions. - Unexpected disk standby wake events = remote connection. On NAS devices with standby logging, a disk wake at 3 AM when nobody is home warrants investigation.
Indicators of Compromise
Network Indicators
| Indicator | Type | Context |
|---|---|---|
123.58.207.127 | IP address | SMBv1 probing, initial reconnaissance (Chinese ISP) |
3.131.220.121 | IP address | SMB connection attempts (AWS us-east-2, Ohio) |
40.124.173.234 | IP address | SMB connection attempts (Azure, Texas) |
Host Indicators
| Indicator | Type | Context |
|---|---|---|
.eeYai2po | File extension | Appended to wiped files |
RECOVERY.txt | Filename | Plain-text ransom note (758 bytes) |
RECOVERY.hta | Filename | HTML Application ransom note (16,961 bytes) |
CorpKey2025 | XOR key | Used in RECOVERY.hta CN1: URL encoding |
CN1: | Protocol prefix | Custom URL obfuscation in RECOVERY.hta |
59440C6E9F8DFB95B38D5C599FD7546D74148BE6C280BAA8A1F3FBECADC07305BECB204088D7 | Tox ID | Threat actor contact identifier; unknown whether campaign-wide or per-victim |
Behavioural Indicators
| Indicator | Context |
|---|---|
reply_trans: invalid trans parameters (Samba log) | SMBv1 probing / vulnerability scanning |
smbd/oplock.c downgrade_file_oplock storm (Samba log) | Rapid automated file modification (wiper active) |
Sparse files with Blocks: 0 and null-byte content | Files replaced, not encrypted |
| Unexpected disk standby wake events | Remote connection triggering disk spin-up |
Files owned by nobody (UID 65534) in user shares | Unauthenticated SMB guest access |
File Hashes
| File | SHA-256 |
|---|---|
RECOVERY.txt | 6bd649b53db6ee68972bbd3a80f5e9c9ccfbf5f3dce996019c9bff52652eb1cc |
RECOVERY.hta | 16a80dd19517d38e7ce7ab1849f228df6d3adeb1fc31d4629b5c4fe89a7d5e93 |
| Wiped files (all identical) | 30e14955ebf1352266dc2ff8067e68104607e750abb9d3b36582b8af909fcb58 |
MITRE ATT&CK Mapping
| Technique ID | Technique | Evidence |
|---|---|---|
| T1046 | Network Service Discovery | SMBv1 probing (reply_trans) from 3 IPs over 35 hours |
| T1133 | External Remote Services | SMB port 445 exposed to the internet via UPnP; no exploit used — attacker accessed a legitimately running SMB service with guest access enabled |
| T1078.001 | Valid Accounts: Default Accounts | map to guest = bad user + null passwords = yes grants access to any connection |
| T1021.002 | Remote Services: SMB/Windows Admin Shares | Unauthenticated SMB used for all file operations |
| T1083 | File and Directory Discovery | 42-minute share enumeration phase (20:29-21:11) |
| T1059.007 | Command and Scripting Interpreter: JavaScript | RECOVERY.hta uses JavaScript with ActiveX objects (MSXML2.XMLHTTP, ADODB.Stream) |
| T1218.005 | System Binary Proxy Execution: Mshta | RECOVERY.hta is an HTML Application executed via mshta.exe |
| T1036.005 | Masquerading: Match Legitimate Name or Location | HTA poses as "Corp IT" security portal |
| T1486 | Data Encrypted for Impact | Claimed by attacker; not observed in evidence. Ransom notes assert encryption, but all files contain only null bytes. Used as social engineering cover for T1485. |
| T1485 | Data Destruction | 239,285 files replaced with sparse null-filled files |
| T1491.001 | Defacement: Internal Defacement | 338 ransom notes deployed across all subdirectories |
| T1565.001 | Data Manipulation: Stored Data Manipulation | Files truncated and replaced with fixed-size sparse files |
| T1071.001 | Application Layer Protocol: Web Protocols | HTA "decryptor" uses HTTP to download files from attacker infrastructure |
| T1027 | Obfuscated Files or Information | CN1: URL encoding (Base64 + XOR with CorpKey2025) |
Recommendations
These are specific to this case and this class of attack.
- Block SMB at the router. Port 445 should never be internet-accessible. Disable UPnP on your router to prevent devices from opening ports automatically. If remote file access is needed, use a VPN.
- Disable guest access on all shares. Set
map to guest = neverin Samba global config. Removeguest ok = yesfrom every share definition. Require authentication for all access. - Set passwords on all accounts. Set
null passwords = noin Samba. Ensure every user account has a strong password. - Lock down NFS exports. Replace
*with specific IP ranges. Useroot_squashand removeinsecure. Better yet, disable NFS if it's not actively used. - Replace the device. A NAS running Debian 7, kernel 3.2.26, and Samba 4.3.11 cannot be made secure through configuration alone. The software stack has known, unpatched vulnerabilities. WD My Cloud OS 3 will never receive another update.
- Enable persistent logging.
ramlog-tmpfsdestroys all forensic evidence on every reboot. If the device must remain in service, configure remote syslog to an external logging server. - Implement 3-2-1 backups. Three copies of data, two different media types, one offsite or offline. A NAS is storage, not backup. An offline USB drive that the attacker can't reach would have made this entire incident a minor inconvenience.
- Verify before paying. Open any "encrypted" file in a hex editor. If it's all null bytes, you're looking at a wiper. No payment will produce a decryption key for data that was destroyed, not encrypted. Not sure how to check? Use our free File Encryption Checker to analyse files in your browser.
Written by
ForCri Team
Cyber Crisis Management & Digital Forensics