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...
19 min read
Aleksander Bjørkhaug Sep 25, 2025 2:22:29 PM
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.
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.
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.
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----- |
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 !!! ======================================================================================
====================================================================================== !!! WARNING !!! ======================================================================================
SAVE THIS INFORMATION:
After purchasing our decryptor:
======================================================================================
|
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.
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.
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.
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.
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).
![]() RTYPE ** call type, return RAX, RBX and RCX. |
![]() __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.
![]() Test of error value in RBX after a call. |
![]() 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:
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.
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.
When 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.
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.
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.
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:
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.
Exclusion List
Certain folders, files, and file types are explicitly skipped during the scan. Below is the exclusion list organized by type:
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
.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.
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.
Code block that gets 64 random bytes.
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.
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.
The malware then concatenates these encoded strings with a predefined delimiter (::_CALL_::
) to form the final key representation. For example:
OPU35Ww8nHSGNkHVFMoyBg==::_CALL_::a7eIbdePfLIw9rFwJWjGBw==
MadiLock_ciphers_EncryptWithPublicKey
)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.
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.
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.
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.
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.
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.
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.
Before encrypting the actual file data, the ransomware writes metadata related to the encryption stream to the temporary file:
The random IV (16 bytes), essential for recreating the encryption stream during decryption.
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.
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.
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:
The original file’s data is read in chunks and encrypted using the cipher stream.
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.
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
.
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."
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.
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:
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.
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.
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.
System Preparation: The malware performs checks on the affected system to optimize multi-threaded encryption operations.
Final Steps: The last logged action includes:
Saving the ransom note to the user’s desktop.
Executing its cleanup routine by self-deleting and terminating.
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
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.
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.
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.
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.
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.
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.
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.
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. |
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...
IT systems and services that are exposed to the Internet are daily targets of attempted cyber-attacks. Technical vulnerabilities become public...
Recently, we have had the opportunity to learn a little about what Russian intelligence officers spend their days doing in Norway. Will the...