On June 16, 2025, a suspicious domain impersonating AnyDesk — anydeske[.]icu
— was reported on Twitter. The site served what appeared to be a legitimate remote access tool but actually delivered a malicious .NET loader. Further investigation revealed that the loader employed AES decryption, anti-analysis junk code, and evasion techniques to ultimately deliver Phemedrone Stealer

Attack Chain Overview
The attack chain leverages a multi-stage infection strategy starting from a deceptive website and ending with the deployment of the Phemedrone Stealer. Each phase of the chain incorporates layers of obfuscation, encryption, and defense evasion.

1. Initial Access
Victim is lured to
anydeske[.]icu
, a fake AnyDesk website.They download a file named
setup.exe
— a .NET loader, disguised as a legitimate installer.
2. Loader Execution & Obfuscation
Upon execution, the loader:
Runs silently with no GUI.
It immediately begins performing meaningless mathematical calculations and other junk code routines designed to delay execution and evade sandbox timeouts.
Expects a command-line argument containing an AES-encrypted URL of the next-stage payload).
Decrypts this url using a derived AES key and IV (via PBKDF2 and AES-CBC).
Downloads the actual payload (second stage) to the victim’s
%TEMP%
directory.
3. Defense Evasion
Before executing the payload, the loader:
Adds Defender exclusions using repeated PowerShell commands
These exclusions reduce the chance of detection when the final payload is written and executed.
4. Payload Delivery & Execution
The decrypted URL points to a remote payload (EXE)
The loader downloads the file to
%TEMP%
and runs it withProcess.Start()
.This file is identified as Phemedrone Stealer, a credential- and data-exfiltration malware.
Initial Vector: Fake AnyDesk Website
The infection chain begins with a malicious website impersonating AnyDesk, a popular remote desktop software. The domain anydeske[.]icu
was designed to deceive users into believing they were downloading a legitimate installer. Instead, the site served a .NET-based loader malware posing as the setup executable.

While the .NET loader
itself does not contain any hardcoded URLs or payload references, it includes logic to decrypt AES-encrypted data passed as a command-line argument. The malware derives a 256-bit AES key using Rfc2898DeriveBytes
(PBKDF2) and decrypts the input using AES-CBC.
Since the delivery site is currently offline, the original encrypted blob and decryption key are unavailable, but the structure of the code confirms the loader was designed to operate only when invoked with external encrypted data — an evasive technique to hide infrastructure from static analysis.
The loader is a lightweight .NET binary built to run quietly, decrypt external input, and execute its payload. Its structure is minimal but intentional: async entry, junk operations, and AES routines are all used to hide the actual behavior.
Hidden Control Flow via Async State Machine
The loader begins execution through a compiler-generated asynchronous state machine (Program.<Main>d__2
), a structure created by the C# compiler to handle async
methods. This technique allows the malware to execute tasks like downloading or sleeping without blocking the main thread, while also introducing obfuscation. The resulting control flow appears fragmented and cluttered, complicating static analysis and making the execution path less immediately clear to analysts.

Anti-Analysis and Obfuscation Techniques
The loader contains multiple methods designed to slow down analysis, evade detection, and waste time during sandbox execution. by simulating computation or generating useless code paths. These routines do not affect execution or payload delivery but serve to evade sandboxes and slow down debugging
GenerateJunkCodeFunction()
This method randomly constructs fake C-style function signatures and bodies using calls like GenerateRandomName()
and GenerateRandomNumber()
. The loop composes multiple randomized lines, including variable declarations, dummy arithmetic, conditions, loops, and return statements.
This logic isn’t compiled or executed.


PerformJunkCalculations()
This method performs a high-volume, floating-point math loop involving:
Math.Sin
Math.Cos
Math.Sqrt
The loop executes up to 10,000 iterations, depending on a random value. Every 1000 iterations, it reprocesses the calculation through a square root.

ExecuteObfuscatedOperations()
This is the central dispatcher for junk operations. It runs a loop for a specified number of seconds, calling one of several predefined methods in rotation. It also repeatedly invokes AddFoldersToDefenderExclusions()
to evade AV monitoring.
Rotates through
ObfuscatedOperation1()
toObfuscatedOperation6()
every few millisecondsAdds AV exclusions at random intervals
Sleeps for 10–50ms between calls to throttle behavior and prolong runtime

ObfuscatedOperation1()
to ObfuscatedOperation6()
methods are self-contained, meaningless logic intended to create system noise.
ObfuscatedOperation1()
This method allocates a 1KB buffer and fills it with random bytes using Random().NextBytes()
. It then creates a new AES encryption context with Aes.Create()
and generates a fresh encryption key and IV using aes.GenerateKey()
and aes.GenerateIV()
.

The buffer is encrypted using CreateEncryptor()
and TransformFinalBlock()
, and the result is discarded. The encrypted data has no functional use.

this routine simply exists to trigger cryptographic API usage, mimic “real” encryption activity and add complexity and delay for behavioral engines or sandboxes
ObfuscatedOperation2()
This routine generates a random alphanumeric string of 100 characters and computes its SHA256 hash using SHA256.Create()
followed by ComputeHash()
. The resulting hash is converted into a hexadecimal string using BitConverter.ToString()
and a Replace()
operation, but this output is never used. Like Operation1, the purpose is to invoke cryptographic functions

ObfuscatedOperation3()
This method performs repeated trigonometric calculations in a loop: for 1000 iterations, it computes the sum of Math.Sin(i) * Math.Cos(i)
divided by Math.Tan(i + 0.1) + 0.1
. The values are accumulated into a local variable and discarded.

ObfuscatedOperation4()
This operation constructs a large string using Base64-encoded GUIDs. It creates 100 GUIDs via Guid.NewGuid()
, converts each to a Base64 string, and appends them to a StringBuilder
. The resulting string is then mutated with character replacements (e.g., replacing A
with Z
, a
with z
). The final output string is not stored or used.

ObfuscatedOperation5()
This method performs temporary file I/O. It generates a temp file path using Path.GetTempFileName()
, writes a randomly generated 1000-character string into it using File.WriteAllText()
, reads it back using File.ReadAllText()
, and then deletes the file. It mimics the behavior of programs performing temp-file-based operations, but the data involved is meaningless.

Meaningless temp files created during execution:

ObfuscatedOperation6()
In this method, the loader generates a list of 1000 random integers between 0 and 9999 using Random().Next(10000)
. It then sorts the list, reverses it, and filters out all values that are divisible by 3 using a LINQ where
clause. The filtered list is stored locally and not used elsewhere. This method is a classic case of memory churn: it exercises list sorting, reversal, and filtering logic, all of which appear behaviorally legitimate but contribute nothing to the malware’s functionality.

Disabling Windows Defender via PowerShell
Next the loader disables Windows Defender’s scanning in specific system directories by adding them to Defender’s exclusion list. It begins by retrieving the path to the system’s CommonApplicationData directory (C:\ProgramData
) via Environment.GetFolderPath()
. The exclusion command is constructed in an intentionally obfuscated way: the string "Add-MpPreference"
is assembled character by character, and the argument "-ExclusionPath"
is also dynamically built using Convert.ToChar()
for each letter.

Once the components are constructed, the final PowerShell command is composed and Base64-encoded then decoded
The resulting PowerShell command is (after executing ExecutePowerShellCommand() method):
"powershell.exe" -Command "Add-MpPreference -ExclusionPath "C:\ProgramData""
Then the loader defines a hardcoded byte array (array3
) that also decodes to the same Add-MpPreference
command, but this time targeting the $env:TEMP
folder. This ensures the malware excludes both the ProgramData and TEMP directories from Defender scanning.


Like the previous command, the string is Base64-encoded/decoded before use.
The resulting PowerShell command is (after executing ExecutePowerShellCommand() method):
"powershell.exe" -Command "Add-MpPreference -ExclusionPath $env:TEMP"
At the end of the method, both commands are executed using an internal helper: Program.ExecutePowerShellCommand()
, which launches powershell.exe
with elevated permissions.
Privilege-Escalated, Silent Command Execution via PowerShell
Next it executes PowerShell commands on the victim system with elevated privileges.
It constructs a ProcessStartInfo
object configured to launch powershell.exe
with the provided command string passed via the -Command
argument with parameters:
CreateNoWindow = true
ensures that no PowerShell window appears on the screen.UseShellExecute = false
disables shell-level execution to allow for input/output redirection.RedirectStandardOutput
andRedirectStandardError
are enabled to capture any response (although not read in this case).Verb = "runas"
forces the process to run with administrator privileges, triggering UAC elevation if required.
Once the process is configured, it is started and allowed to run for up to 5 seconds via WaitForExit(5000)
.

This silently executes PowerShell commands with elevated privileges, primarily to add Defender exclusions, without showing a window or triggering visible output.
Payload URL Decryption
The loader implements a custom AES-CBC decryption routine to extract the actual payload URL from an externally supplied encrypted blob. This design choice moves sensitive infrastructure (download URLs) outside the binary, forcing analysts to obtain the original command-line arguments or staging source to reconstruct the full execution flow.

The method accepts two parameters:
encryptedData
: a byte array containing the encrypted content (URL).key
: a 32-byte AES key derived from the first 16 bytes ofencryptedData
The first 16 bytes of encryptedData
are extracted into a separate array and used as the AES IV. The remaining bytes are treated as ciphertext.
The AES key is generated using GenerateSecureKey()
method:

In the GenerateSecureKey()
method, the loader uses PBKDF2 via Rfc2898DeriveBytes
to derive a 256-bit AES key from a password. The key derivation process is based on three inputs:
Password: likely passed as a command-line argument or dynamically fetched (not present in the static binary).
Salt: the static string
"SaltValueForUrlDecryption"
is hardcoded in the sample.Iterations: 10,000 rounds of HMAC are used to slow down brute-force attempts.
The result is a 32-byte AES key suitable for AES-256 encryption, which is later used to decrypt the payload URL.
Payload Download, Validation, and Execution
Once the loader has decrypted the payload URL, it proceeds to download the next-stage binary (in this case, Phemedrone Stealer).
This phase is handled in three steps: downloading the binary from a remote location, validating that the file is executable, and launching it.
DownloadFileWithProgressAsync
is responsible for retrieving the payload from the remote server. It accepts two parameters: the URL to download from, and the full file path where the payload should be saved.

Before execution, the downloaded file is passed through ValidateDownloadedFile
method to avoid crashing or executing a corrupt payload. This method performs three main checks:
Existence Check – Verifies that the file exists at the specified path.
Size Check – Ensures the file is not empty (
Length > 0
).PE Header Check – Reads the first two bytes to confirm that they match the standard
MZ
signature of a valid Windows PE file.
If any check fails, the function returns false
and terminates execution.

Once the file passes validation, the loader executes it using Process.Start()
, with UseShellExecute = true
. This launches the binary in a separate process.

Conclusion
This campaign uses a malicious AnyDesk lookalike website to distribute a custom .NET loader designed to stealthily retrieve and execute the Phemedrone Stealer. The loader employs AES-encrypted arguments, PowerShell-based AV evasion, and a variety of junk and obfuscated operations to delay dynamic analysis and mislead reverse engineers.
Notably, the loader adds its working directory to Windows Defender exclusions, helping the second-stage payload persist without interference. The use of PBKDF2 key derivation with a hardcoded salt to decrypt the download URL indicates a moderate level of obfuscation, requiring knowledge of both the password and binary logic to retrieve the payload.
The final payload, Phemedrone Stealer, is delivered via Process.Start()
as an external executable, completing a simple yet effective infection chain.
IOCs
.Net loader:
- b1edc65392305bb7062c86930baae32ead04731e9dbd806ab6a5c382e9e52e3f
Phemedrone Stealer:
- 29c5fe838dbcf78b8e6c77c60cd8a2e6c19515b6cd986e11d3b3e4af5fe61c73
AnyDesk Clone Domain:
- anydeske[.]icu
Contacted IP Addresses:
- 45.145.7[.]134
- 216.74.123[.]49:50643
Contacted URLs:
- https://pastebin[.]com/raw/YwvHhwUk
- https://pastebin[.]com/raw/WrgrtxSu
- http://45.145.7[.]134/hook/upgrade.php
- http://45.145.7[.]134/ups/Snup.bat
MITRE ATT&CK
Initial Access
- User Execution: Malicious File – [T1204.002]
Execution
- Command and Scripting Interpreter: PowerShell – [T1059.001]
Defense Evasion
- Obfuscated Files or Information – [T1027]
- Modify System Configuration: Windows Defender Exclusions – [T1562.001]
- Signed Binary Proxy Execution: PowerShell – [T1216.001]
- Deobfuscate/Decode Files or Information – [T1140]
- Command-Line Interface with Encrypted Parameters – [T1059.003]