19 min read

A closer look at what we suspect is vibe coded ransomware

A closer look at what we suspect is vibe coded ransomware

During a summer investigation in 2025, Defendable uncovered signs of ransomware activity targeting a file-share server. Further analysis revealed the ransomware sample, dubbed “MadiLock,” present on one of the compromised servers. Surprisingly, the sample went undetected by traditional antivirus solutions. When we dug deeper, we couldn’t find any public analysis available for MadiLock. While there was a brief mention of the malware family in a Cyber Threat Intelligence X-thread and an auto-generated threat page from Zscaler, neither contained meaningful details.

Through VirusTotal, Defendable identified just one additional sample of MadiLock. Aside from minor alterations to the ransom note, it was practically identical to the ransomware in our incident. This scarcity of information only added to the intrigue.

Although the investigation couldn’t pinpoint the exact intrusion point, Defendable’s team found evidence suggesting that MadiLock entered via an exploited vulnerability in SonicWall SSL VPN. Once inside the network, the attacker used the SoftEther VPN program to maintain persistent access to internal servers.

Upon reversing the ransomware, a curious detail stood out: MadiLock’s coding practices felt unconventional—not what you’d typically expect from seasoned malware authors. Based on our analysis, we theorize that MadiLock’s creation relied heavily on modern machine learning (ML) and artificial intelligence (AI) tools. If true, this could represent a significant shift, demonstrating how attackers may be able to rapidly develop unique malware tailored to each campaign with minimal effort.

Executive Summary

In this blog post, we dive deep into the investigation and analysis of MadiLock, a ransomware variant that exemplifies simplicity paired with effectiveness. This malware targets user-created files across mounted drives, encrypting them with a unique runtime-generated key and appending a .MadiLock extension to their names. While it lacks advanced features like network activity, persistence mechanisms, or anti-analysis techniques, its deliberate design allows it to perform its core function—file encryption—with precision.

MadiLock’s approach to file encryption is thorough yet surprisingly straightforward. It uses strong cryptographic methods, generating a unique encryption key on the victim’s system and encrypting it with a hardcoded RSA public key to ensure recovery is only possible via the attacker’s decryptor tool. Its operations are multi-threaded for speed and efficiency, skipping system-critical files to maintain usability on the affected machine—an intentional choice aimed at facilitating ransom payment.

One notable aspect is its method of deleting original files. Instead of overwriting them immediately, MadiLock relies on temporary files to store the encrypted data and uses the Windows API to mark original files as deleted. This design leaves the door open for potential forensic recovery, as the original file data may still exist on the disk unless overwritten through subsequent system activity.

Despite its effectiveness, MadiLock is far from sophisticated. It shows no signs of network communication, remote control capabilities, or attempts to evade security systems like sandboxes. It operates entirely offline and is poorly suited for large-scale ransomware campaigns, as its lack of centralized control over encryption keys can render shared files unrecoverable in networked environments.

In summary, MadiLock serves as a case study of focused functionality over complexity, delivering a robust encryption strategy while staying lightweight and unrefined. This blog post provides an in-depth look at its design, encryption routine, runtime behavior, and forensic opportunities, empowering incident responders and analysts to understand and counteract this particular ransomware variant.

Key Takeaways:

  • Target Focus: MadiLock prioritizes files created by users, avoiding system and critical files to ensure ongoing system usability.

  • Cryptographic Approach: Runtime-generated AES keys and one-way RSA encryption ensure strong security but limit scalability in network environments.

  • Forensic Opportunities: Temporary file handling and soft deletion via the Windows API leave room to recover original file data if action is taken quickly.

  • Lack of Sophistication: The absence of anti-analysis features, packing, or backdoor functionality makes MadiLock straightforward to investigate and analyze.

This blog will guide you through the mechanics of MadiLock—from its file encryption routine to insights gained during dynamic sandbox analysis—while highlighting its strengths, weaknesses, and missed opportunities for forensic response.

 

Basic info:

Known/found name(s)

MadiLock, svchosts.exe

MD5

c0504174e7f6db086e9dbd882c97e16a

SHA1

cfeeec7f276e5f104fd0ef8ba599ed1e728997c6

SHA256

29386d4aa666f59cc8da77c7ac524ffd913117a9f0d2c0176873bf7551b343a1

File type

PE EXE 64-bit

Signature

Compiler: Go(1.15.0-X.XX.X)

File size (bytes)

4429824

Entropy

6.211

 

PE INFORMATION BELOW

Compiler timestamp

1970-01-01 01:00:00

Debugger timestamp

None

Internal name

MadiLock

Debug path

None

Section names

.text,.rdata,.data,.pdata,.xdata,.idata,.reloc,.symtab

Exported functions

None

 

The malware sample is not packed or encrypted. There are many interesting strings found in the sample, complete list of interesting strings appended at the end. There are runtime logging of what the malware does, the RSA Public certificate and the template for the ransom note.

Some interesting strings:

Strings

Comment

-----BEGIN RSA PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvnjWYpTgGBfXujJsaa24
6eHaQ0vYDLSdhISw5dGVdktdHQT2pa5irdrnLgkvpb3pDyUMZH1WIebzKOJXMmw+
FRZBvQix3TOK/oRh8YluMnhAFMzsjgwHVbnnZedG976NZp4clI0lYvY383Mwufb8
FVXRuug8Q0wG1UcqJ+Di7ng47dx4qkVpTPNn1PFdjRkxYENV1GXfwZ9xrPIrBQeP
cxzCpfZowlYEx74zAcNp8zj64cp1sB+urbbx1djsfuezt+2A7FCMnRBTMRYZjKei
Ru/v+S29cquixxXbCaJ5A2Lyq8aHI1L0nsJND09OVJVBQwPNfQeIIg+Q81CdHWE0
twIDAQAB
-----END RSA PUBLIC KEY-----

RSA Public key used to encrypt the ransomware key.

======================================================================================

Files were encrypted and stolen. Pay to decrypt and delete stolen copies

Your personal identification ID:

======================================================================================

!!! RECOVERY !!!

======================================================================================

  1. Pay BTC to this address:

  2. Send your ID: and payment proof to:

  3. Wait for decryption tool and key

======================================================================================

!!! WARNING !!!

======================================================================================

  • DO NOT delete or modify any files (very important)

  • Deadline: after this, price doubles

  • Your data will be permanently lost after 15 days.

  • Using third-party decryption tools will cause permanent data loss

SAVE THIS INFORMATION:

  • Your ID:

  • Address:

  • Contact Email:

  • Backup Email:

  • Amount: BTC

After purchasing our decryptor:

  1. You will not be attacked by us in any form

  2. You will not cause any data leakage due to us

======================================================================================

 

Ransomware note template

dinhvanhie@bk.ru

dinhvanhieuhd88@gmail.com

Contact Emails

bc1qh0sn5hadpd9k03ktmc3yun6nv5247vhzfdgq4jxefx6q92zkfc8s8h5jfj

Bitcoin wallet address

[+] completed processing list: %s (%d files)

[+] encryption complete: %d processed, %d failed

[+] first run inspection

[+] skip %s

[+] successfully created %d notes

[+] target drive: %s (%.2f GB free)

[-] avoid repeating

[-] decrypt failed: %s

[-] failed to decode PEM block containing public key

[-] failed to encrypt data: %v

Example log lines found in the sample. See appended list for all found log lines.

 

There is also an hard coded victim ID in the sample, here is a regex for the ID:

\w{4}\-\d{4}\-926101

The two first parts seem to be specific for the victim. The first 4 characters are from the organization name, the next 4 numbers are unique or random. The last 6 numbers are equal in the samples we have found and the one found on VirusTotal. Defendable believes that it could be a ransomware version number.

The compiling of Golang has left internal function names. The names are quite descriptive and informative. The list of function names is created by disassembling the sample with IDAPro, just removed wrapper and “duplicate” function names.

MadiLock_ciphers_DecryptFile MadiLock_ciphers_EncryptFile MadiLock_ciphers_EncryptWithPublicKey MadiLock_ciphers_GenerateRandomKeys128 MadiLock_ciphers_init MadiLock_cleanup_CleanFlush MadiLock_cleanup_DelMadiLockFilePaths MadiLock_cleanup_dsDepositeHandle MadiLock_cleanup_dsOpenHandle MadiLock_cleanup_dsRenameHandle MadiLock_safe_CreateAllDesktops MadiLock_safe_NewPathFilter MadiLock_safe_ScanWriteFiles MadiLock_safe_ScanWriteFilesWithConfig MadiLock_safe_StartEnc MadiLock_safe__ptr_PathFilter_IsAllowedExt MadiLock_safe__ptr_PathFilter_IsDenyFile MadiLock_safe__ptr_PathFilter_IsDenyLargeFile MadiLock_safe__ptr_PathFilter_IsDenyPath MadiLock_safe_batchProcessor MadiLock_safe_collectResults MadiLock_safe_fileWriter MadiLock_safe_formatDuration MadiLock_safe_init MadiLock_safe_printStats MadiLock_safe_processFile MadiLock_safe_processFileList MadiLock_safe_scanFileSystem MadiLock_utils_GetAvailableDrive MadiLock_utils_GetDriveType MadiLock_utils_GetMaxFreeDisk MadiLock_utils_OptimizeSystem MadiLock_utils_QueryRegistry MadiLock_utils_SaveGenerateKeys MadiLock_utils_WriteRegistry MadiLock_utils_configureBufferSettings MadiLock_utils_configureFileHandles MadiLock_utils_reserveSystemMemory MadiLock_utils_tryOptimizeProcessPriority type__eq_MadiLock_cleanup_FILE_RENAME_INFO type__eq_MadiLock_safe_MessageNote type__eq_MadiLock_safe_ScanConfig

Most of the functionality is related to finding and encrypting files, but there is one “Decrypt” function in the sample. It is not used directly, but it seems to be easy for the malware author to recompile the sample with new configuration to make it into a decryptor.

During the analysis of the sample, Defendable found one other instance of MadiLock ransomware on VirusTotal. That sample and the sample found by Defendable is practically identical, other than victim ID.

 

Technical analysis

This section explores key parts of the ransomware's functionality, breaking down how these components operate. We'll use Hex-Rays IDAPro (v9.1) to analyze the sample statically, followed by runtime logging captured through dynamic analysis. While we assume readers have basic familiarity with assembly language, we aim to explain our findings to ensure clarity.

Screenshots of assembly code in this post include analyst annotations (in pink text) to help communicate what’s happening at each step.

Heads up: Understanding 64-bit Golang assembly

Before jumping into the assembly specifics, it's important to highlight some quirks of Golang’s calling conventions for 64-bit systems. If you’re used to typical AMD64/x64 assembly conventions, Golang’s differences might catch you off guard. Personally, I found these differences confusing when I started—especially since resources explaining the nuances are scarce—so let’s demystify some key points.

Here’s the good news: unlike early Golang-compiled malware samples (which felt like deciphering a pile of unhelpful hex-bytes), this ransomware sample has fairly clean assembly code. Whether this improvement is due to advancements in Go compilers (version ≥ 1.15.x) or intentional compilation flags used by the malware authors is not entirely clear, but it’s certainly helpful for analysis.

image-20250924-080136

Golang call to an equivalent of “RegCreateKeyExA”, with 9 arguments.

 

Passing Arguments
Golang aims to pass as many arguments as possible directly via registers, prioritizing speed over stack-based arguments. At least the following registers are used for passing arguments:

RAX, RBX, RCX, RDI, RSI, R8, R9, R10, R11

We did not see calls with more than 9 parameters, but they most likely passed in the R12-R15 registers.

 
image-20250924-080938
Golang call to an equivalent of “RegCreateKeyExA”, with 9 arguments.

 

Return Values
Golang functions typically return two values:

  • RAX: Contains the primary result of the function call.

  • RBX: Stores an optional error value, if applicable.

However, there’s an exception to this rule when working with RTYPE functions (explained below).

image-20250924-081601

RTYPE ** call type, return RAX, RBX and RCX.

image-20250924-081826

__int64 call type, return RAX and RBX.

 

Functions of type RTYPE have a unique behavior, mimicking the functionality of “this-calls” in object-oriented programming. Here's how they operate:

  • On entry, RAX contains a pointer to a structure object (essentially a context object).

  • This structure object is modified or acted upon within the function, and then returned back via RAX.

  • Because RAX is in use for the RTYPE object, the primary result of the function call is pushed into RBX, and the optional error value is placed into RCX.

This behavior baffled me initially, as I couldn’t figure out where the return values were—and nothing I tested aligned with standard x64 expectations. Through trial, frustration, and patterns in function calls, I eventually cracked the logic.

image-20250924-082938

Test of error value in RBX after a call.

image-20250924-083033

Test of error value in RCX after a call.

 

So, how do you figure out where "interesting" return values live during analysis? Here are two quick tips:

  1. Post-Call Tests

    • If you see RBX being tested immediately after a function call, it’s likely the primary return value is in RAX and RBX is the error.

    • If RCX is being tested instead, the primary return value is probably in RBX.

  2. RTYPE References

    • If the disassembly references an object labeled RTYPE_<something> being loaded into RAX before the function call, you can usually assume that it’s a context object returned through RAX. Tools like IDAPro can help definitively identify RTYPE functions, showing the calling type directly.

image-20250924-084601When looking for interesting API calls in Golang, use the included functions and not the IAT.

Here’s a critical debugging tip if you’re analyzing Golang-based malware dynamically. Unlike traditional executables, many Golang samples handle essential functionality internally, bypassing standard import address tables (IAT) for API calls. This means setting breakpoints on Windows API functions like CreateFile or VirtualAlloc often won’t work—the execution never hits these points directly. Instead, the runtime functionality is embedded within the malware’s compiled code.

To debug successfully:

  • Set breakpoints on Golang runtime functions rather than Windows API imports.

  • Tools like IDAPro or Ghidra can help pinpoint these functions, enabling you to stop execution at critical points.

Checking ransomware execution mark

image-20250915-124819

Second code block in main.main function. Checking for ransomware mark.

The ransomware’s entry point is its main function, appropriately named main.main. This function initializes all other operations relevant to the malware’s behavior. One of the first checks performed by the ransomware is for a specific registry key: 

HKEY_LOCAL_MACHINE\Software\MadiLock\Machine
 

If the key exists and contains a value, then the ransomware log “[-] avoid repeating” and exits.

image-20250915-125540

Code block that logs to “console”, after ransomware mark found.

The registry key appears critical to the ransomware’s operations, as its value is the RSA-encoded encryption key used to encrypt victims' files (explained further below). This mechanism prevents the ransomware from running multiple times on the same machine or re-encrypting already affected files—a simple but efficient safeguard against redundancy.

Finding disks and files

Before encrypting files, the malware first identifies all accessible drives on the affected machine. It leverages the API call GetDriveTypeW and iterates through potential drive letters from A:\ to Z:\. For each drive that returns a positive result, the malware stores its root path (e.g., C:\) for later use.

The malware ignores network shares mounted without a named drive (e.g., \\server\share) and only works with traditional drive letters like C:.

Once the drives are mapped, the ransomware begins scanning the file system. Starting at the root directory of each mapped drive, it recursively traverses subdirectories searching for files matching specific extensions.

The malware exclusively targets user-created files. While there are no system-critical files in the list, the extensions span various categories, including documents, databases, media files, and backups. Intriguingly, a significant portion of the targeted extensions are related to 3D models and schematics, which may not align with typical victim profiles but might indicate broader ambitions or unrefined targeting strategies.

Here’s the full list of extensions:

  • Documents: .doc, .pdf, .wpd, .ppt, .pps, .odp, .csv, .xls

  • Databases: .mdb, .frm, .myd, .sql, .pst, .ost, .edb

  • Media Files: .mp3, .mp4, .avi, .wav

  • Compressed Archives: .zip, .rar, .tar, .tgz

  • Programming Files: .php, .asp, .cpp

  • Other Files:

    • Financial: .tax, .qbw, .qbb

    • Creative Projects (3D Models, Graphics): .psd, .sldprt, .dwg, .rvt, .f3d, .aep, .f3d, .glb, .fbx, .ztl, .skp

    • Backup Files: .bak, .sql

Note that some extensions (e.g., .doc) will also include derivative extensions (e.g., .docx) due to the targeting logic only requiring exact matches for the initial value.

The malware imposes several filters to control what files will be encrypted:

  1. File Size

    • Small files are encrypted directly.

    • Large files are handled separately in their own threads to avoid bottlenecks.

    • Excessively large files are skipped altogether.

  2. Exclusion List
    Certain folders, files, and file types are explicitly skipped during the scan. Below is the exclusion list organized by type:

Excluded Folders:
  • System and recovery folders:

    • C:\Program Files*, C:\ProgramData, C:\Windows, C:\recovery, C:\$recycle.bin

  • User folders:

    • C:\Users\*\Documents, C:\Users\*\AppData, C:\Users\Public

  • Cloud and monitoring directories:

    • C:\OneDrive, C:\inetpub, C:\perflogs

Excluded Files and File Types:
  • .rustup, .docker, .sqlite, .backup, .ibdata

  • Specific design project formats:

    • .sldprt, .sldasm, .slddrw, .sketch, .prproj

The ransomware logs all files matching its criteria into a file named:

C:\Users\Public\MadiLock1.txt

If this file already exists, the malware updates the filename by iterating the number (e.g., MadiLock2.txt) until an unused filename is found.

While the log file is intended to be deleted after execution, Defendable’s analysis revealed that incomplete runs—such as crashes or forced shutdowns—leave the file intact. This can provide critical forensic insights into what the malware attempted to encrypt, as the log file contains the full list of targeted files.

Creating the ransomware encryption key

Once the malware identifies files to encrypt, it executes a routine to generate a base ransomware encryption key. This process is complex, with multiple layers that add redundancy and obfuscation. The encryption mechanism involves several distinct steps, starting with random data generation and culminating in storage within the system registry.

Random Data Generation (MadiLock_ciphers_GenerateRandomKeys128)

Key generation begins in the function MadiLock_safe_StartEnc, which calls MadiLock_ciphers_GenerateRandomKeys128. This initial process combines various sources of randomness and system-specific data to build the foundation of the key.

image-20250919-122014

Code block that gets 64 random bytes.

 

image-20250919-122143

Get “now” timestamp, starts to modify it.
 
 
 
image-20250919-122329
 
Continue to modify timestamp, also gets PID.
 
 
image-20250919-122743
 
Random and created values passed to SHA3-256 hashing API.


First, the malware uses the API crypto_rand_Read to generate 64 bytes of random data (0x40 bytes). It then retrieves a timestamp using the time_Now API, which undergoes modification via a series of arithmetic operations to produce an 8-byte pseudo-random value. Alongside these, the malware collects its own process ID (PID) and another timestamp from its initialization routine. These inputs—random bytes, the modified timestamp, the PID, and an earlier timestamp-derived value—form a blob of data that is 84 bytes long (0x54). This combined data is passed into a SHA3-256 hashing algorithm, resulting in a cryptographically secure hash.

(0x40 random bytes) + (8 bytes time-random) + (4 bytes PID) + (8 bytes earlier time-random) = 0x54 (84) random bytes
 

The SHA3-256 output serves as a unique identifier for the key-generation routine. This hash is used in subsequent steps to encode and encrypt the ransomware's encryption key.

Splitting and Encoding (MadiLock_utils_SaveGenerateKeys)

The hash returned from the previous function is processed further in MadiLock_utils_SaveGenerateKeys, which also takes an RSA public key as input. The function splits the SHA3-256 hash into two equal parts, with each half being Base64-encoded to create human-readable strings.

image-20250919-123709
 
Newly created hash passed to save function, with a RSA Public Key.
 
 
 image-20250919-123907
 
The hash is split into two 128-bit blobs and worked with.
 

The malware then concatenates these encoded strings with a predefined delimiter (::_CALL_::) to form the final key representation. For example:

OPU35Ww8nHSGNkHVFMoyBg==::_CALL_::a7eIbdePfLIw9rFwJWjGBw==

 

RSA Encryption (MadiLock_ciphers_EncryptWithPublicKey)

image-20250919-124700

The RSA encryption routine used to one-way encrypt the ransomware encryption key.

The encoded key is then passed to MadiLock_ciphers_EncryptWithPublicKey, which uses the RSA public key to encrypt the data. To perform the encryption, the ransomware leverages the RSA algorithm via the crypto_rsa_EncryptOAEP function. While encryption operations typically involve random inputs, this malware uses hardcoded values to generate an additional SHA3-256 hash just before calling EncryptOAEP. This reduces true randomness in the process but does not compromise the one-way nature of RSA encryption.

The result of the encryption is a 256-byte block of data that represents the ransomware encryption key. This block is then Base64-encoded into its final form and returned as the output of the encryption function.

Storing the Encryption Key

image-20250919-125355

Encoded data is passed to WriteRegistry to save it for a possible ransomware decryptor software.
 

The Base64-encoded RSA-encrypted key is stored in the system registry. The encrypted key is written to the following location:

HKEY_LOCAL_MACHINE\Software\MadiLock\Machine

Although the registry value contains the fully encrypted key, the ransomware does not read it again during execution. Instead, it operates on the key stored directly in process memory. This suggests the registry entry serves a secondary purpose, primarily acting as a backup for external decryptor tools controlled by the attacker. By storing the key securely in the registry, attackers ensure victims can access it as part of the ransom payment process.

File encryption

image-20250922-114554

Function call graph from main to EncryptFile function.
 

After the ransomware generates and saves the encryption key, it proceeds with encrypting the list of discovered files. This process is multi-threaded, allowing the ransomware to handle multiple files simultaneously to speed up the operation. The design shows a balance between efficient encryption practices and robust functionality, including unused routines that hint at additional flexibility in the malware’s infrastructure.

Observations: Unused DecryptFile Routine

Within the ransomware’s processFile function, there is a reference to a DecryptFile routine. However, this routine is never utilized in the sample and does not naturally branch to it during execution. Based on static analysis, Defendable theorizes that the ransomware and decryptor are built on the same codebase, with different configurations compiled depending on the required functionality.

It is important to note that this ransomware cannot act as a decryptor in its current state. For decryption, it would require access to the Private Key, along with other unknown configurations embedded in the attacker-controlled decryptor.

File Encryption Process

The actual encryption takes place within the EncryptFile routine. Below is a breakdown of the process:
The ransomware begins by opening a handle to the original file targeted for encryption. At the same time, it creates a temporary file on the root of the C:\ drive named in the format:

C:\wl_enc_{rand_nr}.tmp

This temporary file serves as the location where the encrypted data will be written, preserving the integrity of the original file during the process.

 
image-20250923-133416
 
Creating a 16 bytes long random IV and then a AES-256 encryption block.
 

The ransomware follows standard practices for initializing encryption operations:

  • 16-Byte Initialization Vector (IV): The malware generates a random 16-byte IV to seed its encryption algorithm.

  • AES-256 Block Creation: Using the first part of the previously generated SHA3-256 hash as a key, the ransomware forms an AES-256 encryption block.

image-20250923-133819

CTR encryption stream created, then XOR on a 16 bytes zero buffer.
  • CTR Encryption Stream: An AES-256 encryption block is used to create a CTR mode encryption stream. This stream allows for efficient encryption of arbitrary-length data, block by block.

To initialize the encryption process, the CTR mode stream is applied to a 16-byte buffer consisting entirely of zeros. This results in an XOR operation that writes the first 16 bytes of the encryption stream to the buffer. These 16 bytes represent the starting encryption key segment.

image-20250923-134259

Both the random IV and the XOR buffer with the encryption stream is written to the temp file.
 

Before encrypting the actual file data, the ransomware writes metadata related to the encryption stream to the temporary file:

  1. The random IV (16 bytes), essential for recreating the encryption stream during decryption.

  2. The first 16 bytes of the encryption stream, extracted earlier during XOR operations.

These metadata writes ensure that the encrypted file can be correctly decrypted if the private key and proper configurations are provided later.

image-20250923-134706

Recreate the CTR encryption stream, then over write the IV variable with a zero buffer.
 

With the encryption stream initialized, the ransomware moves on to encrypting the actual file contents.

The malware recreates the CTR encryption stream using the AES-256 block and the IV, ensuring consistency throughout the process. It also initializes a new zero buffer, although the buffer itself is no longer directly used in subsequent operations.

image-20250923-135056
 
Uses the recreated cipher stream on the original file’s content, write result to temp file.
 

Before entering the encryption loop, the ransomware performs several checks on the original file’s statistics (e.g., size) to prepare for the processing of large data chunks.
The actual encryption occurs within a loop, especially for larger files. It uses the same aesCtrWrapper_XORKeyStream mechanism as earlier:

  1. The original file’s data is read in chunks and encrypted using the cipher stream.

  2. Encrypted data is written to the temporary file (C:\wl_enc_{rand_nr}.tmp).

The loop handles encryption in large chunks to optimize performance, particularly for larger files.

After the file data is encrypted, the ransomware moves the temporary file back to the original file’s directory. The temporary file is renamed to match the original file’s name, but with the .MadiLock extension appended. Once this process is complete, the malware deletes the original file using the Windows API function for file deletion. This operation does not immediately erase the file's data from the disk; instead, it merely marks the file as “deleted” in the Master File Table (MFT).

Since the ransomware does not directly overwrite the original file’s data, there is potential for recovery if the disk is analyzed promptly after the attack. However, the creation of the encrypted temporary file and subsequent file system operations could unintentionally overwrite portions of the deleted file's data. Recovery depends on timing and the system’s subsequent disk activity, but forensic tools may still be able to retrieve some or all of the original data if action is taken quickly.

Rename and self-delete

After completing its encryption operations, the ransomware attempts to conceal its presence by removing the ransomware sample itself from the disk. This process is handled by the malware's cleanup function, MadiLock_cleanup.CleanFlush. Within this function, the ransomware executes two key routines: MadiLock_cleanup.dsRenameHandle and MadiLock_cleanup.dsDepositionHandle.

image-20250922-134922

Code block that result in renaming of the ransomware file by changing the file’s file-information.
 

The ransomware starts by renaming its executable file on disk, presumably to make it harder to identify during any forensic investigation. In the routine MadiLock_cleanup.dsRenameHandle, it creates a file rename information structure.

To rename the file, the malware inserts a hardcoded string, :deadbeef, into the structure—an apparent preference for strings that may feel arbitrary but are often used in debugging or testing contexts. Interestingly, only the first four characters of this string (":dea") are applied to the file's name. This truncated rename operation leads to the ransomware sample being renamed to :dea.

While the choice of the new name (":dea") might seem random, the obscure format could be intentional, aiming to minimize suspicion and to bypass casual searches for more obvious ransomware names like "MadiLock.exe."

image-20250922-140417
 
Same technique to change the files information, this time that the file is deleted.
 

Following the file rename operation, the ransomware executes another cleanup routine, MadiLock_cleanup.dsDepositionHandle. Here, the malware interacts with the file's information through the FileDispositionInfo structure. This structure is used to control how Windows processes files on the disk, including whether they should be marked for deletion.

The ransomware sets the boolean value in the FileDispositionInfo structure to 1, signaling to Windows that the file should be deleted. This operation marks the file as deleted at the file system level, effectively removing it from directory listings and access paths.

The process then terminates.

Dynamic analysis

The MadiLock ransomware includes extensive runtime logging to track the encryption process, but it does not visibly log information to a file or open a process window for monitoring. Since the file is compiled as a Windows GUI application, it executes silently without displaying a console window.

To capture the malware’s internal logging, Defendable applied two approaches:

  1. Direct PE Modification: By modifying the sample’s Optional Header to change its Subsystem field to "Windows Console," we were able to force the malware to display its runtime logs in a console window during execution. This simple yet effective change reveals all logging output generated by the system.

  2. Debugging: By attaching a debugger to the process and intercepting parameters passed to the malware’s print functions, Defendable was able to extract similar log information. However, debugging requires active attachment to the ransomware process, making it a less convenient method.

image-20250915-135527
 
CFF Explorer can show and modify pretty much anything in the MZ file. The field “Subsystem” show that it is compiled for “Windows GUI”.
 
 image-20250915-135709
 
By changing Subsystem to “Windows Console” we get a output window.
 
 

Running the sample in a sandbox provided insights into its behavior and confirmed findings from static assembly analysis. Key observations include:

  • Skipping Folders and Files: The malware honors a hardcoded list of keywords, paths, and directories to ignore during encryption. This includes system-critical folders (e.g., C:\Windows) and files matching specific criteria.

 
image-20250922-124547
 
Screenshot from sandbox analysis, showing folders being skipped and system information and preparation.
  • System Preparation: The malware performs checks on the affected system to optimize multi-threaded encryption operations.

image-20250922-125014
 
Logging of files being encrypted successfully, how log it took and that ransom note is dropped.
  • Final Steps: The last logged action includes:

    1. Saving the ransom note to the user’s desktop.

    2. Executing its cleanup routine by self-deleting and terminating.

Function Call Verification

By capturing binaries' function calls during dynamic execution, Defendable was able to verify the ransomware’s file encryption routine. Below is an extract from the runtime log that represents typical interactions with the Windows API during file encryption:

CreateFileW (lpFileName="C:\\Users\\8qy2SK\\Desktop\\7YTJ.docx", ...) returned 0x234

CreateFileW (lpFileName="C:\\wl_enc_2654692488.tmp", ...) returned 0x238

WriteFile (in: hFile=0x238, nNumberOfBytesToWrite=0x10, ...) returned 1

WriteFile (in: hFile=0x238, nNumberOfBytesToWrite=0x10, ...) returned 1

ReadFile (in: hFile=0x234, ...) returned 1 - lpNumberOfBytesRead=0xa6ff

WriteFile (in: hFile=0x238, nNumberOfBytesToWrite=0xa6ff, ...) returned 1

ReadFile (in: hFile=0x234, ...) returned 1 - lpNumberOfBytesRead=0x0

CloseHandle (hObject=0x238) returned 1

CloseHandle (hObject=0x234) returned 1

MoveFileExW (lpExistingFileName="C:\\wl_enc_2654692488.tmp",

lpNewFileName="C:\\Users\\8qy2SK\\Desktop\\7YTJ.docx.MadiLock", ...) returned 1

DeleteFileW (lpFileName="C:\\Users\\8qy2SK\\Desktop\\7YTJ.docx") returned 1

 

Breakdown of the Process:

  • Temporary File Creation: The malware creates a temporary file (C:\wl_enc_{random_number}.tmp) to store encrypted data.

  • Metadata Writes: It writes the 16-byte IV and the 16-byte XOR encoding stream to the temporary file.

  • File Encryption: The original file is read in chunks, encrypted with the AES CTR stream, and written to the temporary file.

  • Final Operations:

    • The temporary file is renamed with the same name as the original file but appending the .MadiLock extension (e.g., 7YTJ.docx.MadiLock).

    • The original file is marked for deletion via Windows API (DeleteFileW), leaving only the encrypted file.

This process is repeated for all files meeting the ransomware’s targeting criteria. 

Ransom Note Analysis

 
 Ransom note censored-20250924-112446-1
 
Ransom note created after execution, almost identical to ransom note seen from other sample.
 

The ransom note generated by MadiLock is nearly identical to the note in a sample seen on VirusTotal. The differences are limited to:

  • Identification ID: The ID includes:

    • The first four characters derived from the organization name.

    • A random four-digit number.

    • The constant value 926101 (potentially a version identifier or campaign-specific marker).

  • Ransom Amount: The Bitcoin payment value is configurable and varies between campaigns.

Aside from these small differences, the ransom note structure and wording are consistent across samples.

Lack of Network Activity and Additional Features

MadiLock appears to be purely designed for file encryption and ransom extortion. Defendable detected no network activity during execution and observed no evidence of backdoor creation, persistence mechanisms, or secondary payloads. Additionally, the malware does not employ any anti-analysis techniques or checks for sandbox environments, giving analysts full access to its runtime behavior without needing substantial evasive workarounds.

The lack of advanced features such as network communication or anti-analysis techniques indicates that MadiLock is primarily focused on ransomware functionalities. It does not aim to infiltrate systems for deeper access or prolonged control.

Conclusion

The MadiLock ransomware is a straightforward yet effective file encryptor. Its design prioritizes basic functionality, skipping over complex features like persistence mechanisms, network backdoors, or anti-analysis protections. Despite its simplicity, it executes its intended purpose—encrypting user-created files on a victim’s system—competently.

Strengths and Weaknesses

MadiLock’s file locator algorithm effectively identifies files for encryption across mounted disks, while skipping over files or directories that could create operational issues. Notably, it avoids targeting system-critical files, ensuring the infected system remains functional—an important aspect for ransom payment facilitation. However, skipping the user’s “Documents” folder seems like a major oversight, as this is often the repository for highly critical user files and data.

The file encryption routine uses runtime-generated 128-bit AES keys, which are then one-way encrypted with a hardcoded RSA public key. These encrypted "ransomware keys" are stored in the system registry and are intended to be used by the attacker’s decryptor. While the use of AES block cipher encryption ensures strong cryptographic security, the absence of centralized key management makes MadiLock unsuitable for mass distribution in networked environments. For example, in cases where multiple devices simultaneously encrypt shared files, it becomes impossible to determine which encryption key corresponds to which file—rendering some data potentially irrecoverable.

Potential for Forensic Recovery

A noteworthy characteristic of MadiLock is its file-handling mechanism during encryption. Rather than directly overwriting the original file, the ransomware creates a temporary file to store the encrypted data. This file is moved back to the original location and renamed with the addition of the .MadiLock extension. The original file is then deleted via the Windows API, which only "de-lists" the file from the file system's Master File Table (MFT) without immediately overwriting its underlying data.

While the process of creating temporary files increases the potential for system overwrites, the actual original file data may still remain intact on the disk until it is explicitly overwritten by the system. This creates a window of opportunity for forensic teams to recover data using disk recovery tools, provided that action is taken promptly and there is minimal additional system activity.

Simplistic Design

From a design perspective, MadiLock is focused exclusively on file encryption with no additional functionality:

  • No Backdoor or Remote Control: The malware does not attempt to establish persistence or allow attackers to access the system remotely.

  • No Packing or Anti-Analysis: The sample lacks packing, obfuscation, or anti-debugging mechanisms, making analysis straightforward. It also performs no environmental checks to avoid execution on virtual machines or sandboxed environments, leaving it exposed during dynamic analysis.

While these omissions simplify the malware’s creation, they also make it less sophisticated and easier to detect, analyze, and potentially mitigate.

 

Appendix A: IoC

VALUE

IOC TYPE

CONTEXT/DESCRIPTION 

 c0504174e7f6db086e9dbd882c97e16a

 MD5 hash

MadiLock sample

 cfeeec7f276e5f104fd0ef8ba599ed1e728997c6

 SHA1

 MadiLock sample

 29386d4aa666f59cc8da77c7ac524ffd913117a9f0d2c0176873bf7551b343a1

 SHA256

 MadiLock sample

C:\Users\Public\MadiLock1.txt

File path

MadiLock file log over files to encrypt. Number can increase by runs.

C:\wl_enc_{numbers}.tmp

File path

Temp files used to store encrypted files before moving.

.MadiLock

Extension

Encrypted files extension.

README_TO_RECOVER_FILES!!!.txt

File name

MadiLock Ransom Note. Custom for victim.

HKEY_LOCAL_MACHINE\Software\MadiLock\Machine

Registry path

Registry key that store the data used for encryption.

How fast and deliberate swiping gave us access to very sensitive data

How fast and deliberate swiping gave us access to very sensitive data

While testing for a customer, we discovered a 0-day exploit in VMware Workspace ONE Launcher which allowed us to access to all data on the device and...

Read More
Why vulnerability scanning is the foundation of all IT security

Why vulnerability scanning is the foundation of all IT security

IT systems and services that are exposed to the Internet are daily targets of attempted cyber-attacks. Technical vulnerabilities become public...

Read More
What will fill the information vacuum after the expulsion of Russian spies?

What will fill the information vacuum after the expulsion of Russian spies?

Recently, we have had the opportunity to learn a little about what Russian intelligence officers spend their days doing in Norway. Will the...

Read More