Skip to navigation

Threat reportMalwareTL-2026-2782

North Korea-Linked XCTDH/OmniStealer Campaign Uses Ethereum Transactions (HashHiding) for Covert C2 Signaling

highACTIVE

DPRK-linked operators behind the Cross-Chain TxDataHiding (XCTDH) campaign encode the active C2 IPv4 address and port in the recipient address of ordinary Ethereum transfers ("HashHiding"), alongside TRON, Aptos and BNB Smart Chain layers that deliver encrypted JavaScript payloads. The DEV#POPPER.js Node.js RAT and the Python OmniStealer credential stealer are delivered to developers through fake job offers, trojanized GitHub repositories and npm packages on Windows, macOS and Linux.

Key facts

IdentifiersTL-2026-2782
Also known asXCTDH, Cross-Chain TxDataHiding, HashHiding, NullReceiver-style dead drop
SeverityHIGH
Affected productsVarious Developer workstations (Windows, macOS, Linux) running Node.js/npm and Python; Microsoft / Anysphere VSCode / Cursor IDE (targeted for persistence by DEV#POPPER.js)
AttributionContagious Interview (medium confidence)
Nation-state nexusNorth Korea
MalwareDEV#POPPER.js, OmniStealer, Python, _Z, telegram
MITRE ATT&CK techniquesT1027 Obfuscated Files or Information, T1056.001 Keylogging, T1059.006 Python, T1059.007 JavaScript, T1071.001 Web Protocols, T1102.001 Dead Drop Resolver, T1140 Deobfuscate/Decode Files or Information, T1195.001 Compromise Software Dependencies and Development Tools, T1204.002 Malicious File, T1219 Remote Access Tools, T1555.003 Credentials from Web Browsers, T1555.005 Password Managers and 3 more in the attack flow
MotivationFINANCIAL
Target sectorstechnology, software-development, cryptocurrency, finance
Target regionsGlobal
Detection rules9 (1 shown free)
Sources9 cited sources

Detection coverage

As of 2026-09-29, Threadlinqs Intelligence publishes 9 detection rule(s) for TL-2026-2782 across Splunk SPL, Microsoft KQL and Sigma, covering 23 indicator(s) of compromise. The whole corpus is readable without an account. Every threat comes with one complete detection in Splunk SPL, Microsoft KQL and Sigma, free for everyone; a free account adds daily TL Creds to unlock the rest. Paid plans add a larger daily allowance, correlation and the MCP server. Threadlinqs MCP server · View plans.

Free detection: XCTDH Loader — Node.js -eval With Campaign Markers (global.i / RS260605)

Detects the XCTDH/HashHiding loader stage: a Node.js process started with -eval (or -e) whose command line carries the campaign markers global.i='5-3-132', global.r=require or the _Z version marker /*RS260605*/. This is how the obfuscated JavaScript pulled from the TRON/Aptos/BSC chain or the C2 /init endpoint is executed on developer endpoints after a trojanized repo, npm package or poisoned config.js/tailwind.config.js is run.

  • Languages: Splunk SPL, Microsoft KQL, Sigma
  • ATT&CK: T1059.007, T1204.002, T1027, T1140
  • Data sources: sysmon, microsoft_defender_for_endpoint
  • Severity: critical
  • Confidence: high

Splunk SPL

index=sysmon sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1 (OriginalFileName="node.exe" OR Image="*node.exe" OR Image="*/node") (CommandLine="*-eval*" OR CommandLine="* -e *") (CommandLine="*global.i=*" OR CommandLine="*global.i =*" OR CommandLine="*global.r=require*" OR CommandLine="*5-3-132*" OR CommandLine="*RS260605*")
| stats count min(_time) as first_seen max(_time) as last_seen values(CommandLine) as command_lines values(ParentImage) as parents by host, User, Image
| convert ctime(first_seen) ctime(last_seen)

Microsoft KQL

DeviceProcessEvents
| where Timestamp > ago(24h)
| where FileName in~ ("node.exe", "node")
| where ProcessCommandLine has_any ("-eval", "--eval", " -e ")
| where ProcessCommandLine has_any ("global.i=", "global.i =", "global.r=require", "5-3-132", "RS260605")
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine

Sigma

title: XCTDH Loader - Node.js Eval With Campaign Markers
id: 6f1d3a52-8c4b-4e17-9a2d-5b7e0c31a901
status: experimental
description: Detects Node.js started with -eval/-e and command-line markers (global.i, global.r=require, 5-3-132, RS260605) used by the DPRK-linked XCTDH/HashHiding loader to run obfuscated JavaScript.
references:
  - https://ransom-isac.org/blog/xctdh-adopts-hash-hiding/
author: Threadlinqs Team
date: 2026-09-29
tags:
  - attack.execution
  - attack.t1059.007
  - attack.t1204.002
  - attack.defense-evasion
  - attack.t1027
  - attack.t1140
logsource:
  category: process_creation
  product: windows
detection:
  selection_img:
    Image|endswith: '\node.exe'
  selection_eval:
    CommandLine|contains:
      - '-eval'
      - ' -e '
  selection_marker:
    CommandLine|contains:
      - 'global.i='
      - 'global.i ='
      - 'global.r=require'
      - '5-3-132'
      - 'RS260605'
  condition: selection_img and selection_eval and selection_marker
falsepositives:
  - Developer scripts that legitimately define a global.i variable via node -e (rare; the marker strings make this unlikely)
level: high

Known false positives:

  • Developers running ad-hoc node -e one-liners that happen to set global.i (marker strings make collisions unlikely)

Tuning notes: Marker strings are campaign-version specific (5-3-132, RS260605); keep the -eval + global.r=require structure as the durable signal and refresh markers from new Ransom-ISAC reports. On macOS/Linux point the SPL at the EDR or Sysmon-for-Linux index; the KQL already covers non-Windows Defender devices.

8 more detection rules (Splunk SPL, Microsoft KQL, Sigma) · unlock with TL Creds. Sign up free to unlock the detection rules or query them with the Threadlinqs MCP server (Purple)
  • Trojanized npm Package Install or Direct Execution of Poisoned [indicator] / [indicator] · unlock with TL Creds
  • OmniStealer — Python Touching Browser/Wallet Stores Then Exfiltrating via Telegram Bot API · unlock with TL Creds
  • XCTDH C2 Infrastructure — Connections to HashHiding C2 IPs and Community-Related Sibling Infrastructure · unlock with TL Creds
  • XCTDH Dropper — Node.js Spawning Silent Python 3.13 Install or 7-Zip · unlock with TL Creds
  • XCTDH C2 HTTP Fingerprint — Python-urllib/3.13 UA With /init, /boot, /$/boot or /$/1 Paths · unlock with TL Creds
  • DEV#POPPER.js Clipboard Monitoring — Node.js Repeatedly Spawning Clipboard Utilities · unlock with TL Creds
  • DEV#POPPER.js Persistence — Node.js Writing VSCode/Cursor Settings or Extensions · unlock with TL Creds
  • Blockchain RPC Resolution From Node.js/Python — Ethereum/TRON/Aptos/BSC Dead Drop Lookups · unlock with TL Creds

Indicators of compromise

As of 2026-09-29, Threadlinqs Intelligence tracks 23 indicators of compromise for TL-2026-2782.

Sample indicators (3 of 23)

  • IP address: 23.27.20[.]143
  • IP address: 23.27.20[.]187
  • IP address: 181.214.149[.]147

Defanged, TLP:CLEAR. Full set of 23 indicators: unlock with TL Creds.

23 indicators of compromise · unlock with TL Creds. Compare plans

Community OSINT corroboration

2 of this threat's indicators have also been reported by the open-source security community, which observed at least one of them before this report was published. Community sightings are unverified and are kept separate from Threadlinqs' curated indicators. Indicator values, reporters and campaign linkage are available to authenticated Red-tier users.

Technical analysis

Ransom-ISAC ("XCTDH Adopts Hash Hiding", September 2026) documents a DPRK-linked campaign first described in October 2025 as Cross-Chain TxDataHiding (XCTDH). The operators added an Ethereum-based recovery channel called HashHiding. Instead of storing payloads in smart contracts or transaction calldata (EtherHiding / TxDataHiding), the attacker's signal wallet 0x33ff3edaf55a8e03dcbc7cb40d498a49cd499891 sends mostly zero-value transfers whose recipient (`to`) address carries six bytes of data: the first 4 bytes are an IPv4 address and the next 2 bytes the port; further bytes carry a second IP/port pair (80) and padding. Ransom-ISAC observed 2,655 such beacon transactions between 2026-06-23 15:21 UTC and 2026-09-21 21:25 UTC (about one every 49-51 minutes, mostly 0 wei, some 150 wei) and four C2 rotations: 23.27.20.187:80, 23.27.20.187:443, 181.214.149.147:443 and 181.214.149.148:443. Most transfers move no cryptocurrency; a few send a tiny amount to an address whose private key nobody is expected to control. The technique closely resembles the "NullReceiver" dead-drop resolver that OpenSourceMalware disclosed in August 2026 in trojanized npm packages (bianira-ui, fluid-type-ui), which was also linked to the DPRK Contagious Interview activity.

Delivery targets developers. Victims receive fake job offers (Telegram-based), then run a trojanized GitHub repository or npm package, or a poisoned configuration file (e.g. config.js, tailwind.config.js) in which obfuscated JavaScript is appended after whitespace padding. The loader queries TRON wallets for the latest transaction, decodes a reversed BNB Smart Chain (BSC) transaction hash from it, and fetches an XOR-encrypted payload from BSC calldata; Aptos serves as a fallback pointer. Three channels run unconditionally in parallel: a hardcoded C2 IP (181.214.149.148:443 in the September chain), the TRON/Aptos-to-BSC XCTDH chain, and HashHiding on Ethereum. The C2 /init endpoint (443) returns a ~303KB JSON blob with `_B` (the DEV#POPPER.js RAT) and `_Z` (the HashHiding scanner, 69,470 characters obfuscated with base-91 using 18 custom alphabets plus generator-based control-flow flattening). `_Z` scans Ethereum mainnet at exponentially growing block offsets through public RPC providers (publicnode.com, drpc.org, blastapi.io), looks for transfers from the signal wallet, decodes the recipient address, fetches /boot (443) to load boot.js, then re-fetches /init and evals the RAT. A parallel path via /$/boot (80, XOR-encrypted dropper that installs Python 3.13 and 7-Zip) and /$/1 (80, OmniStealer) delivers the stealer.

DEV#POPPER.js is a cross-platform Node.js RAT (grown from ~530 lines in October 2025 to ~2,500 in September 2026) with WebSocket C2, shell command execution, keylogging and clipboard monitoring, and it persists by injecting into VSCode/Cursor and spawning the `_Z` module in every child process. OmniStealer is a ~3,500-line Python stealer targeting 153 cryptocurrency wallet targets plus browsers, password managers and cloud-storage credentials on Windows, macOS and Linux; it runs once (fire-and-forget), packs loot into an AES-encrypted ZIP and exfiltrates via the Telegram bot API. Campaign markers: `global.i = '5-3-132'`, `/*RS260605*/` (`_Z` version), OmniStealer build `B9=260924`, Node.js requests spoofing `Python-urllib/3.13`, and a custom `Sec-V` header. Attribution to North Korea rests on overlap with the Contagious Interview / Famous Chollima activity and on infrastructure continuity (the same BSC address and XOR key as the October 2025 chain); the report does not establish a victim count. Google GTIG's earlier reporting on UNC5342 (October 2025) describes related DPRK use of EtherHiding on BSC, and lists 0x9bc1355344b54dedf3e44296916ed15653844509 as the owner address of its BSC contract, which is the same address Ransom-ISAC lists as the BSC payload sender here.

MITRE ATT&CK techniques by tactic:

Defense Evasion

T1027 Obfuscated Files or Information; T1140 Deobfuscate/Decode Files or Information

Collection

T1056.001 Keylogging; T1560.001 Archive via Utility

Execution

T1059.006 Python; T1059.007 JavaScript; T1204.002 Malicious File

Command and Control

T1071.001 Web Protocols; T1102.001 Dead Drop Resolver; T1219 Remote Access Tools

Initial Access

T1195.001 Compromise Software Dependencies and Development Tools; T1566.003 Spearphishing via Service

Credential Access

T1555.003 Credentials from Web Browsers; T1555.005 Password Managers

Exfiltration

T1567 Exfiltration Over Web Service

Remediation

Immediate actions

  • Block egress to 23.27.20.143, 23.27.20.187, 181.214.149.147 and 181.214.149.148 (ports 80/443/27017)
  • Hunt developer endpoints for Node.js processes started with -eval containing global.i= / global.r=require and for the strings '5-3-132', '/*RS260605*/' and 'B9=260924'
  • Alert on Node.js processes issuing JSON-RPC calls (eth_getBlockByNumber, eth_getTransactionByHash, eth_call) to Ethereum, TRON, Aptos or BSC RPC endpoints
  • If a host ran an untrusted repo or npm package from a job assessment, treat it as compromised: rotate browser, password-manager, cloud and wallet credentials and move crypto assets from a clean device

Workarounds

  • Inspect config files (config.js, tailwind.config.js) for long whitespace padding followed by appended JavaScript before running a repo
  • Review npm dependencies for the packages bianira-ui and fluid-type-ui

Longer-term hardening

  • Restrict direct access to public blockchain RPC endpoints from developer workstations and build systems, or route them through a proxy with logging
  • Run code from job assessments and unknown repositories only in disposable sandboxes or VMs
  • Audit VSCode/Cursor extension and settings changes on developer machines
  • Because removing a known C2 IP is not enough when malware reads new addresses from public blockchain records, monitor the signal wallet and BSC address for new transactions

Affected and fixed versions

  • Various — Developer workstations (Windows, macOS, Linux) running Node.js/npm and Python
    Vulnerable versions: Systems that execute trojanized GitHub repositories, npm packages or poisoned config files
  • Microsoft / Anysphere — VSCode / Cursor IDE (targeted for persistence by DEV#POPPER.js)
    Vulnerable versions: Not version-specific

Timeline

  • Google GTIG later reports that DPRK cluster UNC5342 began using EtherHiding on public blockchains around February 2025 (related Contagious Interview activity).
  • Ransom-ISAC first documents the Cross-Chain TxDataHiding (XCTDH) campaign, with a C2 at locked-ioc-10:27017 and a ~530-line DEV#POPPER.js RAT (exact day not stated; month per report).
  • Google GTIG publishes 'DPRK Adopts EtherHiding' describing UNC5342 use of BSC/Ethereum smart contracts, JADESNOW, BEAVERTAIL and INVISIBLEFERRET.
  • First HashHiding beacon from signal wallet 0x33ff3eda...9891 at 15:21 UTC, encoding locked-ioc-11:80.
  • Encoded destination changes to locked-ioc-11:443 (locked-ioc-3); it remains active until September 3.
  • Trojanized npm packages bianira-ui and fluid-type-ui, later tied by OpenSourceMalware to DPRK Contagious Interview and named NullReceiver, are first published.
  • OpenSourceMalware publicly discloses the NullReceiver technique (August 2026; exact day approximate), which encodes a C2 IP in the recipient address of an empty Ethereum transfer.
  • Encoded destination changes to locked-ioc-8:443 (locked-ioc-4).
  • Encoded destination changes to locked-ioc-9:443 (locked-ioc-5), the last of four observed C2 rotations.
  • End of Ransom-ISAC's 90-day collection window; last beacon at 21:25 UTC, 2,655 transactions in total.
  • OmniStealer build marker B9=260924 (September 24, 2026) seen in the delivered stealer.
  • Cyber Security News, GBHackers and Cyberpress publicize Ransom-ISAC's 'XCTDH Adopts Hash Hiding' findings.

Sources cited

More from Contagious Interview

Previous and next in malware

Drafted by the Threadlinqs research pipeline from 9 sources; published ; last updated —.

Threadlinqs Intelligence — Real-Time Threat Detection Platform

// threat_feed
$ sort --newest
Showing all threats

Live intelligence console

Threat level

Latest Threats